本章的主題是繼承,分為上下兩部分來介紹,上主要來介紹call和apply方法,下用來介紹繼承的幾種實現方式。
在介紹繼承的時候,call和apply是一個繞不過去的話題,也是大傢需要深入瞭解的知識。下面我們來看看call的定義(apply和call基本是一樣的,隻是參數不同,這裡不做介紹瞭):
?
call 方法
請參閱
應用於:Function 對象
要求
版本 5.5
調用一個對象的一個方法,以另一個對象替換當前對象。
call([thisObj[,arg1[, arg2[, [,.argN]]]]])
參數
thisObj
可選項。將被用作當前對象的對象。
arg1, arg2, , argN
可選項。將被傳遞方法參數序列。
說明
call 方法可以用來代替另一個對象調用一個方法。call 方法可將一個函數的對象上下文從初始的上下文改變為由 thisObj 指定的新對象。
如果沒有提供 thisObj 參數,那麼 Global 對象被用作 thisObj。
定義總是讓人看不懂,還是直接上例子直接。
例1:
function Person(name) {
this.name = name;
this.getName = function () {
return this.name;
}
}
function Man(name, age) {
Person.call(this, arguments[0]);
this.age = age;
this.setAge = function (age) {
this.age = age;
}
}
var man = new Man('jason', 'man');
alert(man.getName()); //jason
以Person.call(this,argument[0])為例:
call方法的調用者:一個對象的方法(在js裡面方法/函數也是對象),調用者為,Person
call方法的參數:一個新對象(man),這個對象的作用是“攔截”對象Person,來運行本來屬於Person的getName方法;而 argument[0]就是給method傳遞參數瞭
call方法的結果:Person.call(man,argument[0])類似於:man=new Person(argument[0])
call方法的作用:Person方法得到重用、共享,有new的特效,實現繼承。
那麼通過call到底能繼承什麼內容呢?我通過下面的例子做以介紹。
上面的例子是在構造函數裡面調用瞭call,那麼在構造函數外,代碼運行的過程中能否實現繼承呢?
例子2:
function Person(name) {
this.name = name;
this.getName = function () {
return this.name;
}
}
function Man(name, age) {
this.age = age;
this.setAge = function (age) {
this.age = age;
}
}
var man = new Man('jason', '25');
Person.call(man, 'jason');
alert(man.getName());//jason
通過測試,man繼承瞭Person的getName函數。前兩次都是用Person去調用call方法,這次我們換成person,看看效果如何。
例3:
function Person(name) {
this.name = name;
this.getName = function () {
return this.name;
}
}
function Man(name, age) {
this.age = age;
this.setAge = function (age) {
this.age = age;
}
}
var person = new Person('person');
var man = new Man('jason', '25');
person.call(man, 'jason');
alert(man.getName()); //person.call is not a function
結果報錯,原因是其實很簡單,call的調用者隻能是Function 對象,person是Function的實例,Person才是Function對象。
那麼這次我們用person.getName來調用call,看會是什麼樣的結果。
例4:
function Person(name) {
this.name = name;
this.getName = function () {
return this.name;
}
}
function Man(name, age) {
this.age = age;
this.setAge = function (age) {
this.age = age;
}
}
var person = new Person('person');
var man = new Man('jason', '25');
person.getName.call(man, 'jason');
alert(man.getName()); //man.getName is not a function
在這裡肯定會有人疑問瞭,不是隻要做為方法就能調用call嗎,那man就應該繼承getName啊。前半句話是對的,但是後半句就不一定瞭。那通過call到底繼承瞭哪些內容呢?
例5:
function Person(name) {
this.name = name;
this.getName = function () {
this.address = 'address'; //代碼稍加改動,在getName方法中增加瞭一個變量
return this.name;
}
}
function Man(name, age) {
this.age = age;
this.setAge = function (age) {
this.age = age;
}
}
var person = new Person('person');
var man = new Man('jason', '25');
person.getName.call(man, 'jason');
//在這裡我們遍歷man,看他到底包含瞭哪些對象
for (pro in man) {
alert(pro + ":" + man[pro]);
}
//輸入結果:
//age:25
//setAge:function (age) {
// this.age = age;
//}
//address:address
結果很特別吧,居然多瞭一個address。結果也就很明顯瞭,調用call,call的被調用者會繼承調用者內部的實例對象,而不是調用者本身。
下面我們在做最後一個測試,看call是否能繼承對象的prototype裡面的對象。
例6:
function Person(name) {
this.name = name;
}
Person.prototype.getName = function () {
return this.name;
}
function Man(name, age) {
this.age = age;
this.setAge = function (age) {
this.age = age;
}
}
var man = new Man('jason', '25');
Person.call(man, 'jason');
alert(man.getName()); //man.getName is not a function
結果很顯然,通過call不能繼承調用者的prototype對象,他隻能繼承調用者內部的實例對象。
今天的內容就到此瞭,希望對大傢有幫助。
作者:kbh1983