面向對象-非構造函數的繼承

1.最近一直再看javascript高級程序設計3,面向對象章節,前面寫了兩篇讀書筆記javascript

(1)構造函數 --建立對象
(2)構造函數的原型鏈繼承
如今又在網上看到阮一峯大大的一篇非構造函數繼承的文章,特地借來學習一下!

非構造函數繼承--阮一峯html

一:什麼是非構造函數的繼承?
    好比:一個對象叫作中國人
        一個對象叫作醫生
var Chinese = {
    nation:"中國"
}
var doctor = {
    career:"醫生"
}

怎樣才能讓「醫生」去繼承「中國人」,也就是說,我怎樣才能生成一個「中國醫生」的對象?
這裏注意。這兩個都是用字面量方法建立的普通對象,不是構造函數沒法使用構造函數的原型鏈繼承的方法的實現繼承。java

第一種:object方法jquery

json格式發明人提出的一種方法
function object(o){
    function F(){};    // 建立一個空構造函數
    F.prototype = o;   // 原型對象指向父對象
    return new F();
}

這個object函數的做用就是將子對象的prototype屬性指向父對象,從而使的父子對象連在一塊兒json

(1)使用時先在父對象基礎聲稱子對象數組

var Doctor = object(Chinese);

(2)而後給自對象賦上本身的屬性函數

var Doctor.carrer = "醫生";

(3)這樣子對象就繼承了父對象的屬性了學習

alert(Doctor.nation);  // "醫生"

clipboard.png

第二種:淺拷貝this

除了使用「prototype」鏈之外,還有另外一種思路:就是把父對象的屬性,所有拷貝給子對象,也能實現繼承。
下面這個函數,就是在作拷貝:
function extendCoby(p){
    var c = {};
    for(var i in p){
        c[i] = p[i];
    }
    c.uber = p; // 軟大大:uber是一個德語詞,意思是"向上"、"上一層"
    return c;
}
使用的時候,這樣寫
var Doctor = extend(Chinese);
Doctor.carrer = "醫生";
alert(Doctor.nation);  // 中國

clipboard.png

可是這樣的拷貝有一個問題。那就是,若是父對象的屬性等於數組或另外一個對象,那麼實際上,子對象得到的只是一個內存地址,而不是真正的拷貝,所以存在父對象被篡改的可能。spa

請看如今給Chinese添加一個出生地屬性,它的值是一個數組。

Chinese.birthPlace = ['北京','上海','香港'];

經過extendCopy()函數,Docttor繼承了Chinese

var Doctor = extendCopy(Chinese);

而後咱們爲出生地添加一個城市:

Doctor.birthPlace.push("廈門");

此時,發生了什麼事?

alert(Doctor.birthPlace);   // 北京,上海,香港,廈門
alert(Chinese.birthPlace); //  北京,上海,香港,廈門

clipboard.png

因此,extendCopy()只是拷貝基本數據類型,咱們把這種拷貝叫作淺拷貝。
這是早期的jquery實現繼承的方式

第三種 深拷貝

所謂深拷貝,就是可以真正意義上的數組和對象的拷貝。
它的實現並不難,只要遞歸調用淺拷貝就能夠啦
function deepCopy(p,c){ //參數p,c順序萬不可寫反,由於第一次c爲空
    var c = c || {};   // 第一次執行函數的時候 c爲 空對象
    for(var i in p){
        if(typeof p[i] === 'object'){ // 判斷對象p的一個屬性值是否爲複雜數據類型object或array
            // [] 或 {} 判斷
            c[i] = (p[i].constructor === Array) ? [] : {};
            deepCopy(p[i],c[i]);         // 遞歸調用此方法
        }else{
            c[i] = p[i];                //簡單數據類型直接賦值
        }
    }
    return c;                          // 將新對象c返回出來
}
var Chinese = {
    nation:"中國",
    place:["A","B","C"],
    say:function(){
        alert(this.nation);
    }
}
var Doctor = deepCopy(Chinese); // 調用deepCopy建立新對象
Doctor.carrer = "醫生";
Doctor.place.push("X");
console.log(Doctor);
console.log(Chinese);

clipboard.png

此方法是目前jq實現集成的方法

感悟:我的感受此方法只適用簡單方法,不適合複雜對象,複雜對象仍是得靠構造函數原型鏈的繼承!

相關文章
相關標籤/搜索