【问题标题】:Shorthand for Object.create() with multiple properties具有多个属性的 Object.create() 的简写
【发布时间】:2017-04-23 01:24:00
【问题描述】:

如果我想在 JavaScript 中创建一个对象,它有一个原型链接到另一个对象,但它有几个自己的属性,我该怎么做?

var object1 = {
  a: 1,
  b: 2
};

var object2 = Object.create( object1 );
object2.c = 3;
object2.d = 4;

console.log( object2 ); // my new object with object1 as it's prototype link

我的挑战是我必须一次设置一个object2 的属性。

我的另一个选择是:

var object1 = {
  a: 1,
  b: 2
};

var object2 = {
  c: 3,
  d: 4
};
    
Object.setPrototypeOf( object2, object1 );

console.log( object2 );

我上面的挑战是性能应该很糟糕。也就是说,setPrototypeOf 很慢。 https://jsperf.com/object-create-vs-object-setprototypeof

当然,还有你提供的“速记”,writeableenumerable 以及所有这些到Object.create(),但这并不是真正的速记。

有什么想法吗?

【问题讨论】:

  • 你总是可以var object2 = Object.assign(Object.create(object1), {c: 3, d: 4}));?
  • 实际上,这是Object.setPrototypeOf 可接受的用例之一,而且很容易优化。如果它对您来说太慢,您应该向您的浏览器供应商提出问题。

标签: javascript ecmascript-6 ecmascript-5


【解决方案1】:

通常,当我们谈论设置和交换原型时,我们谈论的是被实例化为对象而不是对象字面量本身的构造函数。

您当然可以,在这种情况下,您只需自己手动切换原型(这是原型继承的基础),这将导致您继承正确的属性,但您现在还必须处理派生实例时的构造函数问题制作对象。

但是,这种技术很快,因为它只需要创建一个新实例,然后在原型属性中设置该引用。

function object1(){
  this.a = 1;
  this.b = 2;
  console.log("object1 has been invoked");
};

function object2(){
  console.log("object2 has been invoked");
  this.c = 3;
  this.d = 4;
};
    
// It's very important that the prototype be set to a NEW instance
// of the super-object so that you don't wind up sharing a prototype
// with other unintended objects.
object2.prototype = new object1();

// object2.prototype.constructor was the function object2
// But now that object2 has had its prototype swapped out
// to object1, when new instances of object2 are made, the
// constructor for object1 will execute. To fix this, we
// just need to reset the constructor property of the new
// prototype that we just set. That's another reason we created
// a new instance of object1, so we could modify the constructor
// of that instance without screwing up other instances of object1
// that may be in use. object2 will use object1 as 
// it's prototype, but that particular instance of object1
// will have object2 set as the constructor to use when instances
// are needed.
object2.prototype.constructor = object2;

console.log( new object2() );

【讨论】:

    【解决方案2】:

    作为Object.assign 的替代方案,请记住Object.create 接受带有要添加到对象的属性描述符的第二个参数:

    var object1 = {
      a: 1,
      b: 2
    };
    var object2 = Object.create(object1, {
      c: {value: 3, enumerable: true},
      d: {value: 4, enumerable: true}
    });
    console.log( object2 ); // my new object with object1 as it's prototype link

    注意默认是不可配置、不可写和不可枚举的。

    如果这是个问题,ES2017 引入了Object.getOwnPropertyDescriptors

    var object1 = {
      a: 1,
      b: 2
    };
    var object2 = Object.create(object1, Object.getOwnPropertyDescriptors({
      c: 3,
      d: 4
    }));
    console.log( object2 ); // my new object with object1 as it's prototype link

    【讨论】:

      【解决方案3】:

      为此,您可以将Object.createObject.assign 结合使用:

      var object2 = Object.assign(Object.create(object1), {
          c: 3,
          d: 4
      });
      

      【讨论】:

        猜你喜欢
        • 2012-03-29
        • 2021-12-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-13
        • 1970-01-01
        • 2015-08-23
        • 2019-04-15
        相关资源
        最近更新 更多