【问题标题】:What's the difference between return vs. new keyword Constructor patterns?return 与 new 关键字构造函数模式有什么区别?
【发布时间】:2016-10-29 21:05:36
【问题描述】:

考虑以下代码:

var Animal = function(name) {
  return {
    name: name,
    speak: function() { return "My name is " + name; }
  };
};

var cat = Animal("Kitty");

我的问题是:上面的代码和下面的代码在性能、约定或最佳实践方面有什么区别:

var Animal = function(name) {
  this.name = name,
  this.speak = function() { return "My name is " + name; }
};

var cat = new Animal("Another Kitty");

哪一个更可取? new 关键字有哪些用例?

【问题讨论】:

  • 这是一个不错的起点,可以让您的仓鼠车轮滚动:Ian Bicking - "new" only makes Javascript OO harder
  • 请将您的问题限制在客观差异上。主要基于意见的问题有一个特定的离题原因,这就是您的问题在当前状态下的样子。
  • 第一个创建一个普通对象,第二个创建一个Animal 实例(“继承”自Animal.prototype)。 “哪个更可取?” 取决于你问谁。有些人会不惜一切代价避免new
  • Rafay 虽然这个问题可能会因为重复而关闭,但感谢您提出这个问题。重复也很有用,因为它们会添加新的关键字来查找相同的信息。

标签: javascript object javascript-objects


【解决方案1】:

当您考虑原型(以及它们控制的所有内容,例如继承)时,它们是完全不同的。例如:

var SimpleAnimal = function(name) {
  return {
    name: name,
    speak: function() { return "My name is " + name; }
  };
};

var RealAnimal = function(name) {
  this.name = name,
  this.speak = function() { return "My name is " + name; }
};

var simpleCat = SimpleAnimal("Kitty");
var realCat = new RealAnimal("Another Kitty");

console.log(simpleCat instanceof SimpleAnimal, realCat instanceof RealAnimal); // simple is not an instance of the constructor
console.log(simpleCat.constructor, realCat.constructor); // because it uses the object literal constructor

缺少原型(和继承)意味着您的对象不会收到在类原型上定义的任何方法:

var SimpleAnimal = function(name) {
  return {
    name: name,
    speak: function() {
      return "My name is " + name;
    }
  };
};

SimpleAnimal.prototype.roar = function() {
  console.log("roar!");
};

var RealAnimal = function(name) {
  this.name = name,
    this.speak = function() {
      return "My name is " + name;
    }
};

RealAnimal.prototype.roar = function() {
  console.log("roar!");
};

var simpleCat = SimpleAnimal("Kitty");
var realCat = new RealAnimal("Another Kitty");

try { simpleCat.roar(); } catch (e) { console.error(e); }
realCat.roar();

【讨论】:

  • 这是我见过的关于这个主题的最清晰、最简洁的演示。
【解决方案2】:

第一个版本返回一个简单的 Object,第二个版本创建一个新的 Animal。

第一个版本适用于小数据对象。它们可以存储不同的值,仅此而已。它们不需要大量内存。

第二个是更大的对象。您可以将原型附加到它们并使用“this”关键字来访问对象的属性。因为每个对象都具有相同的属性,所以它们比第一种方法占用更多的空间。

让我们使用以下内容并创建一个矢量对象。使用第一种方法,您将执行以下操作:

function createVector(x, y) {
    return {
        x: x,
        y: y
    };
}

//Add to vectors together
function add(vec1, vec2) {
    return {x: vec1.x + vec2.x, y: vec1.y + vec2.y};
}

add(createVector(1, 1), createVector(1, 2)); //return {x: 2, y: 3}

这可能非常有用,但是如果您想拥有多种类型的向量(3 维、4 维等)怎么办?您需要为加法器函数指定一个单独的名称,这不是很好。这就是第二种方法的用武之地。它可以将函数分离到不同的命名空间中:

function Vector2(x, y) {
    this.x = x;
    this.y = y;
}

//Add vectors together:
Vector2.prototype.add = function(vec) {
    this.x += vec.x;
    this.y += vec.y;
};

new Vector2(1, 1).add(new Vector2(1, 2)); //{x: x, y: y}

这样,您可以创建多个向量类型,并且每个向量类型都可以具有单独的添加功能,而不会相互干扰。

你应该根据你想要达到的目标来使用它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-12
    • 1970-01-01
    • 2021-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-25
    相关资源
    最近更新 更多