一、基础
ES6 将箭头函数纳入标准,很多人都知道一些基本的特性,比如下面的:
- 没有this、super、arguments 和 new.target 绑定
- 不能通过 new 关键字调用
- 没有 prototype
- 不可改变 this 的绑定
- 不支持 arguments
- 不支持重复命名参数(无论是严格模式还是非严格模式)
上面的列表时《深入理解ES6》中zakas列出的。
二、问题
最近遇到一个小疑问,也不算是我自己遇到的,看到别人提出的问题:
示例一:
// 示例一 lastName 使用 var 声明
var lastName = 'postbird';
const person = {
lastName:"ptbird",
getLastName:()=>{
console.log(this.lastName)
}
};
person.getLastName();// postbird
示例二:
// 示例二 lastName 使用 const 声明
const lastName = 'postbird';
const person = {
lastName:"ptbird",
getLastName:()=>{
console.log(this.lastName)
}
};
person.getLastName();// undefined
上面两个示例,第一个输出 postbird
第二个输出undefined
,都是直接请求的全局的属性,因为const
不会自动挂到 window 属性上,因此会输出 undefined。
那个提问者提出的问题是:为什么输出的不是 "ptbird" (示例二是我自己加上去的)
三、解释
很多人都指出所谓的 箭头函数是由声明的时候决定的,这个点是正确的,可是并没有人能够解释为什么声明的时候不能由person对象决定,而实际上由window决定.
zakas在讲箭头函数的时候,提出这样一个概念:
箭头函数 this 的指向(不仅仅是this,其实super,new.target等)由外围最近一层非箭头函数决定。
这个点首先指出,this 的指向是由什么决定的,然后再解释为什么是 window 而不是 person.
在对象声明的时候, lastName
和 getLastName()
都是 person 的内部(内部这个词可能不严谨)属性(方法),则他们的外围自然是全局了。
关键的点在于getLastName:()=>{}
和 getLastName:function(){}
和 getLastName(){}
这三种形式对于方法的声明,应该怎么看待。
这三者功能上后两者是等价的,第三个是ES6新增的简写方式(可以使用super),而第一个箭头函数和两者的却比在于箭头函数本身以及this指向等。
所以这三者在进行声明的过程中,他们仍旧与 lastName
属性一样,属于person的内部且与person
是等价的。
因此,在使用箭头函数声明 getLastName
方法的时候,this 由 person 的外围决定,而 person 的外围 自然是 window 了。