關於this指向
- 如果一個函式中有this,但是它沒有被上一級的物件所呼叫,那麼this指向的就是window,這裡需要說明的是在js的嚴格版中this指向的不是
window。
var a="隴錦";
function foo() {
var a="掘金";
console.log(this.a);
console.log(this)
};
foo();
複製程式碼
- 如果一個函式中有this,這個函式被上一級的物件所呼叫,那麼this指向的就是上一級的物件。
var a="隴錦";
var foo = {
a:"掘金",
fn:function(){
console.log(this.a);
}
};
foo.fn();
複製程式碼
- 如果一個函式中有this,這個函式中包含多個物件,儘管這個函式是被最外層的物件所呼叫,this指向的也只是它上一級的
var a={
b:"隴錦",
c:{
fn:function() {
console.log(this.b);
}
}
};
a.c.fn();
複製程式碼
- this指向永遠都是最後呼叫他的物件,可以對比一下前面的例子。這裡q被賦值為fn函式,執行q,他的this就會改變。
var a={
b:"隴錦",
c:{
fn:function() {
console.log(this.b);
console.log(this);
}
}
};
var q=a.c.fn;
q();
複製程式碼
當 this 碰到 return
- 如果返回值是一個物件,那麼this指向的就是那個返回的物件,如果返回值不是一個物件那麼this還是指向函式的例項。
function fn() {
this.b="隴錦";
return {
b:"掘金"
};
};
var a=new fn;
console.log(a.b);
複製程式碼
function fn() {
this.b="隴錦";
function (){}
};
var a=new fn;
console.log(a.b);
複製程式碼
- 但需要注意的是,雖然null也是物件,但是在這裡this還是指向那個函式的例項,因為null比較特殊。
function fn() {
this.b = '隴錦';
return null;
}
var a = new fn;
console.log(a.user);
複製程式碼
如何改變this指向
- 通過new:用變數a建立了一個Fn的例項(相當於複製了一份Fn到物件a裡面),此時僅僅只是建立,並沒有執行,而呼叫這個函式Fn的是物件a,
那麼this指向的自然是物件a,那麼為什麼物件a中會有user,因為你已經複製了一份Fn函式到物件a中,用了new關鍵字就等同於複製了一份.
function Fn(){
this.b = "掘金";
}
var a = new Fn();
console.log(a.b);
複製程式碼
- call方法和apply方法
- 每個函式都包含兩個非繼承而來的方法:call()方法和apply()方法。
- 相同點:這兩個方法的作用是一樣的。都是在特定的作用域中呼叫函式,等於設定函式體內this物件的值,以擴充函式賴以執行的作用域。
window.color = 'red';
document.color = 'yellow';
var s1 = {color: 'blue' };
function changeColor(){
console.log(this.color);
};
changeColor.call();
changeColor.call(window);
changeColor.call(document);
changeColor.call(this);
changeColor.call(s1);
複製程式碼
window.number = 'one';
document.number = 'two';
var s1 = {number: 'three' };
function changeColor(){
console.log(this.number);
};
changeColor.apply();
changeColor.apply(window);
changeColor.apply(document);
changeColor.apply(this);
changeColor.apply(s1);
複製程式碼
- 不同點:接收引數的方式不同
- apply()方法 接收兩個引數,一個是函式執行的作用域(this),另一個是引數陣列。
- 語法:apply([thisObj [,argArray] ]);,呼叫一個物件的一個方法,2另一個物件替換當前物件。
- 說明:如果argArray不是一個有效陣列或不是arguments物件,那麼將導致一個TypeError,如果沒有提供argArray和thisObj任何一個引數,那麼Global物件將用作thisObj。
- call()方法 第一個引數和apply()方法的一樣,但是傳遞給函式的引數必須列舉出來。
- 語法:call([thisObject[,arg1 [,arg2 [,...,argn]]]]);,應用某一物件的一個方法,用另一個物件替換當前物件。
- 說明: call方法可以用來代替另一個物件呼叫一個方法,call方法可以將一個函式的物件上下文從初始的上下文改變為thisObj指定的新
物件,如果沒有提供thisObj引數,那麼Global物件被用於thisObj。
function add(c,d){
return this.a + this.b + c + d;
}
var s = {a:1, b:2};
console.log(add.call(s,3,4));
console.log(add.apply(s,[5,6]));
複製程式碼
var a = {
user:"掘金",
fn:function(){
console.log(this.user);
}
};
var b = a.fn;
b.bind(a);
複製程式碼
- 我們發現程式碼沒有被列印,因為bind方法返回的是一個修改過後的函式。
var a = {
user:"掘金",
fn:function(){
console.log(this.user);
}
}
var b = a.fn;
var c = b.bind(a);
console.log(c);
複製程式碼
var a = {
user:"掘金",
fn:function(){
console.log(this.user);
}
};
var b = a.fn;
var c = b.bind(a);
c();
複製程式碼
- 同樣bind也可以有多個引數,並且引數可以執行的時候再次新增,但是要注意的是,引數是按照形參的順序進行的。
var a = {
user:"掘金",
fn:function(e,d,f){
console.log(this.user);
console.log(e,d,f);
}
};
var b = a.fn;
var c = b.bind(a,10);
c(1,2);
複製程式碼
- call和apply都是改變上下文中的this並立即執行這個函式,bind方法可以讓對應的函式想什麼時候調就什麼時候呼叫,並且可以將引數在
執行的時候新增,這是它們的區別
參考部落格:追夢子blog http://www.cnblogs.com/pssp/
內容如有錯誤,歡迎指正。文章只寫給需要的人,大牛忽略。