【问题标题】:Object.create and reference propertiesObject.create 和引用属性
【发布时间】:2012-10-07 00:23:23
【问题描述】:

您如何处理在其子级之间共享原型的引用属性的问题?是否有任何众所周知的模式(除了在构造函数中重新定义属性)来解决这个问题?这是一个问题,还是我缺少关于原型继承的一些东西?

例子:

var dog = 
{
    name: "no-name",
    paws: ["front-right", "front-left", "back-right", "back-left"]
};

var rex = Object.create(dog);
rex.name = "Rex";

var bingo = Object.create(dog);
bingo.name = "Bingo";
bingo.paws.pop(); //Bingo is just like a dog, but has lost a paw in a tragic accident

console.log(bingo.paws); //["front-right", "front-left", "back-right"]
console.log(rex.paws); //Rex lost a paw too! ["front-right", "front-left", "back-right"]


更新:

在研究了原型继承之后,在我看来,这种范式中“自然”的编程方式是扩展对象,而不是在将它们用作“类”的意义上过多依赖构造函数。我在博客上看到的示例(而且它似乎也与 Douglas Crockford 的Object.create 一致)或多或少是这样的:

var Dog = 
{
    name: "no-name",
    paws: ["front-right", "front-left", "back-right", "back-left"],
    bark: function() { alert("Bark!!"); }
};

//No constructor acting like a "class"
var BigDog = Object.create(Dog);
BigDog.bark = function() { alert("WOLF!!!"); };

var thor = Object.create(BigDog);
thor.name = "Thor";
thor.bark();

构造函数是在新实例上复制或创建新数组的唯一方法吗? Object.create这个模式是不是“不完整”?

感谢您的回答!

【问题讨论】:

  • 创建一个构造方法,返回一个带有数组副本的完全限定对象。
  • 引用类型会有这个问题。您只需要以某种方式手动将引用类型直接放在对象上而不是原型上。
  • 这里的学习总是把函数放在原型对象中,把属性(每个实例可能有单独的副本)放在构造函数中。

标签: javascript prototype design-patterns object-create


【解决方案1】:

你应该看看模块模式

制作一个可以使用的封闭物,以便您的狗可以分开

var dog = function(){
 //private
 var name = "no-name";
 var paws = ["front-right", "front-left", "back-right", "back-left"];

 //public
 function getName(){
  return name;
 }

 function setName(newName){
  name = newName;
 }

 function getPaws(){
  return paws;
 }

 function pawPain(){
  paws.pop();
 }

 //expose
 return{
  pawPain: pawPain,
  getPaws: getPaws,
  getName: getName,
  setName: setName
 };
};

现在你可以用它来制作新狗了

var rex = new dog();    
var bingo = new dog();
rex.pawPain();
console.log(bingo.getPaws());

【讨论】:

  • 您对this 的使用不太正确。您的一些方法使用this 而不是引用局部变量。
【解决方案2】:

http://jsfiddle.net/sVaSp/

只需要一个构造函数。每个版本都有自己的对象副本。

    function dog(name) {
        this.name = "no-name",
        this.paws = ["front-right", "front-left", "back-right", "back-left"]
    } 

    var rex = new dog();
    rex.name = "Rex";

    var bingo = new dog();
    bingo.name = "Bingo";
    bingo.paws.pop(); //Bingo is just like a dog, but has lost a paw in a tragic accident

    console.log(bingo.paws); //["front-right", "front-left", "back-right"]
    console.log(rex.paws); //Rex lost a paw too! ["front-right", "front-left", "back-right"]​

【讨论】:

    【解决方案3】:

    如您所知,对象的原型是一个包含构成该对象的基本属性的对象。与所有对象一样,该原型对象是名称到值的映射。 javascript 中的数组(和对象)总是通过引用传递,因此当在原型上调用 Object.create 时 - 它只是将数组的引用复制到新对象中。正如 TheZ 在他的评论中所说,你可以这样做:

    function Dog(){
        this.paws = ['front-right', 'front-left', 'back-right', 'back-left'];
    }
    Dog.prototype = {
        name: 'no-name',
        paws: null
    };
    

    所以现在我们可以创建我们的对象了:

    var rex = new Dog();
    rex.name = 'Rex';
    
    var bingo = new Dog();
    bingo.name = 'Bingo';
    bingo.paws.pop();
    

    【讨论】:

    • Object.create 不能与数组参数一起使用,因为您仍然只是创建一个具有数组的 reference 的新对象,而不是一个新的数组。
    • 太难过了...用更少的行创建类和对象会更好=/
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-04
    • 2017-04-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多