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

WEB前端 waitig 418℃ 百度已收录 0评论

传闻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(){
    function test(){
        console.log(this.a);
    }
    return test;
};
var obj = {
    a : 2,
    foo:foo
}
obj.foo()();//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的指向机制


本文由【waitig】发表在等英博客
本文固定链接:JavaScript的this机制与箭头函数(一)——this绑定的4种机制
欢迎关注本站官方公众号,每日都有干货分享!
等英博客官方公众号
点赞 (0)分享 (0)