用于初始化对象的编码模式 - 构造函数(新)与 Object.create()(Crockford)

Coding patterns for initializing objects - constructors (new) vs. Object.create() (Crockford)

本文关键字:Object Crockford create 构造函数 对象 初始化 编码 模式 用于      更新时间:2023-09-26

注意:这不是一个关于经典和原型继承的问题。这是关于使用什么编码模式来初始化对象。类构造函数创建和初始化对象,而避免使用new运算符并采用Object.create()只会创建对象并设置原型链。我还没有找到一个在线资源来解释在采用 Crockford Object.create() 方法时进行创建和初始化的最佳实践编码模式。

如果我有一个构造函数(在我的脑海中,这让我的类,尽管我知道类在主流 JavaScript 中在技术上还不存在)

function Person(first, last) {
  this.name = {
    first: first,
    last: last
  };
}
Person.prototype.tellName = function() {
  return this.name.first + ' ' + this.name.last;
}

然后我可以像这样实例化它

var p1 = new Person('John', 'Doe');
var p2 = new Person('Sven', 'Svensson');

并分别更改Person.name.firstPerson.name.last

p1.tellName();  // Output: 'John Doe'
p2.tellName();  // Output: 'Sven Svensson'
p1.name.first = 'Peter';
p2.name.last = 'Celery';

并使用以下输出Person.tellName()执行对象的函数

p1.tellName();  // Output: 'Peter Doe'
p2.tellName();  // Output: 'Sven Celery'

这与我在C++或Java中构建此类类的方式非常相似。


当使用 Crockford (Object.create() -ish) 方法而不是 new 时,我使用什么模式来构造或启动一个对象,我可以在其中分配给嵌套对象?

例如

...
// some code that does the same stuff as defining a class + constructor
...
var p1 = ???????
var p2 = ???????
// The following is the code and behavior I'm looking to get
p1.tellName();  // Output: 'John Doe'
p2.tellName();  // Output: 'Sven Svensson'
p1.name.first = 'Peter';
p2.name.last = 'Celery';
p1.tellName();  // Output: 'Peter Doe'
p2.tellName();  // Output: 'Sven Celery'

而不是:

function Person(first, last) {
  this.name = {
    first: first,
    last: last
  };
}
Person.prototype.tellName = function() {
  return this.name.first + ' ' + this.name.last;
}

你只需要:

function Person(first, last) {
  return {
    name: { first: first, last: last },
    tellName: function() { return this.name.first + ' ' + this.name.last; }
  };
};

或者,如果您更喜欢person.create()的外观,那么:

var person = {
  create: function(first, last) {
    return {
      name: { first: first, last: last },
      tellName: function() { return this.name.first + ' ' + this.name.last; }
    };
  }
};

但在第二种情况下,你会有一个不必要的对象(person ),只包含一个函数(person.create())。

不需要Object.create也不需要new因为这些是为了继承,你说你不在乎。这将允许您执行以下操作:

var p1 = Person('John', 'Doe');
var p2 = Person('Sven', 'Svensson');

一个有趣的事实是,如果您愿意,您仍然可以以这种方式在person.create面前使用new,但它不会提供任何效果。如果必须使用现有函数,则可以使用 .call 显式设置this上下文

// with your original `Person`
var p1 = Person.call({}, 'John', 'Doe');
var p2 = Person.call({}, 'Sven', 'Svensson');

这也不会设置原型,因为函数不像构造函数那样调用。请参阅此答案,了解原型答案的作用和不作用 - 在一行中,它是关于共享功能,而不是关于构造对象的属性。