return关键字和new关键字构造函数模式有什么区别?

4

Consider the following piece of code:

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关键字有哪些使用场景?


1
这是一个不错的起点,可以让你开始着手解决问题:Ian Bicking - "new" only makes Javascript OO harder - Sunny Patel
请限制您的问题于客观差异。针对主要基于个人意见的问题,有一个特定的离题理由,而您目前的问题似乎是以此为主。 - Heretic Monkey
第一个创建一个普通对象,第二个创建一个“继承”自Animal.prototypeAnimal实例。 “哪一个更好?” 取决于你问谁。 有些人尽量避免使用new - Felix Kling
1
可能是JavaScript中的“new”关键字是什么?的重复问题。 - Sunny Patel
Rafay,虽然这个问题可能会被关闭为重复问题,但感谢您的提问。重复问题也很有用,因为它们添加了新的关键词来查找相同的信息。 - DavidS
2个回答

2

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

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


这是我在这个主题上看到的最清晰、最简洁的示例演示。 - gfullam

1
第一个版本返回一个简单的对象,第二个版本创建了一个新的动物。
第一个版本适用于小型数据对象。它们可以存储不同的值,这就是它们的主要作用。它们不需要很多内存。
第二个版本适用于更大的对象。你可以将原型附加到它们上,并使用“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}

这很有用,但如果您想要多种类型的向量(三维、四维等等),该怎么办?您需要为加法函数分别命名,这不太好。这就是第二种方法发挥作用的地方。它可以将函数分离到不同的命名空间中:
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}

这样,您可以创建多个矢量类型,每种类型都可以有单独的添加函数,而不会相互干扰。

根据您想要实现的目标,应该同时使用它们。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接