javascript設計模式–繼承(上)

來源:互聯網
上載者:User

  本章的主題是繼承,分為上下兩部分來介紹,上主要來介紹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對象,他只能繼承調用者內部的執行個體對象。

  

  今天的內容就到此了,希望對大家有協助。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.