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