this in JavaScript's function
· 2 分钟阅读
一般情况
标题部分 一般情况最近在看 GitHub 上的一本书,You-Dont-Know-JS ,这本书讲解的this非常清楚:要理解this的指向,首先得知道call-site这个概念:
To understand this binding, we have to understand the call-site: the location in code where a function is called (not where it’s declared).
然后根据这个函数在call-site是怎样被调用的,按如下四条规则,优先级从上到下:
- Is the function called with
new
(new binding)? If so, this is the newly constructed object.var bar = new foo()
- Is the function called with
call
orapply
(explicit binding), even hidden inside a bind hard binding? If so, this is the explicitly specified object.var bar = foo.call( obj2 )
- Is the function called with a context (implicit binding), otherwise known as an owning or containing object? If so, this is that context object.
var bar = obj1.foo()
- Otherwise, default the this (default binding). If in strict mode, pick undefined, otherwise pick the global object.
var bar = foo()
Lexical this
标题部分 Lexical this一般情况以上四条规则就可以cover 了,但是ES6 新加的箭头函数就不是这样。它的this用lexical this概括再好不过了。Lexical 这个词,在讲作用域时提到了JS 是Lexical Scope ,lexical 强调的是声明时,author-time,反正我是这么理解的。所以,箭头函数中的this就只与定义它时的父级上下文相关,而且无法用bind、call、apply 改变。 看下面三个例子,就很清楚了:
function foo() { setTimeout(() => { // `this` here is lexically adopted from `foo()` console.log(this.a); }, 100);}var obj = { a: 2,};foo.call(obj); // 2 将 foo 中的 `this` 绑定到了 obj 上,对应情形 2
function foo() { var self = this; // lexical capture of `this` setTimeout(function () { console.log(self.a); }, 100);}var obj = { a: 2,};foo.call(obj); // 2 注意这里不是箭头函数
function foo() { // return an arrow function return () => { console.lot(this.a); };}var obj1 = { a: 2,};var obj2 = { a: 3,};var bar = foo.call(obj1);bar.call(obj2); // 2 not 3! 这证明了箭头函数中的 `this` 无法通过 bind 来改变。