第四章 变量 作用域和内存问题

4.1变量

变量包含2种类型的值:

基本类型的值: 即undefined,null, string,number,boolean.   按值访问,可以操作保存在变量中实际的值, 不能添加属性。

var name = "Nicholas";
name.age = 27;
console.log(name.age);
//undefined

引用类型的值:多个值构成的对象。JS不允许直接操作对象的内存空间。给一个对象添加属性,是在实际的对象中添加。

 

俩种类型值的区别: 

1.保存方式不同: 基本类型保存在对象空间中。引用类型保存在内存中。 

2.复制变量值时:基本类型 从一个变量复制到另外一个变量,变量创建一个副本,然后把值复制给新变量。

                          引用类型 复制值的一个指针,存储在新变量中,实际引用的是同一个对象。

var obj1 = new Object();
var obj2 = obj1;
obj1.name = "Nicholas";
console.log(obj1);
console.log(obj2);

//Object {name: "Nicholas"}
//Object {name: "Nicholas"}

传递参数

JS中所有函数的参数都是按值传递的。

基本类型的值从一个变量复制到另一个变量,实际是值被复制了俩份。

function addTen (num) {
   num +=10;
   return num;
 }
var count = 20;
var rezult = addTen(count);
console.log(rezult);
console.log(count);
// 30  rezult保存的值 被当做参数传递进addTen进行了+10;再返回
// 20  count在外部,没有受到+10的影响,所以返回20.俩个值互相独立,互不影响。

而参数是对象(对象是引用类型的一种)时,也是按值传递。

function setName (obj) {
   obj.name = "Nicholas";
   obj = new Object();
   obj.name = "Gray";
  }
var person = new Object();
setName(person);
console.log(person.name);
// Nicholas  即使再函数内部修改了参数的值,原始的引用仍然保持不变。
// 再函数内部重写obj时,这个变量引用的是一个局部对象,这个局部对象会在函数执行完毕后立即被销毁。

检测类型

instanceof:  变量是给定类型的实例返回true.

function setName (obj) {
   obj.name = "Nicholas";
  }
var person = new Object();
setName(person);

console.log(person instanceof Object);
//true person是Object的实例

执行环境及作用域

执行环境:       定义变量或函数有权访问的其他数据,决定他们各自的行为。执行环境中的代码执行完毕后,该环境被销毁,变量和函数也被销毁。

变量对象:       每个执行环境有一个变量对象。环境中定义的所有变量和函数都保存再这个对象中。

全局执行环境: 最外围的一个执行环境,也被认为是window对象。所有全局变量和函数都是作为window对象的属性和方法创建的。

作用域链:       函数有自己的执行环境。代码在一个环境中执行时,会创建变量对象的一个作用域链。用途是搜索变量和函数。作用域链的前端始终都是当前执行代码所在环境的变量对象。

 

var color = "blue";
function changeColor() {
    if(color === "blue") {
        color = "red";
      } else {
          color = "blue";
        }
     }
changeColor();
console.log("Color is now " + color);           
// Color is now red

函数changeColor的作用域链包含2个对象,它自己的变量对象(arguments对象)和全局变量对象(color)。

var color = "blue";
 
function changeColor() {
   var anotherColor = "red";
   
   function swapColors() {
    var tempColor = anotherColor;
    anotherColor = color;
    color = tempColor;
    }
}

内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境的变量和函数。

没有块级作用域

再JS中,if语句中变量声明会将变量添加到当前的执行环境。

if(true) {
  color = "red";
}
console.log(color);
//red

for语句创建的变量i既然再for循环执行结束后,依旧存在循环外部的执行环境中。

for(var i=0; i <10; i++) {
        i++;
    }
console.log(i);
//10

查询标识符

查询标识符从作用域最前端开始,向上逐级查找与给定名字匹配的标识符。找到为止,没有找到意味着该变量未声明。

var color = "blue";

function getColor() {
    return color;                //首先在getcolor函数里寻找color标识符,未找到
                                 //接着向上查找,包裹getColor的是全局执行环境,最后在全局执行环境中到了,,并立即返回
  } 

console.log(getColor());
// blue

 如果存在同名标识符,局部变量优先级最高。

var color = "blue";

function getColor() {
    var color = "red";      //局部变量覆盖了全局变量
    return color; 

  }

console.log(getColor());
//red
原文地址:https://www.cnblogs.com/zhangbaihua/p/5557110.html