JavaScript的this机制与箭头函数(一)——this绑定的4种机制

传闻JavaScript有两座大山——this与作用域,在函数中,这两个难点会交织在一起。本来this就一脸懵逼,又有同样懵逼的作用域,所以说很多人就会
这里写图片描述
es6中,又出现了一个箭头函数,箭头函数的this又比普通函数的this“骨骼惊奇”得多。欲搞清楚箭头函数的this指向,必须要搞清楚this的四种绑定机制。
参考链接:深入理解this机制系列第一章

默认绑定

全局环境中,this默认绑定到window
在控制台中分别执行以下代码,注意,全局变量相当于window对象的属性

<1> console.log(this==window) // true
<2> var a={
        foo:"123",
        bar:"456",
        that:this
    }
    a.that // window
<3> this // window

函数独立调用或者被嵌套函数独立调用时,this默认绑定到window
虽然test()函数被嵌套在obj.foo()函数中,但test()函数是独立调用,而不是方法调用。所以this默认绑定到window

var a = 0;
var obj = {
    a : 2,
    foo:function(){
         function test(){
             console.log(this.a);
         }
         test();
    }
}
obj.foo();//0

立即执行函数实际上是函数声明后直接调用执行

var a = 0;
function foo(){
    (function test(){
        console.log(this.a);
    })()
};
var obj = {
    a : 2,
    foo:foo
}
obj.foo();//0

闭包中被返回到外部的函数也是独立调用

var a = 0;
function foo(){
    var a = 1
    function test(){
        console.log(this.a);
    }
    return test;
};
var obj = {
    a : 2,
    foo:foo
}
obj.foo()();//0

在这个例子中,如果test函数中console的是变量a,那么按照闭包的运行原理输出的是1,但这里输出的是this.a,this又绑定到了window,所以输出的值是0

隐式绑定

函数做为对象方法调用时(即方法调用),this隐式绑定到该直接对象

function foo(){
    console.log(this.a);
};
var obj1 = {
    a:1,
    foo:foo,
    obj2:{
        a:2,
        foo:foo
    }
}
//foo()函数的直接对象是obj1,this隐式绑定到obj1
obj1.foo();//1
//foo()函数的直接对象是obj2,this隐式绑定到obj2
obj1.obj2.foo();//2

隐式丢失
隐式丢失是指被隐式绑定的函数丢失绑定对象,从而默认绑定到window,有以下几种情况会造成隐式丢失

<1>函数别名

var a = 0;
function foo(){
    console.log(this.a);
};
var obj = {
    a : 2,
    foo:foo
}
//把obj.foo赋予别名bar,造成了隐式丢失
var bar = obj.foo;
bar();//0

<2>参数传递

var a = 0;
function foo(){
    console.log(this.a);
};
function bar(fn){
    fn();
}
var obj = {
    a : 2,
    foo:foo
}
//把obj.foo当作参数传递给bar函数时,有隐式的函数赋值fn=obj.foo
bar(obj.foo);//0

<3>作为内置函数的回调

var a = 0;
function foo(){
    console.log(this.a);
};
var obj = {
    a : 2,
    foo:foo
}
//如果没有隐式丢失,this应该指向obj
setTimeout(obj.foo,100);//0
//结果为0,证明函数作为作为内置函数的回调时发生了隐式丢失

<4>其他特殊情况

function foo() {
    console.log( this.a );
}
var a = 2;
var o = { a: 3, foo: foo };
var p = { a: 4 };
o.foo(); // 3
//将o.foo函数赋值给p.foo函数,然后立即执行。相当于仅仅是foo()函数的立即执行
(p.foo = o.foo)(); // 2

引用与调用的区别
调用:用原函数名调用函数,如foo()
引用:通过别名调用函数,比如var a=foo;a()

显式绑定

通过call()、apply()、bind()方法把对象绑定到this上,叫做显式绑定。对于被调用的函数来说,叫做间接调用

var a = 0;
function foo(){
    console.log(this.a);
}
var obj = {
    a:2
};
foo();//0
foo.call(obj);//2

显式绑定不能解决隐式丢失问题

function foo() {
    setTimeout(function (){
        console.log('id:',this.id);
    }, 100);
}
var id = 21;
foo.call({ id: 42 });//21

new绑定

构造函数通常不使用return关键字,它们通常初始化新对象,当构造函数的函数体执行完毕时,它会显式返回。在这种情况下,构造函数调用表达式的计算结果就是这个新对象的值

function fn(){
    this.a = 2;
}
var test = new fn();
console.log(test);//{a:2}

如果构造函数使用return语句但没有指定返回值,或者返回一个原始值,那么这时将忽略返回值,同时使用这个新对象作为调用结果

function fn(){
    this.a = 2;
    return;
}
var test = new fn();
console.log(test);//{a:2}

如果构造函数显式地使用return语句返回一个对象,那么调用表达式的值就是这个对象

var obj = {a:1};
function fn(){
    this.a = 2;
    return obj;
}
var test = new fn();
console.log(test);//{a:1}

以上便是this绑定的四种机制,下一篇博文将讲解箭头函数this的指向机制

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值