JavaScript中作用域
在 JavaScript 中, 作用域为可访问变量,对象,函数的集合。
ECMAScript6之后新增了块级作用域的概念,对应let
关键字
除此之外还有全局作用域,函数作用域。
块级作用域
由 { } 包括,if语句和for语句里面的{ }也属于块作用域。let声明的变量只在当前块内有效。
全局作用域
变量在函数外定义,即为全局变量,全局变量在页面关闭后销毁。
实际上,全局变量是全局对象的属性。在网页中,(译注:缺省的)全局对象是 window ,所以你可以用形如 window.variable 的语法来设置和访问全局变量。
全局变量有 全局作用域: 网页中所有脚本和函数均可使用。
函数作用域(又称为局部作用域)
变量在函数内声明,变量为局部作用域。
局部变量:只能在函数内部访问,函数执行完毕后销毁。
(函数参数也使用函数作用域)
var
var声明可以在包含它的函数,模块,命名空间或全局作用域内部任何位置被访问
捕获变量容易令人误解
for (var i = 0; i < 10; i++) {
setTimeout(function() { console.log(i); }, 100 * i);
}
//setTimeOut()会在若干秒延时后执行一个函数
函数执行在若干秒之后,是在for循环之后触发的,但由于变量i作用域是全局的,故而在循环之后都运行的为i=10之后的函数。
一个通常的解决方法是使用立即执行的函数表达式(IIFE)来捕获每次迭代时i的值:
for (var i = 0; i < 10; i++) {
// capture the current state of 'i'
// by invoking a function with its current value
(function(i) {
setTimeout(function() { console.log(i); }, 100 * i);
})(i);
}
多次声明同一个变量并不会报错
function sumMatrix(matrix: number[][]) {
var sum = 0;
for (var i = 0; i < matrix.length; i++) {
var currentRow = matrix[i];
for (var i = 0; i < currentRow.length; i++) {
sum += currentRow[i];
}
}
return sum;
}
var i多次在for循环内声明并不会报错
let
let声明的为块作用域变量,块作用于变量在包含它们的块或for循环之外是不能访问的
变量提升
JavaScript 变量的另一个不同寻常的地方是,你可以先使用变量稍后再声明变量而不会引发异常。这一概念称为变量提升;JavaScript 变量感觉上是被“提升”或移到了函数或语句的最前面。但是,提升后的变量将返回 undefined 值。因此在使用或引用某个变量之后进行声明和初始化操作,这个被提升的变量仍将返回 undefined 值。
/**
* 例子1
*/
console.log(x === undefined); // true
var x = 3;
/*=======================等效于如下========================*/
var x;
consle.log(x === undefined);
x = 3;
/**
* 例子2
*/
// will return a value of undefined
var myvar = "my value";
(function() {
console.log(myvar); // undefined
var myvar = "local value";
})();
/*===================等效于如下=========================*/
var myvar = "my value"
(function(){
var myvar;
console.log(myvar);//undefined
myvar = "local value"
})
在 ECMAScript 6 中,let(const)同样会被提升变量到代码块的顶部但是不会被赋予初始值。在变量声明之前引用这个变量,将抛出引用错误(ReferenceError)。这个变量将从代码块一开始的时候就处在一个“暂时性死区”,直到这个变量被声明为止。
console.log(x); // ReferenceError
let x = 3;
函数提升
对于函数来说,只有函数声明会被提升到顶部,而函数表达式不会被提升。
/* 函数声明 */
foo(); // "bar"
function foo() {
console.log("bar");
}
/* 函数表达式 */
baz(); // 类型错误:baz 不是一个函数
var baz = function() {
console.log("bar2");
};
Comments | NOTHING