变量,作用域和内存问题
一,变量分为两种类型:基本类型值和引用类型值,基本类型包括:Undefined, String, Boolean, Null, Number,我们无法给基本类型值添加属性;
二,复制变量值的时候,如果改变复制的值,那么原来的值是否会变化?
这个取决于原来的值是什么类型:
1.基本类型值:只是存在于栈内存中,如果复制,相当于栈内存里又多了一个值,两者相互独立,改变其中一个,另一个不变
2.引用类型值:实际上是指向堆内存中的一个object,复制相当于多了一个指针,也是指向这个object,改变其中一个,所指的这个object也发生改变(注意,这个object不是整个大的Object对象,而只是其中的一小个),那么所有指向该object的值全部发生变化。
三,传递参数的时候,如果参数在局部作用域下发生变化,那么参数会变化吗?
js中,所有的参数传递都是按值传递,不管是基本类型还是引用类型。不同的类型下不同的讨论方式:
1.基本类型值:将参数传递给函数执行,实际上就是复制了一个值,给了函数,即基本类型值的复制,局部作用域怎么变化,原值都不会变。
2.引用类型值:将引用类型值作为参数传递给函数,实际上相当于把这个值在内存中的地址作为一个值传递给了函数,那么此时在函数里改变这个复制的地址,原来的值一定会发生改变,因为两个值指向的是同一个地址,但是如果此时在函数内部再声明一个新的引用类型值,name一样,此时这个指向的object和刚刚那两个指向的就不一样了,再次修改这个值,原来的相同name的值不会发生改变了,因为它是按值传递的。改变函数内部的参数值,外部参数也会发生改变,看起来好像是按引用传递,实际上却不是,只是因为二者引用的是同一个object,因为类型是引用类型。
附上一堆代码:
function setName(obj){
obj.name="ABC";
obj=new Object();
obj.name="BCD";
}
var person=new Object();
setName(person);
alert(person.name);// ABC
四,执行环境以及作用域的问题:
执行环境定义了变量或函数有权访问的其他数据(这里的变量或函数可能是外部环境的,也可能是当前执行环境的)。每个执行环境有一个对应的变量对象,这里面存储了在该环境下定义的所有变量和函数。执行环境中所有的代码执行完毕后,当前环境就会销毁,全局执行环境直到应用程序退出时才会销毁。
每个函数都有自己的执行环境,执行流进入一个函数时,函数当前的执行环境被推入环境栈中,此时控制权就由原来的执行环境而移交给当前执行环境下,当函数执行完毕后,栈就会将这个环境推出,控制权也重新回到原来的执行环境下。每一个正在执行的环境都放在环境栈里面。ECMAScript的执行流就是这个机制。
当代码在一个环境中执行的时候,就会创建一个变量对象的作用域链,这个作用域链的用途是保证对所有能够在当前执行环境下有权访问的变量或函数的有序访问。(换句话说,在当前执行环境下,有哪些变量或函数是可以访问的,我通过作用域链就可以查到,而且是有序的查找,所以我认为其实作用域链就是变量对象的排序,也不能这么说,因为当前执行环境下有权访问的变量或函数也未必全都是当前环境下定义的变量和函数,也有可能是外部进来的)。这个作用域链的前端,是当前执行环境的变量对象。如果这个执行环境是函数,则将其活动对象作为变量对象。活动对象起初只有一个变量,就是arguments对象(全局环境中没有的)。作用域链上,从前端开始往后,下一个变量对象就是当前执行环境外的环境下的变量对象,再下一个就是再外一层环境的变量对象,(这个环境一层层的,就是执行流依次经过的环境,只不过是倒过来,从前往后的,从里到外),一直到最外层的全局执行环境:全局执行环境的变量对象一定是作用域链的最后一个对象。
标识符的解析就是沿着作用域链从前往后找的。
作用域链本质上是一个指向变量对象的指针列表,他只引用但不实际包含变量对象。
——节选自闭包一节。