先来看一个例子
var name = 'World!';
var t = {name:"w"};
(function () {
//console.log(this);
console.log(t);
//console.log(name);
if (typeof name === 'undefined') {
var name = 'Jack';
console.log('Goodbye ' + name);
}else{
console.log('Hello ' + name);
}
})();
输出结果为:
World!
{name: "w"}
undefined
Goodbye Jack
该代码执行输出的结果为 Goodbye Jack,而不是Hello World,也不是Hello Jack;
为什么?
因为(function(){})();这样写法的内部function是一个局部函数,而且函数执行之前,必须等待function内的所有变量都声明了才会开始执行,就像java的局部变量一样,java的方法内的局部变量并不是执行到哪一行才去声明的,而是初始化方法时,先扫描所有局部变量,并声明所有的局部变量的内存才开始执行的
同理闭包(function(){})();内的function也是先声明所有局部变量才去执行,因为function内声明了name所以会初始化一个局部变量name=undefined才开始执行方法,而执行到if (typeof name === 'undefined') ,因为存在局部变量name,所以方法不会提升变量name的范围,故这时name仍然是undefined,而不是外部声明的全局变量的值World,这就是为什么typeof name === 'undefined'是true,方法输出结果为Goodbye Jack。
而t因为function内不存在局部变量声明(var,let,const等声明关键字修饰),所以不会先初始化t的内存,而是等到执行时才是提升变量范围访问全局变量中的t,如果提升变量范围也没有对应的声明,那就再重新初始化(仅js这种存在自动识别并声明变量的语言才会,如果是java直接编译不通过)