JavaScript中若想改變this的指向那就必須用到apply call bind 方法,但其中三個方法有他們的區別
apply()
apply():第一個參數將代替function類裏的this對象,第二個參數是數組,將他作爲參數傳給function的arguments
function a(){
this.name = 'a';
this.show = function(){alert(this.name)};
}
function b() {
this.name = 'b';
}
var B = new b();
a.apply(B);
B.show();
這時輸出a,這是因爲apply方法中將this的指針改爲了b,在function中b.name = 'a', b.show = function(){alert(this.name)};所以當再次調用B.show()時輸出的是a
function A(a,b) {
this.a = a;
this.b = b;
}
function B() {
A.apply(this,[1,2]);
this.c = 3;
}
var s = new B();
alert(s.a+","+s.b+","+s.c);
這時輸出1,2,3,這是因爲在B函數中用apply方法將B的this給了a的this,將後面的1,2作爲參數傳給了A,這時給B的this分別添加了a和b屬性,所以再次輸出的時候B中會存在a,b,c三種屬性。
call ()
call():call方法和apply方法類似只不過傳入參數方法不同call方法中第二個參數不是數組,而是從第二個開始其餘參數直接傳給函數的arguments
,f function a(){
this.name = 'a';
this.show = function(){alert(this.name)};
}
function b() {
this.name = 'b';
}
var B = new b();
a.call(B);
B.show();
在這裏我們將之前的apply方法改爲了call方法,執行之後的結果和方法與apply方法相同
function A(a,b) {
this.a = a;
this.b = b;
}
function B() {
A.call(this,1,2);
this.c = 3;
}
var s = new B();
alert(s.a+","+s.b+","+s.c);
在這裏我們將B函數中的apply方法改爲了call方法,執行之後的結果和方法與apply方法相同,但是在這裏call方法傳入的參數發生了變化,apply是傳入數組,而call方法是直接將參數傳入
有了之前的鋪墊,那麼我們現在繼續深入一下
function A(a,b) {
this.a = a;
this.b = b;
}
function B() {
this.a = 5;
this.c = 3;
A.call(this,1,2);
}
var s = new B();
alert(s.a+","+s.b+","+s.c);
這時大家猜測一下輸出是什麼,是5,2,3嗎?
不,這時繼續輸出1,2,3,爲什麼呢?這時因爲給B調用了A的call方法,使A的this指針指向了B,雖然我們定義了B的a爲5,但是在調用call方法之後又將B的a重寫爲了1
function A(){
this.show = function(){alert(this.name)}
}
function B(){
this.name = 'b';
}
var C = new A();
var D = new B();
C.show.call(D);
alert(D.show);
這段代碼中,讓C.show中的this指向了D,但是並沒有給D寫入C.show,所以第一個輸出b第二個輸出undefined
最後我們來看一種奇怪的調用方式
function A(a){
alert(this+","+a+","+'A');
}
function B(b){
alert(this+","+b+","+'B');
}
var C = A.call;
A('a');
C.call(B,'a');
大家看到這估計已經懵逼了吧,想不到還可以這麼調用吧
在這裏第一個alert輸出[object Window],a,A,結果正常,第二個alert輸出a,undefined,A,這時就有人會問了,爲什麼a做了this指針而應該輸出a的地方卻輸出了undefined
我們先來看一下調用一次call方法輸出什麼
function A(a){
alert(this+","+a+","+'A');
}
function B(b){
alert(this+","+b+","+'B');
}
var C = A;
A('a');
C.call(B,'a');
也就是說調用一次call方法是沒問題的而且將他的this指向了B
那麼在調用兩次call方法時A的this指針域指向了arguments的第一個參數,而後面的參數則是作爲了arguments的參數。
bind()
bind():這個方法會創建一個函數的實例,傳入參數與call方法相同
var name = 'global';
function person () {
this.name = 'hero';
}
function print(age, job) {
console.log(this.name, age, job);
}
var Person = new person();
var printf = print.bind(Person);
printf(18, '前端工程師');
在這裏將print通過bind方法將this的指針改爲了print,返回了一個函數,調用函數並傳入參數
輸出hero 20 前端工程師
但是對bind方法new會讓bind方法綁定的第一個參數消失
function Person(name, age) {
this.name = name;
this.age = age;
}
var _Person = Person.bind(null, 'hanzichi');
var p = new _Person(30);
因爲new方法導致bind第一個參數無效