2016-06-24 17 views
0

實施例:如何在基礎對象上聲明數據結構,使它們在每個擴展對象中保持獨立?

var Person = { 
 
    name : '', 
 
    collection : new Array(), 
 
    addToCollection : function(x) 
 
    { 
 
    this.collection.push(x); 
 
    }, 
 
    printCollection: function() { 
 
     console.log(this.collection); 
 
    } 
 
}; 
 

 

 
var skywalker = Object.create(Person); 
 
skywalker.name = 'Anakin Skywalker'; 
 
skywalker.addToCollection(1); 
 
skywalker.printCollection(); // prinnts [1] 
 

 

 
var skywalker2 = Object.create(Person); 
 
skywalker2.name = 'Anakin Skywalker 2'; 
 
skywalker.addToCollection(2); 
 
skywalker2.printCollection(); // prints [1, 2]

我想實現情況skywalker2.printCollection();打印[2]。我希望基礎對象Person關注集合,並公開像addToCollection(x)這樣的操作。

+0

明顯的錯誤:爲什麼skywalker.addToCollection(2);嘗試添加它自己的對象skywalker2.addToCollection(2); –

+0

然後你必須在通過Object.create(Person)實例化一個名爲'collection'的屬性,並且只共享設置和獲取它的函數('addToCollection'和'setToCollection')在原型中(在這種情況下爲'Person'對象) – Redu

+0

@AliTorabi感謝您指出它,但這並不會改變結果 @Redu在我的問題中,我陳述了'我希望基礎對象Person關心集合' 。通過這個我的意思是,我不想將這個集合添加到每個實例化對象。沒有辦法實現這個嗎? –

回答

1

你必須這樣做;

var Person = { 
 
    name : '', 
 
    addToCollection : function(x) 
 
    { 
 
    this.collection.push(x); 
 
    }, 
 
    printCollection: function() { 
 
     console.log(this.collection); 
 
    } 
 
}; 
 
var sw1 = Object.create(Person), 
 
    sw2 = Object.create(Person); 
 

 
sw1.collection = new Array(); 
 
sw2.collection = new Array(); 
 
sw1.addToCollection(1); 
 
sw2.addToCollection(2); 
 

 
sw1.printCollection(); // <- 1 
 
sw2.printCollection(); // <- 2

以及每個在OP在JS對象的創建提供一些信息的評論。 Object.create()將允許您定義對象的原型,並且原型中的任何內容都將在實例化對象之間共享。所以在這種情況下,集合數組是共享的。如果你不想共享collection,你只需要在實例化的對象中創建它,就像我在前面的代碼片段中展示的那樣。然而,據我所知,你不想要那樣。好的,還有一種方法可以實現這一點。我們可以將collection數組作爲私有屬性,並通過我們的原型方法通過閉包來訪問它。然後,我們將實現我們想要的。像這樣;

function collectionInClosure(){ 
 
    var collection = [], 
 
    getCollection = function(){return collection}, 
 
    setCollection = function(v) {collection.push(v)}; 
 
    return { 
 
      printCollection: function() {console.log(getCollection())}, 
 
      addToCollection: setCollection 
 
     }; 
 
} 
 

 
var sw1 = Object.create(collectionInClosure()); 
 
    sw2 = Object.create(collectionInClosure()); 
 

 
sw1.addToCollection(1); 
 
sw2.addToCollection(2); 
 

 
sw1.printCollection(); // <- 1 
 
sw2.printCollection(); // <- 2

+0

在我的問題中,我陳述了'我希望基礎對象Person關心集合'。通過這個我的意思是,我不想將這個集合添加到每個實例化對象。沒有辦法實現這個嗎? –

+0

@Tomasz Szawara通常最好保留你不想在實例化對象中共享的屬性,但是因爲你不想在這裏實現你的目標。請參閱第二個片段,並將我的解釋添加到我的答案中。 'sw1'和'sw2'對象現在都是空的。 – Redu

+0

是的,你的擴展答案與我原來的問題更相關,因爲我只要求在基類中爲每個實例化對象分別處理集合。我真正想要的是一種行爲,所有的財產都是公開的,但同時對每個實例都是分開的,對此我的回答是適合的。雖然我沒有在我的問題中準確描述它。 –

0

它非常普遍的做法,很大的便利,以便能夠在抽象基類的一些屬性,這樣我們就不需要實例化或擴展對象時,關心他們。像Java這樣的其他面向對象的經典語言對我們來說也是如此,它通常被認爲是開發人員理解的更直觀的行爲。

解決這方面的問題可以通過兩種方式來實現:

1)ES6

class Animal { 
 
    constructor(name) { 
 
    this.name = name; 
 
    this.collection = []; 
 
    } 
 
    addToCollection(x) { 
 
    this.collection.push(x); 
 
    } 
 
    printCollection() { 
 
    console.log(this.collection); 
 
    } 
 
} 
 

 
var dog = new Animal(); 
 
dog.addToCollection(1); 
 
dog.printCollection(); // prints 1 
 

 
var dog2 = new Animal(); 
 
dog2.addToCollection(2); 
 
dog2.printCollection(); // prints 2

因爲不是所有的瀏覽器都支持ES6(大多數瀏覽器都ES6默認關閉),使用Babel或類似的polyfill可以使用上面的語法。

巴別將使用ES5效仿ES6語法類似於JavaScript的:

"use strict"; 
 

 
var _createClass = function() { 
 
    function defineProperties(target, props) { 
 
    for (var i = 0; i < props.length; i++) { 
 
     var descriptor = props[i]; 
 
     descriptor.enumerable = descriptor.enumerable || false; 
 
     descriptor.configurable = true; 
 
     if ("value" in descriptor) descriptor.writable = true; 
 
     Object.defineProperty(target, descriptor.key, descriptor); 
 
    } 
 
    } 
 

 
    return function(Constructor, protoProps, staticProps) { 
 
    if (protoProps) defineProperties(Constructor.prototype, protoProps); 
 
    if (staticProps) defineProperties(Constructor, staticProps); 
 
    return Constructor; 
 
    }; 
 
}(); 
 

 
var Animal = function() { 
 
    function Animal(name) { 
 
    // .. some Babel Class checks here 
 

 
    this.name = name; 
 
    this.collection = []; 
 
    } 
 

 
    _createClass(Animal, [{ 
 
    key: "addToCollection", 
 
    value: function addToCollection(x) { 
 
     this.collection.push(x); 
 
    } 
 
    }, { 
 
    key: "printCollection", 
 
    value: function printCollection() { 
 
     console.log(this.collection); 
 
    } 
 
    }]); 
 

 
    return Animal; 
 
}(); 
 

 
var dog = new Animal(); 
 
dog.addToCollection(1); 
 
dog.printCollection(); // prints 1 
 

 
var dog2 = new Animal(); 
 
dog2.addToCollection(2); 
 
dog2.printCollection(); // prints 2

2)另一種方法是使用由巴別方法的啓發ES5語法:

var Person = function() { 
 

 
    function Person(name) { 
 
     this.name = name; 
 
     this.collection = []; 
 
     this.addToCollection = function (x) { 
 
      this.collection.push(x); 
 
     } 
 
     this.printCollection = function() { 
 
      console.log(this.collection); 
 
     } 
 
    }; 
 
    return Person; 
 
}(); 
 

 
var p1 = new Person(); 
 
p1.addToCollection(1); 
 
p1.printCollection(); // prints 1 
 

 
var p2 = new Person(); 
 
p2.addToCollection(2); 
 
p2.printCollection(); // prints 2

通過包裝構造函數Person在立即執行的函數中,我們確保每次有人實例化Person類時都會創建一個新的構造函數;

相關問題