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

标签 javascript

注意:这不是关于经典继承和原型(prototype)继承的问题。它是关于使用什么编码模式来初始化对象。类构造函数创建和初始化对象,而避免使用 new 运算符并使用 Object.create() 仅创建对象并设置原型(prototype)链。我还没有找到解释在使用 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.createnew 因为那些是为了继承 你说你不关心。这会让你做:

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

这也不会设置原型(prototype),因为函数不像构造函数那样被调用。参见 this answer关于原型(prototype)答案做什么和不做什么 - 总而言之,它是关于共享功能,而不是关于构建对象的属性。

关于javascript - 初始化对象的编码模式 - 构造函数(新)与 Object.create() (Crockford),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27858568/

相关文章:

javascript - window.location.host 和 window.location.hostname 有什么区别

JavaScript 作用域问题

javascript - 无法将 Javascript 符号绑定(bind)到 HTMLElement.style

Javascript 在对象中添加项目

javascript - 提交后重置表单

javascript - 仅用于浏览器关闭的确认消息。不在窗口选项卡关闭时

javascript - 如何实现可折叠的导航栏?

javascript - 不一致的 Javascript 元素控制

javascript - 如果文本字段值匹配,则单击时更改按钮图像源

javascript - Google 热图仅显示一处