與其餘語言相比,函數的 this 關鍵字在 JavaScript中的表現略有不一樣,此外,在嚴格模式和非嚴格模式之間也會有一些差異。本文介紹this在不一樣使用場景的指向問題。git
二、this 的綁定和函數聲明的位置沒有任何關係,只取決於函數的調用方式。當一個函數被調用時,會建立一個「執行上下文」,這個上下文會包含函數在哪裏被調用(調用棧)、函數的調用方式、傳入的參數等信息。this 就是這個記錄的一個屬性,會在函數執行的過程當中用到。github
原文戳我bash
這是函數的最一般的用法,請看下面這段代碼,不管在函數裏執行,仍是函數外執行,它的運行結果都是2。app
function test () {
this.x = 2;
alert(this.x);
}
test(); //2
console.log(this.x) //2
複製代碼
爲了證實this表明全局對象Global,我對代碼做必定的修改,請看下面這段代碼,它的運行結果是1。函數
this.x = 1;
function test () {
alert(this.x)
}
test(); //1
複製代碼
this表明全局對象,屢次申明表示從新定義,請看下面這段代碼,它的運行結果是2。ui
this.x = 1;
funtcion test () {
this.x = 2;
alert(this.x);
}
test(); //2
複製代碼
函數還能夠做爲某個對象的方法調用,這時this就指這個上級對象。this
this.x = 2;
function test () {
alert(this.x);
}
var o = {};
o.x = 1;
o.m = test;
o.m(); //1
複製代碼
this指向構造函數,this再也不是全局變量spa
this.x = 2;
function test () {
this.x = 1;
alert(this.x) //1
}
let newTest = new test();
alert(newTest.x) //1
alert(x) // 2
複製代碼
1.箭頭函數做爲函數的一種形式,對於this的處理和普通函數有所區別,其沒有本身的this上下文,也就是說經過bind/call/apply函數方法設置this值時無效的,會被忽略。
prototype
2.由於箭頭函數沒有本身的this上下文,那麼當它做爲對象的方法函數運行時,this並不指向這個對象。
code
3.箭頭函數的的函數體中出現的this在運行時綁定到最近的做用域上下文對象。
4.你能夠認爲箭頭函數的this和調用者無關,只和其定義時所在的上下文相關。
function Person() {
this.age = 0;
setInterval(() => {
this.age++; // |this| 正確地指向person 對象
}, 1000);
}
var p = new Person();
複製代碼
function objWrapper() {
var a = 10;
var obj = {
foo: () => console.log(this.a)
}
obj.foo();
}
objWrapper.call({a:20});//20
objWrapper();//undefined
複製代碼
這三個函數,均可以改變函數的 this 指向到指定的對象。
上面代碼中, foo() 內部的 this 遵循默認綁定規則,綁定到全局變量中。
而 bar() 在調用的時候,調用了 apply() 函數,把 this 綁定到了一個新的對象中 {a: 2},並且原封不動的接收 foo() 接收的函數。
function foo() {
console.log(this.a); // 輸出 1
bar.apply({a: 2}, arguments);
}
function bar(b) {
console.log(this.a); // 輸出 2
}
var a = 1;
foo(3);
複製代碼
bind函數的第一個參數若是爲null,this指向全局變量。
this.x = 9;
let module = {
x: 81,
getX: function() { return this.x; }
};
module.getX(); // 返回 81
let retrieveX = module.getX;
retrieveX(); // 返回 9, 在這種狀況下,"this"指向全局做用域
// 建立一個新函數,將"this"綁定到module對象
// 新手可能會被全局的x變量和module裏的屬性x所迷惑
let boundGetX = retrieveX.bind(module);
boundGetX(); // 返回 81
let reBoundGetX = retrieveX.bind(null,module)
boundGetX(); // 返回 9
複製代碼