参考文章:https://www.jb51.net/article/161019.htm
var a = 10;
(function() {
console.log(a)
a = 5
console.log(window.a)
var a = 20;
console.log(a)
})()
解析:在立即执行函数中,var a = 20; 语句定义了一个局部变量 a,由于js的变量声明提升机制,局部变量a的声明会被提升至立即执行函数的函数体最上方,且由于这样的提升并不包括赋值,因此第一条打印语句会打印undefined,最后一条语句会打印20。
由于变量声明提升,a = 5; 这条语句执行时,局部的变量a已经声明,但是匿名函数的执行是具有全局性的,因此它产生的效果是对局部的变量a赋值,此时window.a 依旧是最开始赋值的10。
var name = 'window'
var person = {
name: 'Alan',
sayOne: function() {
console.log(this.name)
},
sayTwo: function() {
return function() {
console.log(this.name)
}
}
}
person.sayOne() //Alan
person.sayTwo()() // window
- 函数内部的this指向调用者
- sayOne调用者是person对象,所以this指向person;
- sayTwo的调用者虽然也是person对象,但是区别在于这次调用并没有打出this而是在全局返回了一个匿名函数
- 而这个匿名函数不是作为某个对象的方法来调用执行,是在全局执行
做下修改
var name = 'window'
var person = {
name :'Alan',
sayName:function () {
var that = this
return function () {
console.log(that.name)
}
}
}
person.sayName()() // Alan
延伸
【变量提升】下面代码的输出是什么?
function sayHi() {
console.log(name);
console.log(age);
var name = "Lydia";
let age = 21;
}
sayHi();
- A:
Lydia
和undefined
- B:
Lydia
和ReferenceError
- C:
ReferenceError
和21
- D:
undefined
和ReferenceError
答案: D
在函数中,我们首先使用var
关键字声明了name
变量。 这意味着变量在创建阶段会被提升(JavaScript
会在创建变量创建阶段为其分配内存空间),默认值为undefined
,直到我们实际执行到使用该变量的行。 我们还没有为name
变量赋值,所以它仍然保持undefined
的值。
使用let
关键字(和const
)声明的变量也会存在变量提升,但与var
不同,初始化没有被提升。 在我们声明(初始化)它们之前,它们是不可访问的。 这被称为“暂时死区”。 当我们在声明变量之前尝试访问变量时,JavaScript
会抛出一个ReferenceError
。