理解JavaScript普通函数以及箭头函数里使用的this
普通函数的this
普通函数的this是由动态作用域决定,它总指向于它的直接调用者。具体可以分为以下四项:
- this总是指向它的直接调用者, 例如 obj.func() ,那么func()里的this指的是obj。
- 在默认情况(非严格模式,未使用 'use strict'),如果函数没有直接调用者,this为window
- 在严格模式下,如果函数没有直接调者,this为undefined
- 使用call,apply,bind绑定的,this指的是绑定的对象
箭头函数的this
箭头函数是没有绑定自己的this,函数内使用的this是由静态作用域(也成为词法作用域,参考this)决定。静态作用域就是说箭头函数里this是由定义它的代码决定,而不是执行调用箭头函数的代码。
上面的说法有时很难理解,我自己总结的方法是:找出定义箭头函数的上下文(即包含箭头函数最近的函数或者对象),那么上下文所处的父上下文即为this。具体可以参考箭头函数的示例。
普通函数示例
示例1:对象函数的this
var obj = {
myfunc : function() {
console.log(this);
}
}
obj.myfunc();
输出的是obj对象,this指的是obj。
示例2:全局函数的this
function myfunc() {
console.log(this);
}
myfunc();
输出的是Window对象,this指的是Window
示例3:严格模式下全局函数的this
'use strict';
function myfunc() {
console.log(this);
}
myfunc();
this为undefined,因为严格模式下,myfunc没有直接的调用者。
示例1-变形1:在obj.myfunc()方法里添加普通函数,并执行
var obj = {
myfunc : function() {
function innerfunc() {
console.log(this);
}
innerfunc();
}
}
obj.myfunc();
this指的是Window。这是因为innerfunc()函数执行时没有直接调用者,所有this为Window。
示例1-变形2:把obj.myfunc赋值给一个变量后调用
var obj = {
myfunc : function() {
console.log(this);
}
}
var f = obj.myfunc;
f();
this指的是Window。这是因为f()是没有直接调用者,在非严格模式下,this指的是Window。
箭头函数示例
示例5:函数内使用箭头函数
var obj = {
myfunc : function(){
var f = ()=>{
console.log(this);
}
f();
}
}
obj.myfunc();
this指的是obj。因为定义箭头函数的上下文为myfunc函数,myfunc函数所在的父上下文为obj。
示例6:箭头函数作为方法
var obj = {
myfunc : ()=>{
console.log(this);
}
}
obj.myfunc();
这个地方很容易误以为this指的是obj。其实this实际指的是window,因为定义箭头函数最近的上下文为obj对象(myfunc和箭头函数作为key-value的形式是平级),而obj对象的父上下文为window。
按MDN web docs里说的,建议箭头函数仅用在非方法的函数(non-method function)里。
示例7:
var outeobj = {
outfunc:function() {
var obj = {
myfunc : ()=>{
console.log(this);
}
}
obj.myfunc();
}
}
outeobj.outfunc();
为了和示例6做对比,现在把obj对象添加到outerobj的outfunc里。
this指的是outobj。这是因为箭头函数最近的上下文为obj对象,而obj对象的父上下文为outobj。