JavaScript中apply bind call的異同(重點講解call方法)
阿新 • • 發佈:2019-02-20
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);//b
alert(D.show);//undefined
這段程式碼中,讓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');//[object Window],a,A
C.call(B,'a');// function B(b){alert(this+","+b+","+'B');},a,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); // Person {name: "hanzichi", age: 30}
因為new方法導致bind第一個引數無效