Javascript 创建对象 - 多种方法,有什么区别吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16109108/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Javascript creating objects - multiple approaches, any differences?
提问by Umair
I have seen a few different ways to instantiate objects in javascript, wanted to know the benefits/drawbacks of the various approaches and why you would use one over the other.
我已经看到了几种在 javascript 中实例化对象的不同方法,想知道各种方法的优点/缺点以及为什么要使用一种方法而不是另一种方法。
Approach 1
方法一
var obj = {
prop: value,
.
.
.
}
Approach one is standard approach, nothing new :)
方法一是标准方法,没什么新鲜的:)
Approach 2
方法二
var obj = new function() {
var prop1 = value1;
var fn1 = function() {
};
.
.
.
this.prop2 = value2;
.
.
.
}();
The function approach, I wanted to compare this approach with approach 3. The function approach is primarily used for encapsulation (correct?)
函数方法,我想把这个方法与方法3进行比较。函数方法主要用于封装(对吗?)
Approach 3
方法三
var obj = (function() {
var prop1 = value1;
var fn1 = function() {
};
.
.
.
return {
prop2: value2,
.
.
.
}
})();
With this approach, I do not quite see the reasoning behind its usage. How does it differ from approach 2? Both can be used to encapsulate logic.
使用这种方法,我不太明白其使用背后的原因。它与方法 2 有何不同?两者都可以用来封装逻辑。
Is it so we can pass in parameters, so we can deal with any potential conflicts?? E.g jquery's $
syntax - but you can also do this with approach 2...
是不是这样我们就可以传入参数,这样我们就可以处理任何潜在的冲突??例如 jquery 的$
语法 - 但你也可以用方法 2 来做到这一点......
Thanks.
谢谢。
Edit:
编辑:
I am aware the approach 1 and 3 are similar (in that they both return objects) however approach 3 also creates a closure. Which approach 2 also does.
我知道方法 1 和方法 3 相似(因为它们都返回对象)但是方法 3 也创建了一个闭包。哪种方法2也可以。
That is the basis of my question really, both 2 and 3 create closures, but what is the difference between them.
这确实是我问题的基础,2 和 3 都创建了闭包,但它们之间有什么区别。
采纳答案by Alexey Lebedev
In approaches #2 and #3 the constructor
property of the resulting objects will be different.
在方法#2 和#3constructor
中,生成的对象的属性将不同。
In practice it means that the second approach allows you to instantiate more than one object using the anonymous constructor function:
实际上,这意味着第二种方法允许您使用匿名构造函数实例化多个对象:
x = new function() { alert(1) };
y = new x.constructor; // shows the message too
The top answer to Module pattern vs. instance of an anonymous constructorincludes a quote from Douglas Crockford in which he explains why he thinks the approach #3 is better than #2.
模块模式与匿名构造函数实例的最佳答案包括 Douglas Crockford 的引述,他解释了为什么他认为方法 #3 比 #2 更好。
回答by Mohit Kumar Gupta
7 ways to create objects in JavaScript :
在 JavaScript 中创建对象的 7 种方法:
1. Object constructor
1.对象构造器
The simplest way to create an object is to use the Object constructor: view plainprint?
创建对象的最简单方法是使用 Object 构造函数:view plainprint?
var person = new Object();
person.name = "Diego";
person.getName = function(){
return this.name;
};
2. Literal notation
2. 文字符号
view plainprint?
查看普通版?
var person = {
person.name : "Diego",
person.getName : function(){
return this.name;
}
}
3. Factory function
3.工厂功能
The Factory function allows to encapsulate and re-use the logic for creating similar objects. It leverages any of the previous constructs for this. Either: view plainprint?
工厂功能允许封装和重用创建类似对象的逻辑。为此,它利用了之前的任何构造。要么:查看普通印刷品?
var newPerson=function(name){
var result = new Object();
result.name = name;
result.getName = function(){
return this.name;
};
return result;
};
var personOne = newPerson("Diego");
var personTwo = newPerson("Gangelo");
console.log(personOne.getName()); // prints Diego
console.log(personTwo.getName()); // prints Gangelo
Or:
或者:
view plainprint?
var newPerson=function(name){
return {
person.name : name,
person.getName : function(){
return this.name;
};
};
var personOne = newPerson("Diego");
var personTwo = newPerson("Gangelo");
console.log(personOne.getName()); // prints Diego
console.log(personTwo.getName()); // prints Gangelo
4. Function Constructor
4. 函数构造器
In Javascript it is possible to call any function with the new operator in front of it. Given a function F, for new F(): a new empty object X is created. X is set as context for F meaning throughout F this points to X. X is returned as result of F view plainprint?
在 Javascript 中,可以使用前面的 new 运算符调用任何函数。给定一个函数 F,对于 new F():创建一个新的空对象 X。X 被设置为 F 的上下文,这意味着整个 F 都指向 X。X 作为 F 视图纯文本的结果返回?
function Person(name){
this.name = name;
this.getName = function(){
return this.name;
};
};
var personOne = new Person("Diego");
console.log(personOne.getName()); // prints Diego
console.log(personOne instanceOf Person); // prints true
console.log(personOne.constructor === Person); // prints true
console.log(personOne instanceOf Object); // prints true
5. Prototype
5. 原型
Functions are very special in Javascript. They are objects, they can create other objects and they automatically get a field called prototype. A prototype is a plain object with a single field, called constructor, pointing to the function itself. What makes it special is that every object created through a function inherits the function's prototype. view plainprint?
函数在 Javascript 中非常特殊。它们是对象,它们可以创建其他对象,并且它们会自动获得一个称为原型的字段。原型是具有单个字段的普通对象,称为构造函数,指向函数本身。它的特别之处在于通过函数创建的每个对象都继承了该函数的原型。查看普通版?
function Person(){};
Person.prototype.name = "Diego";
var personOne = new Person();
var personTwo = new Person();
console.log(personOne.constructor == Person); // prints true
console.log(personOne.name); // prints Diego
console.log(personTwo.constructor == Person); // prints true
console.log(personTwo.name); // prints Diego
6. Function/Prototype combination
6. 功能/原型组合
The function/prototype combination, as you would imagine, takes advantage of both approaches :) view plainprint?
正如您所想象的那样,函数/原型组合利用了两种方法:) 查看纯文本?
function Person(name){
this.name = name;
};
Person.prototype.getName = function(){
return this.name;
};
var personOne = new Person("Diego");
var personTwo = new Person("Filippo");
console.log(personOne.getName()); // prints Diego
console.log(personTwo.getName()); // prints Filippo
console.log(personOne.getName === personTwo.getName) //prints true
7. Singleton
7. 单身
Sometimes, you may want to make sure that only a single instance of a certain class exists. To get a Singleton in Javascript is as simple as defining and invoking the constructor at the same time: view plainprint?
有时,您可能希望确保某个类只存在一个实例。要在 Javascript 中获得单例就像同时定义和调用构造函数一样简单:查看普通打印?
var singleton = new function(){
this.name = "ApplicationName";
};
回答by Kamyar Nazeri
The first and third approach are almost the same, in a way they both create an object literal, which is a direct child of Object
class. The difference between them is that in the third approach you may have some sort of encapsulation of properties:
第一种和第三种方法几乎相同,在某种程度上它们都创建了一个对象字面量,它是Object
类的直接子代。它们之间的区别在于,在第三种方法中,您可能对属性进行了某种封装:
var obj = (function() {
var prop = {};
return {
prop2: function(){ return prop };
}
})();
Performance-wise you might consider that the third approach creates closure, while the first one does not!
在性能方面,您可能会认为第三种方法会创建闭包,而第一种方法不会!
However in the second approach you are merely creating a new object from an anonymous class which is not a direct child of Object
class.
然而,在第二种方法中,您只是从一个匿名类创建一个新对象,该类不是类的直接子Object
类。
The correct form of the second approach is this (at least that's ecma standard):
第二种方法的正确形式是这样的(至少那是 ecma 标准):
var obj = new function() {
var prop1 = value1;
this.prop2 = value2;
}();
The difference between approach 2 and 3 is only their inheritance chain: (assuming obj2 is from 2nd approach and obj3 is from 3rd approach)
方法2和方法3的区别仅在于它们的继承链:(假设obj2来自第二种方法而obj3来自第三种方法)
obj2.__proto__ == Object.prototype; // false
obj3.__proto__ == Object.prototype; // true
obj2 is created from an anonymous class itself:
obj2 是从匿名类本身创建的:
obj2.__proto__.__proto__ == Object.prototype; // true (there's 2 level of inheritance here)
回答by rich remer
There's also:
还有:
var obj = Object.create({prop: ...});
This works by setting a prototype. It's much more efficient to use a prototype if you are going to have multiple objects sharing properties or methods.
这是通过设置原型来实现的。如果要让多个对象共享属性或方法,使用原型会更有效率。
var proto = {foo: function() {}},
obj1 = Object.create(proto),
obj2 = Object.create(proto),
obj3 = {foo: function() {}},
obj4 = {foo: function() {}};
In this example, obj1 and obj2 share a "foo" function, defined in "proto". Meanwhile, obj3 and obj4 each have their own "foo". If you are creating lots of objects with lots of properties, this can make a big difference in memory consumption and even performance.
在这个例子中,obj1 和 obj2 共享一个在“proto”中定义的“foo”函数。同时,obj3 和 obj4 都有自己的“foo”。如果您正在创建具有大量属性的大量对象,这会对内存消耗甚至性能产生很大影响。
This benefit is shared by use of the "new" keyword if you use a named function and assign properties to the function's prototype (ex: f.prototype.prop) before using new.
如果您使用命名函数并在使用 new 之前将属性分配给函数的原型(例如:f.prototype.prop),则使用“new”关键字可以共享此好处。
回答by Niels
Approach 1
This is a single object, no class and you can't define more easy if it's complex
方法 1
这是一个单一的对象,没有类,如果它很复杂,你就无法定义更简单的方法
var obj = {
prop: value
}
Approach 2
A non anonymous function. It will create an object out of a 'class', normalle the function is saved as a class name and can create multiple objects of the same type easily like below:
方法 2
一个非匿名函数。它将从“类”中创建一个对象,通常该函数被保存为类名,并且可以轻松创建多个相同类型的对象,如下所示:
var Bycicle= function() {
var prop1 = value1;
this.prop2 = value2;
}
var obj1 = new Bycicle(),
obj2 = new Bycicle();
Approach 3
An anonymous function, variables from outside the function can not interfere with variables inside the function:
方法3
匿名函数,函数外部的变量不能干扰函数内部的变量:
var a = 10;
var obj = (function() {
alert(a); // Alerts undefined
var prop1 = value1;
alert(prop1); // alerts the value of value1
return {
prop2: value2;
}
})(); // Within the () you can pass arguments to the anonymous function.
More about anonymous functions: http://helephant.com/2008/08/23/javascript-anonymous-functions/
有关匿名函数的更多信息:http: //helephant.com/2008/08/23/javascript-anonymous-functions/
Other approaches
There also is an Object.create()
and a new Object()
to create new objects, which both are the same as Approach 1.
其他方法
还有一个Object.create()
和 anew Object()
来创建新对象,两者都与方法 1 相同。
Conclusion
In the end, the object will always be the same except for the 3th one, because it's anonymous.
结论
最后,除了第 3 个对象之外,对象将始终相同,因为它是匿名的。
回答by Adidi
Your question should be 2 Approaches because Approach 3is exactly like Approach 1only the way to create that is by self execute function.
您的问题应该是 2 Approaches,因为Approach 3与Approach 1完全一样,只是通过自执行功能创建的方式。
About the difference when you make an object like Approach 1you can think about it like an object with only static function like in java. so it's always alive and you don't make instance out of it (similar to singleton) - so when you make this object:
关于创建像方法 1这样的对象时的区别,您可以将它视为一个只有静态函数的对象,例如在 java 中。所以它总是活着,你不会从中创建实例(类似于单例) - 所以当你创建这个对象时:
var obj = {
prop: value,
func: function(){
alert(this.prop);
}
};
You can call it immediately:
您可以立即调用它:
obj.prop = 'something else';
obj.func();
Approach 2(without the new like the comment you have got) is a classical object which you can create instances - make inherit (with js "tricks") and so on:
方法 2(没有像你得到的评论那样的新的)是一个经典的对象,你可以创建实例 - 使继承(使用 js“技巧”)等等:
function Person(firstName,lastName){ // or var Person = function(...
this.firstName = firstName;
this.lastName= lastName;
this.getFullName = function(){
return this.firstName + ' ' + this.lastName;
}
}
//use
var person1 = new Person('yair','lapid');
var person2 = new Person('Naftali','Bennet');
you can put it in an array etc...
var arr = [person1,person2, new Person('shelly','yekimovits')];
回答by Apurva Pathak
I have been working around with JS a bit and thought of posting some answer, I hope it helps someone else too:
我一直在使用 JS 并考虑发布一些答案,我希望它也能帮助其他人:
1) Object Literal: You literary written out the object while creating it
1)对象字面量:您在创建对象时将其写出
var person = {
name: ['Bob', 'Smith'],
age: 32,
gender: 'male',
interests: ['music', 'skiing'],
bio: function() {
alert(this.name[0] + ' ' + this.name[1] + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
},
greeting: function() {
alert('Hi! I\'m ' + this.name[0] + '.');
}
};
Usage : When you want to transfer data to server
用法:当您想将数据传输到服务器时
2) Constructor function:You use constructor function when you want to create multiple objects of same falvour.
2)构造函数:当你想创建多个相同的对象时,你可以使用构造函数。
function Vehicle(name, maker) {
this.name = name;// Every function while executing has a reference
this.maker = maker;// to its current execution context called as this
}
let car1 = new Vehicle('Fiesta', 'Ford');// New keyword with function turns function call into constructor call
let car2 = new Vehicle('Santa Fe', 'Hyundai');
console.log(car1.name); //Output: Fiesta
console.log(car2.name); //Output: Santa Fe
3) Create Javascript object with create Method
3)使用 create 方法创建 Javascript 对象
Object.create() allows to create objects with more attribute options like value, configurable, enumerable and writable . Creates a new object extending the prototype object passed as paramtere
Object.create() 允许创建具有更多属性选项的对象,例如 value、configurable、enumerable 和 writable。创建一个扩展作为参数传递的原型对象的新对象
let car = Object.create(Object.prototype,{
name:{
value: 'Fiesta',
configurable: true,
writable: true,
enumerable: false
},
maker:{
value: 'Ford',
configurable: true,
writable: true,
enumerable: true
}});
console.log(car.name) //Output: Fiesta
Prototype: Every single object is built by a constructor function. Constructor function make the object linked to its own prototype Prototype is the arbitrary link between the constructor and the object.
原型:每个对象都是由一个构造函数构建的。构造函数使对象链接到自己的原型原型是构造函数和对象之间的任意链接。
4) Create Javascript using ES6 classes
4)使用 ES6 类创建 Javascript
class Vehicle {
constructor(name, maker, engine) {
this.name = name;
this.maker = maker;
this.engine = engine;
}
}
let bike1 = new Vehicle('Hayabusa', 'Suzuki', '1340cc');
let bike2 = new Vehicle('Ninja', 'Kawasaki', '998cc');
console.log(bike1.name); //Output: Hayabusa
console.log(bike2.maker); //Output: Kawasaki
5) Using Object constructor
5) 使用对象构造函数
var d = new Object();
Best way to create empty objects.
创建空对象的最佳方法。
Note : I have compiled taken most of the contents from this link https://codeburst.io/various-ways-to-create-javascript-object-9563c6887a47
注意:我已经编译了这个链接https://codeburst.io/various-ways-to-create-javascript-object-9563c6887a47 中的大部分内容
回答by Ted Hopp
There isn't a whole lot of difference between approaches 2 and 3 for one-off objects. (If you were to name the function used in approach 2, you would have defined a reusable constructor.) My impression is that approach 3 is more commonly used for these situations, but I don't see a whole lot of difference between them.
对于一次性对象,方法 2 和方法 3 之间没有太大区别。(如果您要命名方法 2 中使用的函数,您将定义一个可重用的构造函数。)我的印象是方法 3 更常用于这些情况,但我看不出它们之间有很大区别。
It should be noted that both approaches 2 and 3 can take arguments:
需要注意的是,方法 2 和方法 3 都可以带参数:
var approach2Obj = new function(formalArg) {
var privateProp = ...;
this.publicProp = ...;
// more constructor logic
)(actualArg);
var approach3Obj = (function(formalArg) {
var privateProp = ...;
// more creation logic
return {
publicProp : ...;
};
}(actualArg));
P.S. As @Alexey Lebedev points out in his answer, one difference between the two (perhaps the only one) is that approach2Obj.constructor
and approach3Obj.constructor
will be different. approach3Obj.constructor
will be identically Object
, while approach2Obj.constructor
will be the anonymous function.
PS 正如@Alexey Lebedev 在他的回答中指出的那样,两者之间的一个区别(也许是唯一的一个)是approach2Obj.constructor
并且approach3Obj.constructor
会有所不同。approach3Obj.constructor
将是相同的Object
,而approach2Obj.constructor
将是匿名函数。
回答by Racheet
In order to understand approach 2, the reader needs to know some quite technical things about the way the new keyword works. Specifically that it will actually call the anonymous function as a constructor, rather than instantiate a new function object and dump it in the obj variable.
为了理解方法 2,读者需要了解一些关于 new 关键字工作方式的技术性知识。具体来说,它实际上将匿名函数作为构造函数调用,而不是实例化一个新的函数对象并将其转储到 obj 变量中。
In order to understand approach 3, the reader just needs to understand the IIFE pattern. That pattern has become very common in javascript code over the past two years, and that is probably why that version is more commonly used.
为了理解方法 3,读者只需要理解 IIFE 模式。在过去的两年中,这种模式在 javascript 代码中变得非常普遍,这可能就是该版本更常用的原因。
Both versions are used to produce encapsulation, and both versions require knowledge of a complex language feature to understand. However the language feature required in approach three is more commonly known than the language feature required to understand approach two. Which is why approach three is more commonly used in the wild.
两个版本都用于生成封装,并且两个版本都需要了解复杂的语言特性才能理解。然而,方法三所需的语言特征比理解方法二所需的语言特征更广为人知。这就是方法三在野外更常用的原因。