一、基础

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.

在对象声明的时候, lastNamegetLastName() 都是 person 的内部(内部这个词可能不严谨)属性(方法),则他们的外围自然是全局了。

关键的点在于getLastName:()=>{}getLastName:function(){}getLastName(){} 这三种形式对于方法的声明,应该怎么看待。

这三者功能上后两者是等价的,第三个是ES6新增的简写方式(可以使用super),而第一个箭头函数和两者的却比在于箭头函数本身以及this指向等。

所以这三者在进行声明的过程中,他们仍旧与 lastName属性一样,属于person的内部且与person是等价的。

因此,在使用箭头函数声明 getLastName 方法的时候,this 由 person 的外围决定,而 person 的外围 自然是 window 了。

请输入图片描述