作用域
作用域即片段的有效范围,这里的片段可以是、变量等。
在 JavaScript 中,通常被拿来讨论的是 全局作用域
和 作用域
。
在全局环境下定义的变量、,都属于全局作用域的范围,也就是这些变量、在任何地方都能被访问。
var number = ;
var fn = function() {
console.log('我是全局下的');
console.log('访问全局下的 number: ', number);
};
fn();
全局的作用域很好理解,即全局下的变量、在任何地方都能被访问到。
在 ES6 的模块化规范中,模块就是 js ,所以如果在 ES6 的模块的最顶层声明变量和,是不属于全局的。
拥有自己的作用域,也就是说内声明的变量和,只在内有效。
var fn = function() {
var innerFn = function() {
console.log('我是内的');
};
var str = '我是内的变量';
innerFn();
console.log(str);
};
fn();
console.log(str); // :ReferenceError: str is not defined
内的变量 str
在外部无法访问到,因为其所在的作用域是 fn
的作用域,所以只在 fn
内能被访问。
eval 根据的方式,其作用域也会发生变化。
如果直接 eval
则其作用域就是当前上下文中的作用域。如果间接性质的,比如通过 eval
的引用来,那作用域就是全局的。
var storeEval = eval;
(function() {
storeEval('var number1 = 1;');
eval('var number2 = 2');
console.log('自执行匿名内:', number2);
})();
console.log(number1); // :1
console.log(number2); // :ReferenceError: number2 is not defined
本身 eval 用到的情况就少,所以这种情况下做个了解即可。
理解了作用域,作用域链就很好理解了。
通常情况下,内层作用域拥有访问上层作用域的能力,而外层无法访问到内层的作用域。
var number = ;
var fn = function() {
console.log(number);
var str = '字符串';
};
fn();
console.log(str); // :ReferenceError: str is not defined
由此可见作用域从内往外的。
var number1 = ;
var fn1 = function() {
var number2 = ;
var fn2 = function() {
var number3 = ;
var fn3 = function() {
console.log('fn3 内的:');
console.log(number1);
console.log(number2);
console.log(number3);
}
fn3();
};
fn2();
}
fn1();
例子中的 fn3
就具有访问 fn2作用域
、fn1作用域
、全局作用域
的能力。
这样从内往外就形成了一条作用域链。
作用域最常用的场景之一就是隔离作用域。
因为有自己的作用域,所以很多库、框架在实现的时候都会把写在中。
(function() {
var con = {};
var fn = function() {
// ...
};
window.$ = fn;
window.jQuery = fn;
})();
这样就不会污染到全局,只想要暴露的部分。
有关作用域有更深入的,本篇探讨的是最容易理解的部分。
理解作用域可以更好的组织结构,减少各个上下文的污染。
在 ES6 中引入了块及作用域的概念,这是在之前都没有的,可以查阅 ES6 中对应的进行了解。