Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/401.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用构造函数创建对象和返回对象有区别吗?_Javascript_Constructor_Javascript Objects_Function Constructor - Fatal编程技术网

Javascript 使用构造函数创建对象和返回对象有区别吗?

Javascript 使用构造函数创建对象和返回对象有区别吗?,javascript,constructor,javascript-objects,function-constructor,Javascript,Constructor,Javascript Objects,Function Constructor,这些功能的运行方式有什么不同吗?第一个问题更典型地反映了我在考虑构造函数时的想法 示例1:使用此选项命名和设置属性。然后使用new创建一个新的Book对象 function Book(name, numPages) { this.name = name; this.numPages = numPages; } var myBook = new Book('A Good Book', '500 pages'); 示例2:使用new返回一个

这些功能的运行方式有什么不同吗?第一个问题更典型地反映了我在考虑构造函数时的想法

示例1:使用此选项命名和设置属性。然后使用new创建一个新的Book对象

    function Book(name, numPages) {
        this.name = name;
        this.numPages = numPages;
    }

    var myBook = new Book('A Good Book', '500 pages');
示例2:使用new返回一个对象,只调用函数本身

    function Movie(name, numMinutes) {
        return { name:name, numMinutes:numMinutes };
    }

    var best = new Movie('Forrest Gump', '150');

    var other = Movie('Gladiator', '180');

我想我想弄清楚的是,它们创建对象的方式是否不同?如果是这样的话,一个比另一个好吗?在不同的情况下,一个会比另一个更好吗?

基本上,当您使用
new
时,JS引擎会为您创建一个全新的对象,并将其作为
this
的值注入。它还会自动为您提供附加到构造函数原型的任何方法。使用构造函数还可以让您更容易地检查对象是否是某个对象

function MovieA(title) {
    this.title = title;
}
MovieA.prototype.getTitle = function() {
    return this.title;
};

function MovieB(title) {
    return {
    title: title
  };
}
MovieB.prototype.getTitle = function() {
    return this.title;
};

var a = new MovieA('A');
console.log(a instanceof MovieA); // true
console.log(a.getTitle()); // 'A'

var b = MovieB('B');
console.log(b instanceof MovieB); // false
console.log(b.getTitle()); // Uncaught TypeError: b.getTitle is not a function
new
为您提供的一切都可以通过其他方法获得,但需要更多的体力劳动

第二种方法,工厂,在单元测试、自定义对象创建和函数编程方面更有效。它对单元测试更有效,因为如果您有一个工厂生产所有对象,您可以用一个模型来替换该工厂,以测试不同的情况

var Factory = {
  makeThing: function() {
    return { name: 'thing' };
  }
};

// Want to test the case for if makeThing fails inside of some other code
var MockFactory = {
  makeThing: function() {
    return null;
  };
};

至于你什么时候用这两种方法,这要看情况而定。有些人根本不使用
new
。其他人专门使用
new
。这完全取决于您是否需要上面列出的任何东西,您需要对对象的创建进行多大程度的控制,何时需要使用
,等等。最后,这都是一个偏好问题。

第一个是构造函数,因此可以通过
原型
进行扩展,您可以通过
instanceof
测试结果是否为这种类型的实例。 缺点:如果您忘记了
new
-关键字,您的代码将崩溃(除非您在每个
构造函数中都编写了相应的解决方法)

当你实例化一个新对象时,你不能用构造函数来传递一个参数数组;另一方面,不要这样做,即使你可以/可以

第二个是工厂,不是构造器。无论您是否使用
新的
-关键字,都是独立的。 通过此实现,它创建了外观相同但不共享类型或原型的对象(尽管底层JS引擎将它们识别为相似的对象,因此它们共享相同的隐藏类,只要它们具有相同的属性,以相同的顺序添加,…不同的主题)
长话短说,这种方法(不再)会影响性能和内存占用

但你不能检查它们是否属于同一类型,你也没有一个可能影响所有实例的共享原型(可能是赞成或反对)

如果我需要继承,我的goto方法是两者的混合:
(如果我只需要一个数据对象,我通常使用工厂和普通对象)

如果我在函数顶部添加以下行,我还可以使用它作为一种方法,将任何内容强制转换到
Book
的实例中,而无需克隆现有实例

function Book(conf) {
    //with this simple line I can also use this as a function to cast anything into a "Book"
    if(conf instanceof Book) return conf;

    var book = Object.create(Book.prototype);
    //...
    return book;
}

var data = [
    "Peter Pan",
    {name: "American Gods"},
    //...
];

var books = data.map(Book);

在我看来,这种方法有两方面的好处。

区别在于用于创建返回对象的构造函数

new Book('A Good Book', '500 pages');
创建
Book
对象实例,实例继承
Book.prototype
的属性,包括
Book
构造函数
属性值。
Book.prototype
对象本身继承自
object.prototype

var other = Movie('Gladiator', '180');
Movie
用作工厂函数(
new
非必需),并返回一个对象实例,该实例直接从
对象继承属性。prototype
,包括
对象的
构造函数
属性值


更简单地说,Object literal语法创建一个Object对象。

返回一个literal不会通过构造函数上的
.prototype
道具提供继承。如果您想要继承,请使用“new”+构造函数。如果没有,请使用工厂,如第二段代码。在第二段代码中,
new
被忽略。不必要地创建了从
Movie.prototype
继承的空对象。不要将
new
与工厂功能一起使用。不,它们不一样。你不应该用第二个。在这里,您不再从Movie.prototype继承,例如
other/best instanceof Movie//returns false
。我建议您阅读以下内容:评估和比较方法所依据的“更好”需求标准可能重复。这两种方法当然不同,结果也不同,这取决于您的需求。
var other = Movie('Gladiator', '180');