1. 問題引入
function A() {}
A.prototype.fna = function() {
console.log(this);
}
我的問題是 fna
的 this
是指向哪裡的?
var a = new A();
a.fna(); // A {}
var fnt = a.fna;
fnt(); // window {...}
再看我們經常遇到的情形
function A() {
this.name = `A`;
}
A.prototype.fna = function() {
return this.name;
}
function sayName(fn) {
console.log(fn());
}
var a = new A();
sayName(a.fna); //undefined
sayName(a.fna.bind(a)); //A
這裡就是我們平時在寫程式碼的時候為什麼要呼叫 bind
函式來繫結上下文
function A() {
this.fna = function() {
console.log(this);
}
}
A.prototype.getFna = function() {
return this.fna;
}
function sayContext(fn) {
fn();
}
var a = new A();
var fna = a.getFna();
sayContext(fna); //window
為什麼會有以上這種情況呢,在 java
中 this
是始終指向呼叫物件的。是的,始終指向呼叫物件,呼叫物件,這個很重要,java
的靜態成員是沒有 this
的概念的。在 javascript
中 this
只和函式的執行環境有關。只有三種情況,在瀏覽中 window、呼叫物件、嚴格模式下的undefined,對應我們開發者來說能接觸到的就是以上三者,所以我們可以理解為 函式的執行環境就是以上三者。
2. 確定 this
指向
我們如何確定 this
的指向呢,有很多文章介紹 this
確定指向,方式也有很多種,而我是根據函式的呼叫形勢去判斷的,有以下兩個判斷標準。
1 如果函式的最終呼叫形式是 fn();
那麼在非嚴格模式下 this
指向 window
物件,在嚴格模式下指向 undefined
2 如果是通過物件呼叫 o.fn();
這種形式 this
指向物件 o
是的就這兩個標準,就這麼簡單。
3. 通過 call
、apply
、bind
深入理解 this
函式呼叫原型
fn.call(thisArg, arg1, arg2, ...)
fn.apply(thisArg, [argsArray])
fn.bind(thisArg[, arg1[, arg2[, ...]]])
上面這三個函式都是用來改變函式的 this
指向的
1 call
第一個引數是 fn
中 this
的期望指向,值可以是 物件
或者 undefined
,後面的引數是要傳遞 給 fn
的引數列表
2 apply
第一個引數是 fn
中 this
的期望指向,值可以是 物件
或者 undefined
,後面的值是 fn
的 引數,是一個陣列
call
和apply
功能相同,唯一不同的是選擇將引數以 引數列表
傳入或者以 陣列
傳入,都可以,可以互換
使用。呼叫者兩個函式會立即執行 fn,這裡是立即執行
3 bind
第一個引數是 fn
中 this
的期望指向,值可以是 物件
或者 undefined
,後面的引數是要傳遞 給 fn
的引數列表
呼叫 bind
函式會返回一個函式,這個函式是 fn
的包裝,和 fn
的唯一區別是繫結了 this
,即 this
指向明確。所以 bind
和 call
、apply
,的區別是 bind
返回一個 this
明確的新函式,call
和 apply
立即執行了 fn
。
到這裡我想 javascript
的 this
已經說的很清楚了。