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

时间:2015-01-09 10:29:25

标签: javascript

注意:这不是关于经典和原型继承的问题。它是关于用于初始化对象的编码模式。类构造函数创建和初始化对象,而避免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时,我可以使用哪些模式构建或启动可以分配给嵌套对象的对象?

E.g。

...
// 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'

1 个答案:

答案 0 :(得分:3)

而不是:

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

一个有趣的事实是,如果你愿意,你可以仍然<{1}}以new的方式使用person.create,但它不会产生影响。如果 使用现有功能,您可以使用this

明确设置.call上下文
// with your original `Person`
var p1 = Person.call({}, 'John', 'Doe');
var p2 = Person.call({}, 'Sven', 'Svensson');

这不会设置原型,因为函数不像构造函数那样被调用。请参阅this answer关于原型答案的作用和不做的事情 - 在一条线上它是关于共享功能它不是关于构建对象的属性。