>웹 프론트엔드 >JS 튜토리얼 >JavaScript 변수, 범위 및 memory_javascript 팁

JavaScript 변수, 범위 및 memory_javascript 팁

WBOY
WBOY원래의
2016-05-16 16:05:101012검색

JS 변수의 특성은 느슨한 유형(강제 유형 없음)이므로 특정 시간에 특정 값을 저장하는 데 사용되는 이름일 뿐이라고 판단합니다.
변수가 보유해야 하는 데이터 유형을 정의하는 규칙이 없으므로 변수의 값과 해당 데이터 유형은 스크립트 수명 주기 동안 변경될 수 있습니다.

1개의 변수 및 범위
1.기본 유형 및 참조 유형

//JS 변수에는 기본 유형 값과 참조 유형 값이라는 두 가지 다른 데이터 유형의 값이 포함됩니다.

// 1. 기본 유형 값: 스택 메모리에 저장된 단순 데이터 세그먼트, 즉 이 값은 메모리의 한 위치에 완전히 저장됩니다. // 기본 유형 값에는 다음이 포함됩니다: Undefine|Null|Boolean|Number|String;
// 이러한 유형은 메모리에서 고정된 크기의 공간을 차지합니다. 해당 값은 스택 공간에 저장되며 값으로 액세스합니다.

// 2. 참조 유형 값: 힙 메모리에 저장된 객체(여러 값으로 구성될 수 있음), 즉 변수에 저장되는 것은 실제로 메모리의 다른 위치를 가리키는 포인터일 뿐입니다. . 개체 저장;

// 참조 타입 값의 크기는 고정되어 있지 않으므로 스택 메모리에 저장할 수 없고 힙 메모리에 저장해야 하지만 참조 타입 값의 메모리 주소는 스택 메모리에 저장할 수 있습니다. > // 참조형 변수를 질의할 때 먼저 스택 메모리에서 메모리 주소를 읽어온 후 주소;=>Access by reference;
를 통해 힙 메모리에 있는 값을 찾습니다.

2.동적 속성


// 定义基本类型值和引用类型值的方式相似:创建一个变量并为该变量赋值;
// 但当这个值保存到变量中以后,对不同类型值可以执行的操作则不一样;
  var box = new Object();           // 创建引用类型;
  box.name = 'lee';              // 新增一个属性;
  console.log(box.name);           // =>lee;

  var box = 'lee';              // 创建基本类型
  box.age = 15;                // 给基本类型添加属性;
  console.log(box.age);            // =>undefined;
3. 변수값 복사


// 在变量复制方面,基本类型和引用类型也有所不同;
// 基本类型赋值的是值本身;
  var box = 'lee';              // 在栈内存中生成一个box'lee';
  var box2 = box;               // 在栈内存中再生成一个box2'lee';
  // box和box2完全独立;两个变量分别操作时互不影响;

// 引用类型赋值的是地址;
  var box = new Object();          // 创建一个引用类型;box在栈内存中;而Object在堆内存中;
  box.name = 'lee';             // 新增一个属性;
  var box2 = box;              // 把引用地址赋值给box2;box2在栈内存中;
  // box2=box,因为它们指向的是同一个对象;
  // 如果这个对象中的name属性被修改了,box.name和box2.name输出的值都会被修改掉;
4. 매개변수 전달


// JS中所有函数的参数都是按值传递的,即参数不会按引用传递;
  function box(num){             // 按值传递,传递的参数是基本类型;
    num +=10;               // 这里的num是局部变量,全局无效;
    return num;
  }
  var num = 50;
  var result = box(num);
  console.log(result);           // 60;
  console.log(num);             // 50;

  function box(num){
    return num;
  }
  console.log(num);             // num is not defined;

  function box(obj){
    obj.name = 'lee';
    var obj = new Object();       // 函数内部又创建了一个对象,它是局部变量;但在函数结束时被销毁了;
    obj.name = 'Mr';           // 并没有替换掉原来的obj;
  }
  var p = new Object();
  box(p);                 // 变量p被传递到box()函数中之后就被复制给了obj;在函数内部,obj和p访问的是同一个对象;
  console.log(p.name);           // =>lee;

  // JS函数的参数都将是局部变量;也就是说,没有按引用传递;
5. 감지 유형


// 要检测一个变量的类型,通过typeof运算符类判断;
// 多用来检测基本类型;
  var box = 'lee';
  console.log(typeof box);          // =>string;

// 要检测变量是什么类型的对象,通过instanceof运算符来查看;
  var box = [1,2,3];
  console.log(box instanceof Array);     // =>true;
  var box2 = {};
  console.log(box2 instanceof Object);
  var box3 = /g/;
  console.lgo(box3 instanceof RegExp);
  var box4 = new String('lee');
  console.log(box4 instanceof String);   // =>true;是否是字符串对象;

  var box5 = 'string';
  console.log(box5 instanceof String);   // =>false;
  // 当使用instanceof检查基本类型的值时,它会返回false;
6. 실행 환경 및 범위


// 执行环境:定义了变量或函数有权访问的其他数据,决定了它们各自的行为;
// 在Web浏览器中,全局执行环境=window对象;
// 因此所有的全局变量和函数都是作为window对象的属性和方法创建的;
  var box = 'blue';             // 声明一个全局变量;
  function setBox(){
    console.log(box);           // 全局变量可以在函数里访问;
  }  
  setBox();                 // 执行函数;
  // 全局的变量=window对象的属性;
  // 全局的函数=window对象的方法;

// PS:当执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁;
// 如果是在全局环境下,需要程序执行完毕,或者网页被关闭才会销毁;

// PS:每个执行环境都有一个与之关联的变量对象,就好比全局的window可以调用全局变量和全局方法一样;
// 局部的环境也有一个类似window的变量对象,环境中定义的所有变量和函数都保存在这个对象中;
// (我们无法访问这个变量对象,但解析器会处理数据时后台使用它);
  var box = 'blue';
  function setBox(){
    var box = 'red';           // 这里是局部变量,在当前函数体内的值是'red';出了函数体就不被认知;
    console.log(box);
  }  
  setBox();
  console.log(box);

// 通过传参可以替换函数体内的局部变量,但作用域仅限在函数体内这个局部环境;
  var box = 'blue';
  function setBox(box){           // 通过传参,将局部变量替换成了全局变量;
    alert(box);              // 此时box的值是外部调用时传入的参数;=>red;
  }
  setBox('red');
  alert(box);

// 如果函数体内还包含着函数,只有这个内函数才可以访问外一层的函数的变量;
// 内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数;
  var box = 'blue';
  function setBox(){
    function setColor(){
      var b = 'orange';
      alert(box);
      alert(b);
    }
    setColor();              // setColor()的执行环境在setBox()内;
  }
  setBox();
  // PS:每个函数被调用时都会创建自己的执行环境;当执行到这个函数时,函数的环境就会被推到环境栈中去执行,而执行后又在环境栈中弹出(退出),把控制权交给上一级的执行环境;

  // PS:当代码在一个环境中执行时,就会形成一种叫做作用域链的东西;它的用途是保证对执行环境中有访问权限的变量和函数进行有序访问;作用域链的前端,就是执行环境的变量对象;
7.스코프 체인 확장


// 有些语句可以在作用域链的前端临时增加一个变量对象,该变量对象会在代码执行后被移除;
// with语句和try-catch语句;这两个语句都会在作用域链的前端添加一个变量对象;
// with语句:会将指定的对象添加到作用域链中; 
// catch语句:会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明;
  function buildUrl(){
    var qs = '?debug=true';
    with(location){            // with语句接收的是location对象,因此变量对象中就包含了location对象的所有属性和方法;
      var url = href+qs;        // 而这个变量对象被添加到了作用域链的前端;
    };
    return url;
  }
8. 블록 수준 범위 없음


// 块级作用域:表示诸如if语句等有花括号封闭的代码块,所以,支持条件判断来定义变量;
  if(true){                 // if语句代码块没有局部作用域;
    var box = 'lee';           // 变量声明会将变量添加到当前的执行环境(在这里是全局环境);
  }
  alert(box);

  for(var i=0; i<10; i++){         // 创建的变量i即使在for循环执行结束后,也依旧会存在与循环外部的执行环境中;
    var box = 'lee';
  }
  alert(i);
  alert(box);

  function box(num1,num2){
    var sum = num1+num2;         // 此时sum是局部变量;如果去掉var,sum就是全局变量了;
    return sum;
  }
  alert(box(10,10));
  alert(sum);                // sum is not defined;访问不到sum;
  // PS:不建议不使用var就初始化变量,因为这种方法会导致各种意外发生;

// 一般确定变量都是通过搜索来确定该标识符实际代表什么;搜索方式:向上逐级查询;
  var box = 'blue';
  function getBox(){
    return box;              // 此时box是全局变量;如果是var box='red',那就变成局部变量了;
  }
  alert(getBox());              
  // 调用getBox()时会引用变量box;
  // 首先,搜索getBox()的变量对象,查找名为box的标识符;
  // 然后,搜索继续下一个变量对象(全局环境的变量对象),找到了box标识符;
// PS:变量查询中,访问局部变量要比全局变量更快,因为不需要向上搜索作用域链;
2 메모리 문제


// JS具有自动垃圾收集机制,执行环境会负责管理代码执行过程中使用的内存;它会自行管理内存分配及无用内存的回收;

// JS最常用的垃圾收集方式就是标记清除;垃圾收集器会在运行的时候给存储在内存中的变量加上标记;
// 然后,它会去掉环境中正在使用的变量的标记,而没有被去掉标记的变量将被视为准备删除的变量;
// 最后,垃圾收集器完成内存清理工作,销毁那些标记的值并回收他们所占用的内存空间;

// 垃圾收集器是周期性运行的,这样会导致整个程序的性能问题;
// 比如IE7以前的版本,他的垃圾收集器是根据内存分配量运行的,比如256个变量就开始运行垃圾收集器,这样就不得不频繁地运行,从而降低了性能;

// 一般来说,确保占用最少的内存可以让页面获得更好的性能;
// 最佳方案:一旦数据不再使用,将其值设置为null来释放引用,这个做法叫做解除引用;
  var o = {
    name:'lee';
  };
  o = null;               // 解除对象引用,等待垃圾收集器回收;
3개 요약


1. 변수

// JS 변수는 기본 유형 값과 참조 유형 값 두 가지 유형의 값을 저장할 수 있습니다.

// 1. 기본 타입 값은 메모리에서 고정된 크기의 공간을 차지하므로 스택 메모리에 저장됩니다.
// 2. 한 변수에서 다른 변수로 기본 유형 값을 복사하면 이 값의 복사본이 생성됩니다.
// 3. 참조 유형의 값은 객체이며 힙 메모리에 저장됩니다.
// 4. 참조 유형 값을 포함하는 변수는 실제로 객체 자체를 포함하지 않지만 객체에 대한 포인터를 포함합니다.
// 5. 한 변수에서 다른 변수로 참조 유형 값을 복사합니다. 복사된 내용은 실제로 포인터이므로 두 변수 모두 결국 개체를 가리킵니다. // 6. 값이 어떤 기본 유형인지 확인하려면 typeof 연산자를 사용하고, 값이 어떤 참조 유형인지 확인하려면
연산자를 사용하세요.
2. 범위
// 모든 변수는 실행 환경(범위)에 존재합니다. 이 실행 환경은 변수의 수명 주기와 변수에 액세스할 수 있는 코드 부분을 결정합니다. // 1. 실행 환경은 전역 실행 환경과 함수 실행 환경으로 구분됩니다.

// 2. 새로운 실행 환경에 진입할 때마다 변수 및 함수 검색을 위한 스코프 체인이 생성됩니다.

// 3. 함수의 로컬 환경은 함수 범위의 변수에 액세스할 수 있는 권한뿐만 아니라 상위 환경 및 전역 환경에도 액세스할 수 있는 권한을 갖습니다.
// 4. 변수의 실행 환경은 메모리를 적절하게 해제해야 하는지 결정하는 데 도움이 됩니다.

3. 추억
// JS 자동 가비지 수집 메커니즘
// 1. 범위를 벗어나는 값은 자동으로 재활용 가능으로 표시되므로 가비지 수집 중에 삭제됩니다.

// 2. 효과적인 메모리 재활용을 위해서는 더 이상 사용되지 않는 전역 객체/전역 객체 속성 및 순환 참조 변수를 적시에 해제해야 합니다.

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.