使用构造函数创建对象和返回对象有区别吗
Is there a difference in using a constructor to create an object versus returning an object?
这些函数的操作方式有什么不同吗?第一个更典型的是我在考虑构造函数时的想法。
示例1:使用this命名和设置属性。然后使用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');
我想我想弄清楚的是,它们创建对象的方式是否不同?如果是这样,一个比另一个好吗?有没有不同的情况下,一个会比另一个工作得更好?
第一个是构造函数,因此可以由prototype
扩展,您可以通过instanceof
测试结果是否为此类型的实例。缺点:如果你忘记了new
-关键字,你的代码就会爆炸(除非你在每个constuctor
中都写了一个解决方法)
当实例化一个新的Object时,不能真正将apply()
与构造函数一起使用来传递参数数组;另一方面,不要那样做,即使你可以。
第二个是工厂,而不是建造商。与是否使用new
-关键字无关。通过该实现,它创建了看起来相同但不共享类型或原型的对象(尽管底层JS引擎将它们识别为相似,因此只要它们具有相同的属性、以相同的顺序添加、…不同的主题,它们就共享相同的隐藏类)
长话短说,无论是性能还是内存占用都不会受到这种方法的影响
但你无法检查它们是否属于同一类型,也没有一个可能影响所有实例的共享原型(可能是赞成或反对)
我的goto方法如果我需要继承,是两者的混合:
(如果我只需要一个数据对象,我通常使用工厂和普通对象)。
function Book(conf) {
var book = Object.create(Book.prototype);
//a book like this usually has multiple configs/properties
if(typeof conf === "object"){
for(var k in conf) book[k] = conf[k];
}else if(conf){
//assuming that I get at least the name passed
book.name = String(conf);
}
return book;
}
//I have a prototype that can be extended
//with default-values for example; no idea for a good method
//to add to the prototype in this example ;)
Book.prototype.numPages = 0;
//but I can also use it like a plain function; no error if you
var myBook1 = Book("Peter Pan");
var myBook2 = Book({
name: "American Gods",
author: "Neil Gaiman"
});
如果我在函数的顶部添加以下行,我也可以将其用作一种方法,将任何内容强制转换到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
时,JS引擎会为您创建一个全新的对象,并将其作为this
的值注入。它还自动为您提供任何附加到构造函数原型的方法。使用构造函数还可以更容易地检查对象是否是instanceof
。
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
。这一切都取决于你是否需要上面列出的任何东西,你需要对对象的创建有多大的控制,你什么时候想使用this
,等等。最后,这都是你的偏好问题。
不同之处在于用于创建返回对象的构造函数。
new Book('A Good Book', '500 pages');
创建一个Book
对象实例,该实例继承Book.prototype
的属性,包括Book
的constructor
属性值。Book.prototype
对象本身继承自Object.prototype
。
var other = Movie('Gladiator', '180');
使用Movie
作为工厂函数(不需要new
),并返回一个Object对象实例,该实例直接继承Object.prototype
的属性,包括Object
的constructor
属性值。
更简单地说,Object字面语法创建一个Object对象。
- "#"keyCode=222 vs 51(Chrome与Android版Chrome)-为什么有区别
- 定义这些对象有什么区别
- javascript 的 Set 和普通的普通对象有什么区别
- smoothstate.js和pjax有区别
- JavaScript中的嵌入循环和嵌套循环之间有区别吗
- XUL文档与HTML文档对象有何不同
- jQuery递归函数调用和Javascript之间有区别吗;s setInterval
- 使用构造函数创建对象和返回对象有区别吗
- 数字和数字对象有什么区别
- 使用 Object.create() 和 Object.assign() 创建对象有什么区别?
- 在Durandal视图模型中返回函数和返回对象有什么区别
- javascript构建对象.有什么区别和最好的方法
- 使用原型和内联扩展对象有什么区别?
- 为什么JS允许对象属性同时“引号”?和引用?有区别吗?
- 在使用继承时,构造函数和原型对象有什么区别吗?
- 这两个JSON对象有区别吗,看起来没有,但是
- 对象构造函数和全局对象有什么区别
- 什么是数组,数组和对象有什么区别,以及何时以及为什么使用数组
- 从定义上看,javascript中的函数和对象有什么本质区别?
- 在object .create中使用对象字面量和函数表达式有区别吗?