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 -> 隱式綁定 -> 默認綁定

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