JS中的call和apply函式
阿新 • • 發佈:2019-02-03
call 函式
- 語法
obj.call(thisObj,arg[,arg2[,arg3[,...agr]]]);
- 簡介
thisObj繼承obj的屬性和方法(obj原型鏈上的屬性和方法不能被繼承),後面的引數會當成obj的引數安裝順序傳遞進去。
- 示例
function animal(type,nickname){
this.type = type;
this.nickname = nickname;
this.sayHello = function(){
return 'hello';
}
}
function cat(name,type,nickname){
this.name = name;
//cat繼承animal
animal.call(this,type,nickname);
}
console.log(new cat('wsscat','cut','tom'));
/*
cat {
name: 'wsscat',
type: 'cut',
nickname: 'tom',
sayHello: [Function] }
*/
apply 函式
- 語法
obj.apply(this[,argArray]);
- 簡介
apply和call的作用差不多,都可以用來繼承,區別在與apply只有兩個引數,第二個引數必須是陣列或者arguments物件。否則會報TypeError錯誤。如果繼承的物件obj有多個引數,則會吧argArray的引數依次對應obj的每個引數。
- 示例
function animal(type,nickname){
this.type = type;
this.nickname = nickname;
this .syaHello = function(){
return 'hello';
}
}
function cat(name,type,nickname){
this.name = name;
animal.apply(this,arguments);
}
console.log(new cat('wsscat','cut','tom'));
/*
cat {
name: 'wsscat',
type: 'wsscat',
nickname: 'cut',
syaHello: [Function] }
*/
總結
- call和apply在功能是相同的。
- 相同點在於都是用於物件的繼承,第一個引數都是thisObj.
- 不同點在於call可以有多個引數,從第二個引數開始往後的引數會依次傳給被繼承的物件做引數。apply只有兩個引數,第二個引數必須是陣列型別或者arguments物件型別,而且他會把陣列中的元素依次傳遞給被繼承的物件做引數。
- 通過以上幾點,我們可以得到如果被繼承的物件只有一個引數的可以使用call,如果被繼承的物件有多個引數的,建議使用apply.
補充
- js中可以實現多繼承,只需要呼叫多次call或apply即可。如:
function animal(type,nickname){
this.type = type;
this.nickname = nickname;
this.syaHello = function(){
return 'hello';
}
}
function wscat(name,age){
this.name = name;
this.age = age;
this.sayMe = function(){
return 'my name:' + this.name + ', age:' + this.age;
}
}
function cat(name,age,type,nickname){
//第一種使用call
animal.call(this,type,nickname);
wscat.call(this,name,age);
//第二種使用apply
//animal.apply(this,[type,nickname]);
//wscat.apply(this,[name,age]);
}
console.log(new cat('wscat',2,'cat','tom');
/*
cat {
type: 'cat',
nickname: 'tom',
syaHello: [Function],
name: 'wscat',
age: 2,
sayMe: [Function] }
*/
- 繼承的優化
如果建構函式this綁定了太多的屬性(比如一些共用的函式),示例化後就會照成浪費(因為this裡的屬性和方法例項化後會複製一份給新物件,多個物件之間的屬性和方法互不干涉,對於一些可以共用的方法來就會造成浪費)
所以我們一般把共用的函式都放在原型鏈(prototype)上。但是使用call和apply無法繼承原型鏈上的屬性和方法。
因此我們可以使用混合的而寫法,使用原型鏈和(apply或call)組合的方式進行繼承。
- 讓子的原型鏈指向父的示例(父的例項化物件)。如:
cat.prototype = new animal();
- 讓父的屬性建立在子的this上。如:
animal.call(this[,arg]);
//animal.apply(this[,argArray]);
具體程式碼如下:
function animal(type,nickname){
this.type = type;
this.nickname = nickname;
}
animal.prototype.sayHello = function(){
return 'hello';
}
function wscat(name,age){
this.name = name;
this.age = age;
}
//這裡是關鍵,原型鏈只能單繼承,
//不能同時繼承多個原型鏈,所以要一級一級來。
wscat.prototype = new animal();
wscat.prototype.sayMe = function(){
return 'my name:' + this.name + ', age:' + this.age;
}
function cat(name,age,type,nickname){
animal.call(this,type,nickname);
wscat.call(this,name,age);
}
cat.prototype = new wscat();
var obj = new cat('wscat',10,'cat','tom');
console.log(obj);
//animal { type: 'cat', nickname: 'tom', name: 'wscat', age: 10 }
console.log(obj.sayHello());//hello
console.log(obj.sayMe());
/*
my name:wscat, age:10
*/