JavaScript挑戰練習(一)-改變this指向
一.this指向的詳解
概括:this的指向到底是指向哪裡?通常來說,只有當函式執行的時候才可以確定this指向的到底是誰,簡單的也可以這麼說:this最終指向的是那個呼叫它的物件。
常見的一般有以下幾種情況:
第一種:在一個函式中有this,但是函式沒有被上一級物件所呼叫,所以此時的this指向的是window(注意在嚴格模式下則不是),如以下程式碼:
function blue() { var blue = "藍源"; console.log(this.blue);//undefind console.log(this);//window } blue();//this指向呼叫它的那個物件,在這裡相當於window
第二種:在函式中有一個this,而且該函式被上一級物件所呼叫,所以此時的this指向的是呼叫該函式的上一級物件,如以下程式碼:
var o = {
name: "blue",
fn: function(){
console.log(this.name);//blue
console.log(this);//指向o物件
}
}
o.fn();//此時this指向的是呼叫函式的物件o。
第三種:有一個函式中有this,函式中有多個物件,儘管這個函式是被最外層的物件呼叫,但是其中的this指向的只是它的上一級物件,如以下程式碼:
var o = {
name: "blue",
a: {
fn: function(){
console.log(this.name);//undefind,這裡有兩個物件o和a,呼叫的時候都指向上一層物件a,這裡找不到宣告的name
}
},
fn1: function(){
console.log(this.name);//blue
}
}
o.fn1();
o.a.fn();
第四種(特殊情況):如果函式中有return,而且return返回的是一個物件,那麼呼叫時候的this指向不再是指向呼叫這個函式的例項了,而是指向這個函式返回的物件,如以下程式碼:
function fn()
{
this.name = 'blue';
return {};
}
var a = new fn;
console.log(a.name); //undefined,這裡指向的是return返回的物件,是一個空物件
改變this指向的方法
第一種:使用call()
var a = {
user:"blue",
fn:function(){
console.log(this.user); //blue
}
}
var b = a.fn;
b.call(a); //若不用call,則b()執行後this指的是Window物件
call方法除了第一個引數以外還可以新增多個引數,如下:
var a = {
user:"blue",
fn:function(c,d){
console.log(this.user); //blue
console.log(e+ee); //3
}
}
var b = a.fn;
b.call(a,1,2);
第二種:使用apply()
var a = {
user:"blue",
fn:function(){
console.log(this.user); //blue
}
}
var b = a.fn;
b.apply(a);
apply方法和call方法很類似,也可以接收多個引數,但是第二個引數必須是陣列,如下:
var a = {
user:"blue",
fn:function(e,ee){
console.log(this.user); //blue
console.log(c+d); //11
}
}
var b = a.fn;
b.apply(a,[10,1]);
第三種:使用bind()
bind和call,apply的使用方法有些不同,如果我們還是按照上面的方法寫程式碼,會發現一些問題,如下:
var a = {
user:"blue",
fn:function(){
console.log(this.user);
}
}
var b = a.fn;
b.bind(a); //程式碼沒有被列印
為什麼程式碼沒有被列印呢?這就是不同的地方所在,實際上執行bind之後返回的是一個函式,想下面這樣寫才是正確的:
var a = {
user:"blue",
fn:function(){
console.log(this.user); //blue
}
}
var b = a.fn;
var c = b.bind(a);
c();
bind()方法也可以接收多個引數,並且引數可以執行的時候再次新增,但是要注意的是,引數是按照形參的順序進行的,如下:
var a = {
user:"blue",
fn:function(e,d,f){
console.log(this.user); //blue
console.log(e,d,f); //10 1 2
}
}
var b = a.fn;
var c = b.bind(a,10);
c(1,2);
總結:
call(),apply()以及bind()方法都可以改變this指向,只是所使用的場景有點不一樣,bind()改變後的函式想什麼時候呼叫就什麼時候呼叫,call和apply都是改變指向後立即呼叫此方法。