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

What's the difference between return vs. new keyword Constructor patterns?

本文关键字:区别 是什么 模式 构造函数 new 关键字 return      更新时间:2023-09-26

考虑以下代码:

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关键字的一些用例是什么?

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

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

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

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

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

让我们用下面的例子创建一个vector对象。对于第一个方法,您可以这样做:

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}

这样,就可以创建多个向量类型,并且每个类型都可以有一个单独的add函数,而不会相互干扰。

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