JS 变量、作用域

变量

 

JS中的变量是松散类型的,可以存储任何类型的数据。

JS变量松散类型的本质,决定了变量只是在特定时间用于保存特定值的一个名字而已。

由于不存在定义某个变量必须要保存何种数据类型的值的规则,变量的值及其数据类型可以在脚本的生命周期内改变。

用var关键字声明的变量,未经初始化时,保存的是一个特殊的值——undefined。

变量初始化仅仅是给变量赋一个值。

可以在一条语句中声明多个变量,初始化或不初始化皆可,变量之间用逗号隔开。

用var关键字声明的变量是定义该变量的作用域中的局部变量。

 

JS中的变量可以保存两种不同类型的值:基本类型值和引用类型值。

在将一个值赋给变量时,解析器必须确定这个值是基本类型值还是引用类型值。

基本数据类型:Number、String、Boolean、Null、Undefiend;

这5种基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值。

对于基本类型的值,在复制变量的时候,会在新的变量上创建一个新值,这个新值是原值的一个副本,它们相互独立。

基本类型值之间的比较,只是单纯的值的比较。

 

引用类型值是保存在变量中的对象。

引用类型值就是指对象。

对于引用类型值,可以为其添加属性和方法,也可以改变和删除其属性和方法。

保存引用类型值的变量,实际上保存的是一个指向该对象的指针。

当复制保存着对象的某个变量时,复制的其实是指针;复制操作结束后,两个变量指向同一个对象。

在为对象添加属性和方法时,操作的是实际的对象,因此,改变任何一个变量,都会影响另外一个变量。

引用类型值的比较并非值的比较:即使两个对象包含相同的属性和值,它们也是不相等的;各个索引元素完全相等的两个数组也不相等。 

引用类型值的比较是引用的比较,当且仅当它们引用同一个对象时,它们才相等。

 

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

把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。

访问变量有按值和按引用两种方式,而参数只能按值传递。

在向参数传递基本类型值时,被传递的值会被复制给一个局部变量(即命名参数,即arguments对象中的一个元素)。

在向参数传递引用类型值时,会把这个值在内存中的地址复制给局部变量,因此这个局部变量的变化会反应在函数的外部。 

 

typeof操作符

typeof操作符是确定一个变量是字符串、数值、布尔值,还是undefined的最佳工具;如果变量的值是一个对象或者null,则都会返回object。

在使用typeof操作符检测函数时,该操作符会返回function。

 

instanceof 操作符

result = variable instanceof constructor

如果变量是给定引用类型的实例,那么instanceof操作符就会返回true;

根据规定,所有引用类型的值都是Object的实例,因此,在检测一个引用类型的值和Object构造函数时,instanceof操作符会始终返回true。

 

 

作用域

 

执行环境

执行环境,定义了变量或函数有权访问的其它数据,决定了它们各自的行为。

每个执行环境都有一个与之相对应的变量对象,环境中定义的所有变量和函数都保存在这个对象中。

 

全局环境是最外围的一个执行环境,在Web浏览器中,全局执行环境被认为是window对象,因此,所有全局变量和函数都是作为window对象的属性和方法创建的。

 

每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境会被推入一个环境栈中;而在环境执行之后,栈将其环境弹出,将控制权返回给之前的执行环境。

 

作用域链

当代码在一个环境中运行时,会创建变量对象的一个作用域链,保证对执行环境有权访问的所有变量和函数的有序访问;也就是说,每次进入一个新的执行环境,都会创建一个作用域链,用于搜索变量和函数。

 

作用域链的前端,始终都是当前执行的代码所在环境的变量对象;如果这个变量是函数,则将其活动对象作为变量对象;活动对象在一开始只包含一个变量,即arguments对象;作用域链中的下一个变量对象来自外部环境,而再下一个变量对象则来自再下一个外部环境,这样一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链的最后一个对象。

 

标识符解析是沿着作用域链一级一级地搜索标识符的过程,搜索过程始终都是从作用域链的前端开始,然后逐级向上,直到找到标识符为止。

 

局部环境可以通过作用域链访问外部环境中所有的变量和函数;但是外部环境不能访问局部环境中的任何数据;环境之间的联系是线性的,有次序的。

 

延长作用域链:try-catch语句中的catch块;with语句。

 

词法作用域

函数之间的嵌套关系是函数定义时就决定的,而非调用时决定的。

函数内无论什么位置声明的变量或函数,在进入函数时,由于声明提升的原因,都是已经声明的,但未初始化。

 

没有块级作用域

在其他类C语言中,由花括号封闭的代码都有自己的作用域(执行环境);

但在JS中,if语句、for语句等,它们中的变量声明会将变量添加到当前的执行环境。

在JS中,函数是唯一拥有作用域的。

 

使用var声明的变量会被添加到最接近的环境中;如果初始化变量时没有使用var声明,该变量会被自动添加到全局环境中。

 

查询标识符

搜索标识符,首先从作用域链的前端开始,向上逐级查找与给定名字匹配的标识符;只要找到了该标识符,搜索停止,变量就绪。

因此,如果在局部环境中定义了一个和外部环境同名的变量,搜索时首先会搜索到局部环境中的变量,并使用这个变量,外部环境中的变量会被忽略。

例子:

var color = "blue";

function Color() {

    var color = "red";

    return color;

};

alert(Color());    //"red"

posted @ 2016-07-26 15:49  Aaron_Xiao  阅读(177)  评论(0)    收藏  举报