5种this绑定全面解析

5种this绑定全面解析

this的绑定规则总共有下面5种

1、默认绑定(严格/非严格模式)
2、隐式绑定
3、显式绑定
4、new绑定
5、箭头函数绑定

一.绑定规则

1.默认绑定

函数直接调用,一般发生在回调函数

  • 独立函数调用:this指向全局对象
  • 严格模式下,不能将全局对象用户默认绑定,this会指向undefined。在严格模式下调用函数则不受影响
  • setTimeout比较特殊,严格模式和非严格模式下都是window
(1)非严格模式,this指向window
function foo() { 
    console.log(this) // window
}
// --------------------------------------
(2)运行在严格模式下,this会绑定到undefined
function foo() { 
    "use strict";
    console.log( this.a );
    console.log(this) // undefined
}

var a = 2;

// 调用
foo(); // TypeError: Cannot read property 'a' of undefined

// --------------------------------------
(3)严格模式下调用函数则不影响默认绑定
function foo() { // 运行
    console.log( this.a );
}

var a = 2;

(function() { // 严格模式下调用函数则不影响默认绑定
    "use strict";
    
    foo(); // 2
})();
// --------------------------------------
(4)setTimeout
setTimeout(funtion(){
    console.log(this) //window
})

2.隐式绑定

当函数引用有上下文对象时,隐式绑定规则会把函数中的this绑定到这个上下文对象。
简而言之:谁调用this就指向谁

function foo() {
    console.log(this) //obj
    console.log( this.a );
}

var obj = {
    a: 2,
    foo: foo
};

obj.foo(); // 2

隐式丢失
被隐式绑定的函数特定情况下会丢失绑定对象,应用默认绑定,把this绑定到全局对象或者undefined上。

// 虽然bar是obj.foo的一个引用,但是实际上,它引用的是foo函数本身。
// bar()是一个不带任何修饰的函数调用,应用默认绑定。
function foo() {
    console.log( this.a );
}

var obj = {
    a: 2,
    foo: foo
};

var bar = obj.foo; // 函数别名

var a = "oops, global"; // a是全局对象的属性

bar(); // "oops, global"

参数传递就是一种隐式赋值,传入函数时也会被隐式赋值。 回调函数丢失this绑定是非常常见的。

function f1() {
    console.log( this.a ); 
}
function f2(fn) {
    // fn其实引用的是foo
    
    fn(); // <-- 调用位置!
}

var obj = {
    a: 2,
    foo: f1
};

var a = "oops, global"; // a是全局对象的属性
f2( obj.foo ); // "oops, global"

3.显式绑定call,apply,bind

const obj1 = {
    name:'wu',
    getName(){
        console.log(this)
        console.log(this.name)
    }
};
const obj2 = {
    name:'jingjing'
}
obj1.getName.call(obj2)//obj2 jingjing
obj1.getName.apply(obj2)//obj2 jingjing
const fn = obj1.getName.bind(obj2)
fn() //obj2 jingjing

4.new绑定

使用new来调用函数,或者说发生构造函数调用时,会自动执行下面的操作。

  • 1、创建(或者说构造)一个新对象。
  • 2、这个新对象会被执行[[Prototype]]连接。
  • 3、这个新对象会绑定到函数调用的this。
  • 4、如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象。
function fn(a){
    this.a=a;
}
var bar = new fn(2)
console.log(bar.a) //2
<!-- this指向fn new出来的对象bar -->

5. ES6的箭头函数绑定

箭头函数比较特殊,箭头函数this为副作用域的this,不是调用的this,前四种方式的this都是动态的,而箭头函数的this指向是静态的,声明的时候就确认下来了,比较符合js的此法作用域。(父元素的this是什么,就是什么

window.name='wu'
const obj = {
    name: 'jingjing',
    age:'18',
    getName()=>{
        <!--  -->
        console.log(this)//window
        console.log(this.name)//wu
    },
    getAge:function(){
        <!-- 通过obj.getAge调用,这里的this指向obj -->
        setTimeout(()=>{
            <!-- 所以这里的this也指向obj -->
            console.log(this.age) //12
        })
    }
}
obj.getName();
obj.getAge();

二.优先级

箭头函数 -> new绑定 -> 显示绑定call/bind/apply -> 隐式绑定 -> 默认绑定

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章