javascript中的this绑定问题

this的绑定规则

1 默认绑定:

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

 

调用 foo() 的时候其实相当于 window.foo(),所以 this.a 其实指向的是 window.a

2 隐式绑定

function foo(){
    console.log( this.a );
}
var obj1 = {
    a: 2,
       obj2: obj2
};
var obj2 = {
    a: 42,
       foo: foo
};
obj1.obj2.foo(); // 42

 

当函数引用有上下文对象时,隐式绑定规则会把函数调用中的 this 绑定到这个上下文的对象。因为调用 foo() 时 this 被绑定到 obj,因此 this.a 和 obj.a 是一样的

对象属性引用链中只有上一层或者说最后一层在调用位置起作用(这里是由于作用域链对于 this 的寻找只会到当前的活动对象或变量对象中,不会到上一层)

3 显式绑定

function foo(){
    console.log( this.a );
}
var obj = {
    a: 2,
};
var bar = function(){
    foo.call( obj );
};
bar(); // 2
setTimeout(bar,100) // 2

// 显示绑定的 bar 不可能再修改它的 this
bar.call(window); // 2

即使用 apply() 和 call() 方法。它们的第一个参数是一个对象,在调用函数时将其绑定到 this。他们的主要区别就是第二个参数。
我们创建了函数 bar(),并在内部调用了 foo.call(obj),因此强制把 foo 的 this 绑定到了 obj。之后无论如何调用 bar(),它总会手动在 obj 上调用 foo。这种绑定是一种强制绑定,也成为硬绑定。
由于硬绑定是一种非常常用的模式,所以 ES5 提供了 bind() 函数。用法如下

function foo(something){
    console.log( this.a, something );
    return this.a + something;
}
var obj = {
    a:2
}
var bar = foo.bind( obj );
var b = bar(3); // 2 3;
console.log(b); // 5

4 new 绑定
使用 new 调用函数只是对函数的 " 构造调用 ",所有的函数都可以使用 new 来调用。
使用 new 来调用函数时,会自动执行如下操作

创建(或者说构造)一个全新的对象
这个新对象会被执行 [[Prototype]] 连接
这个新对象会绑定到函数调用的 this
如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象
用代码表示就是如下步骤

function foo(a){
    this.a = a;
}
var bar = new foo(2);
console.log(bar.a); // 2
// 其中 new foo(2) 进行的是类似如下的操作
{
    var obj = new Object();
    obj.__proto__ = foo.prototype;
    var result = foo.call(obj,"2");
    return result === 'object' ? result : obj
}

 

使用 new 来调用 foo( … ) 时,我们会构造一个新对象并把它绑定到 foo( … ) 调用中的 this

 

以上几种方式的优先级:
【1】是否是new绑定?如果是,this绑定的是新创建的对象var bar = new foo();
【2】是否是显式绑定?如果是,this绑定的是指定的对象var bar = foo.call(obj);
【3】是否是隐式绑定?如果是,this绑定的是属于的对象var bar = obj1.foo(); 
【4】如果都不是,则使用默认绑定 var bar = foo();

posted @ 2019-08-12 10:38  蜗牛菜菜  阅读(335)  评论(0编辑  收藏  举报
footer