Shorthand for Object.create() 具有多个属性

Shorthand for Object.create() with multiple properties

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

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

当然,还有 "shorthand",您提供 writeableenumerable 以及 Object.create() 的所有内容,但这并不是真正的 shorthand.

有什么想法吗?

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

你当然可以,在这种情况下你自己手动切换原型(这是原型继承的基础)并且会导致你继承正确的属性,但是你现在还必须处理构造函数问题您的派生对象已创建。

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

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() );

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

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

作为 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

更优雅的方法是使用 spread syntax.

const obj1 = { a: 1, b: 2 }
const obj2 = { ...obj1, c: 3, d: 4 }
console.table(obj1)
console.table(obj2)

您甚至可以用类似的方式向同一对象添加更多属性。

let obj = { a: 1, b: 2 }
obj = { ...obj, c: 3, d: 4 }
console.table(obj)

这也适用于数组。

let arr = [1, 2]
arr = [...arr, 3] // Equivalent to Array.push()
arr = [0, ...arr] // Equivalent to Array.unshift()
arr = [-1, ...arr, 4] // Equivalent to simultaneous Array.unshift() and Array.push()
console.table(arr)