淺談 OOP JavaScript原型

上一章我們談了構造函數,他的唯一特點就是比較了地址不相同,因為大家知道引用類型是比較的引用。我們來談談 原型。

原型

我們每創建一個函數都有一個原型(prototype)屬性,這個屬性是一個對象,他的特點是 共享 。也就是說不用在構造函數中定義對象實例,而是直接將這些添加到原型當中。

function Create () {}    //聲明一個構造函數
Create.prototype.a = 'abc';    //在原型中添加屬性
Create.prototype.b = 10;
Create.prototype.c = function () {    //在原型中添加方法
    return this.a + this.b;
};
var create = new Create();    
alert(create.c());    //返回abc10

我們這次再來比較一下原型中方法的地址是否一致:

var create = new Create();
var create1 = new Create();
alert(create.c == create1.c);    //true

是不是還沒明白?我們用一張圖來告訴大家:

這個__proto__就相當于指針,指向了原型對象的constructor,而constructor就相當于將構造函數對象和原型對象相關聯。

那么我們要用構造函數對象去給重寫 屬性或者方法 會怎么樣呢?

var create = new Create();
create.a = 'EFD';
alert(create.a);    //返回EFD

真的將原型對象里面的 a 給覆蓋了么?并沒有:

var create1 = new Create();
alert(create.a);    //返回abc

原型模式的執行過程:

1.先去查找構造函數里面的屬性和方法 ,如果有就立即返回。

2.如果構造函數實例里面沒有,就去原型里面查找,如果有就立即返回。

因為我們在構造函數添加了屬性,所以它會自動去查找,構造函數里面的屬性也就立即返回了!

原型的字面量

在原型中,我們也可以使用字面量的方式去創建,可以讓屬性和方法體現出更好的封裝效果。

function Create(a,b){};    //聲明一個構造函數
Create.prototype = {    //字面量方式
    a:'abc',
    b:10,
    c:function () {
        return this.a + this.b;
    }
};

不知道大家有沒有發現,我們用字面量的方式是這樣的:Create.prototype ={};

大家都知道,用一個{}就等同于new Create();這樣,我們就相當于新聲明的一個對象,我們原型對象里面的constructor還會指向Create么?

var create = new Create();
alert(create.constructor == Create);    //false
alert(create.constructor == Object);    //true

(我們來解釋一下為什么用create.constructor,因為我們打印constructor就會將整個構造函數打印出來,因為上面講過它是將構造函數對象和原型對象相關聯的屬性。)

通過上面的例子可以看出,它已經指向了新的實例對象。

constructor的巧妙用法:

我們可以使用constructor來強制指回原來的實例對象:

function Create(a,b){};
Create.prototype = {
    constructor:Create,
    a:'abc',
    b:10,
    c:function () {
        return this.a + this.b;
    }
};

原型對象的重寫問題:

大家都知道,構造函數的屬性和方法重寫是無傷大雅的,但是原型對象中可以重寫么?

function Create(a,b){};
Create.prototype = {
    constructor:Create,
    a:'abc',
    b:10,
    c:function () {
        return this.a + this.b;
    }
};

Create.prototype = {
    a:'EFD',
};
var create = new Create();
alert(create.c());    //create.c is not a function

不難看出,我們重寫了原型會將之前的原型指向切斷!!!

原型模式的缺點:

其實它的缺點也是它優點: 共享

我們在字面量里面給原型對象添加一個數組就很容易的看出來了:

function Create(a,b){};
Create.prototype = {
    constructor:Create,
    a:'abc',
    b:10,
    c:[第一個,第二個,第三個],
    d:function () {
        return this.a + this.b + this.c;
    }
};
var create = new Create();
create.c.push('第四個');
alert(create.run());    //返回abc10第一個第二個第三個第四個

我們看得出這時候push添加已經生效了,在數組的末尾添加了“第四個”

我們再來實例一個對象就能看得出他的共享問題了:

var create1 = new Create();
alert(create1.run());    //返回abc10第一個第二個第三個第四個

這就是共享問題。下面新實例化一個對象也會將上面添加的字符串給共享到這里來。

這一章就到這里。 歡迎所有閱讀文章的人指正錯誤!

Brian Lee

 

來自:https://segmentfault.com/a/1190000007623594

 

 本文由用戶 DanYOU 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!