作用域是JavaScript最重要的概念之一,想要学好JavaScript就需要理解JavaScript作用域和作用域链的工作原理。
1 作用域
作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。
1.1 变量的作用域
在JavaScript中,变量的作用域有全局作用域和局部作用域两种。
全局作用域(Global Scope):
在代码中任何地方都能访问到的对象拥有全局作用域,一般来说以下几种情形拥有全局作用域:
1) 最外层函数和在最外层函数外面定义的变量拥有全局作用域
2) 所有末定义直接赋值的变量自动声明为拥有全局作用域
3) 所有window对象的属性拥有全局作用域
局部作用域(Local Scope):
和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部,所以这种作用域也称为函数作用域。
样例
var message = "Hello"; //全局作用域
function sayHi(){
console.log(message);
var myName = "Castiel_Z"; //局部作用域
content = "Hello ReactNative"; //全局作用域
}
1.2 函数作用域
ECMAScript 中只存在一种作用域 - 公用作用域。ECMAScript 中的所有对象的所有属性和方法都是公用的。因此,定义自己的类和对象时,必须格外小心。记住,所有属性和方法默认都是公用的.
由于缺少私有作用域,开发者确定了一个规约,说明哪些属性和方法应该被看做私有的。这种规约规定在属性前后加下划线:
obj._color_ = "blue"; // 注意,下划线并不改变属性是公用属性的事实,只是规约
1.3 关键字 this
键字 this 总是指向调用该方法的对象,例如:
在五种不同的情况下 ,this指向的各不相同
1) 全局范围内
this;
当在全部范围内使用this,它将会指向全局对象。
注:浏览器中运行的 JavaScript 脚本,这个全局对象是window。
2) 函数调用
foo();
这里this也会指向全局对象。
注:在严格模式下(strict mode),不存在全局变量。这种情况下this将会是undefined。
3) 方法调用
test.foo();
这个例子中,this指向test对象。
4) 调用构造函数
new foo();
5) 显示设置的this
function foo(a, b, c) {}
var bar = {};
foo.apply(bar, [1, 2, 3]); // 数组将会被扩展,如下所示
foo.call(bar, 1, 2, 3); // 传递到foo的参数是:a = 1, b = 2, c = 3
当使用 Function.prototype 上的 call 或者 apply 方法时,函数内的 this 将会被 显式设置为函数调用的第一个参数。 因此函数调用的规则在上例中已经不适用了,在foo 函数内 this 被设置成了 bar
2 作用域链(Scope Chain)
在JavaScript中,函数也是对象,实际上,JavaScript里一切都是对象。函数对象和其它对象一样,拥有可以通过代码访问的属性和一系列仅供JavaScript引擎访问的内部属性。其中一个内部属性是[[Scope]],由ECMA-262标准第三版定义,该内部属性包含了函数被创建的作用域中对象的集合,这个集合被称为函数的作用域链,它决定了哪些数据能被函数访问。
特点:"链式作用域"结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
先简单理解下特点就行了 ^-^!。想深入了解的进参考中的博客。