js 变量作用域探析
背景
var o = {};
o.fun = test();
o.fun();
function test() {
var fn = function () {
console.log(this);
};
return fn;
}
{fun: ƒ}
由于对这个程序的输出结果感到不解,于是决定深入了解 js 作用域究竟是什么个东西
参考:https://msdn.microsoft.com/zh-cn/library/bzt2dkta(v=vs.94).aspx
变量作用域
又要谈到 js 的两个范围:全局和局部
函数之外声明的变量就是全局变量,可在整个程序中访问和修改
函数内声明的变量是局部变量,每当执行程序时都会创建和销毁该变量(所以称临时变量),并且无法通过函数之外的任何代码访问该变量(MSDN 如是说)
js 不支持块范围(通过一组大括号定义新范围),于是就只有全局(函数外)和局部(函数内),以函数划分的这两种范围
js 范围
var aNumber = 100;
tweak();
function tweak() {
document.write(aNumber);
if (false) {
var aNumber = 123;
}
}
undefined
虽然 if(false),var aNumber = 123 不会执行,但是 js 在执行函数 tweak()时,会查找所有变量声明,var aNumber 被扫描到,js 使用初始值undefined创建变量,即使使用一个值声明变量 var aNumber = 123,但 aNumber 变量的初始值仍为undefined,仅当执行包含声明的行(var aNumber = 123)时才会使用已声明的值。
js 会在执行任何代码之前处理所有变量声明,无论是在条件块中声明还是在其他构造中声明
js 一旦找到所有变量,就会执行函数中的代码。如果函数内部隐式声明变量,即变量出现在赋值表达式左侧,但尚未使用var进行声明,则它将创建为全局变量
js 中,内部(嵌套)函数将存储对局部变量的引用(即使在函数返回之后),这些局部变量存在于与函数本身相同的范围,这一组引用称为闭包。
function send(name) {
return function () {
sendHi(name);
};
}
function sendHi(msg) {
console.log("Hello" + msg);
}
var func = send("Bill");
func();
sendHi("Pete");
func();
HelloBill
HelloPete
HelloBill
对内部函数的第二次调用输出与第一次调用相同,因为外部函数的输入参数 name 存储在内部函数闭包中的局部变量
块范围变量
IE11 引入对 let 和 const 这两个块范围变量的支持
let x = 10;
var y = 10;
{
let x = 5;
var y = 5;
{
let x = 2;
var y = 2;
document.write("x: " + x + "<br/>");
document.write("y: " + y + "<br/>");
// Output:
// x: 2
// y: 2
}
document.write("x: " + x + "<br/>");
document.write("y: " + y + "<br/>");
// Output:
// x: 5
// y: 2
}
document.write("x: " + x + "<br/>");
document.write("y: " + y + "<br/>");
// Output:
// x: 10
// y: 2