我已经看到了一些在javascript中实例化对象的不同方法,想知道各种方法的优点/缺点以及为什么要使用其中一种方法。
方法1
var obj = {
prop: value,
.
.
.
}
方法一是标准方法,没什么新的:)
方法2
var obj = new function() {
var prop1 = value1;
var fn1 = function() {
};
.
.
.
this.prop2 = value2;
.
.
.
}();
函数方法,我想将此方法与方法3进行比较。函数方法主要用于封装(正确吗?)
方法3
var obj = (function() {
var prop1 = value1;
var fn1 = function() {
};
.
.
.
return {
prop2: value2,
.
.
.
}
})();
通过这种方法,我不太清楚其使用背后的原因。它与方法2有何不同?两者都可以用来封装逻辑。
是这样我们可以传入参数,所以我们可以处理任何潜在的冲突吗?例如,jquery的$
语法 - 但您也可以使用方法2 ...
感谢。
修改
我知道方法1和3是相似的(因为它们都返回对象)但是方法3也创建了一个闭包。哪种方法2也适用。
这是我的问题的基础,2和3都创建了闭包,但它们之间有什么区别。
答案 0 :(得分:22)
在JavaScript中创建对象的7种方法:
<强> 1。对象构造函数
创建对象的最简单方法是使用Object构造函数: view plainprint?
var person = new Object();
person.name = "Diego";
person.getName = function(){
return this.name;
};
<强> 2。文字符号
查看plainprint?
var person = {
person.name : "Diego",
person.getName : function(){
return this.name;
}
}
第3。工厂职能
Factory函数允许封装和重用逻辑以创建类似对象。它利用了以前的任何构造。 或者: 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
或者:
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。函数构造函数
在Javascript中,可以使用前面的new运算符调用任何函数。 给定函数F,对于新的F(): 创建一个新的空对象X. X被设置为F的上下文,意味着整个F指向X. 作为F的结果返回X. view plainprint?
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。原型强>
Javascript中的函数非常特殊。它们是对象,可以创建其他对象,并自动获得一个名为prototype的字段。 原型是一个普通的对象,它有一个字段,称为构造函数,指向函数本身。 它的特殊之处在于通过函数创建的每个对象都继承了函数的原型。 view plainprint?
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。功能/原型组合
正如您想象的那样,函数/原型组合利用了这两种方法:) 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。单强>
有时,您可能希望确保只存在某个类的单个实例。 在Javascript中获取Singleton就像在同一时间定义和调用构造函数一样简单: view plainprint?
var singleton = new function(){
this.name = "ApplicationName";
};
答案 1 :(得分:10)
在方法#2和#3中,结果对象的constructor
属性将不同。
实际上,这意味着第二种方法允许您使用匿名构造函数实例化多个对象:
x = new function() { alert(1) };
y = new x.constructor; // shows the message too
Module pattern vs. instance of an anonymous constructor的最佳答案包括Douglas Crockford的一句话,他解释了为什么他认为方法#3优于#2。
答案 2 :(得分:4)
第一种和第三种方法几乎相同,它们都创建了一个对象文字,它是Object
类的直接子元素。它们之间的区别在于,在第三种方法中,您可能会对某些属性进行某种封装:
var obj = (function() {
var prop = {};
return {
prop2: function(){ return prop };
}
})();
在性能方面,您可能会认为第三种方法会产生闭包,而第一种方法则不会!
然而,在第二种方法中,您只是从匿名类创建一个新对象,该类不是Object
类的直接子级。
第二种方法的正确形式是这个(至少是那个ecma标准):
var obj = new function() {
var prop1 = value1;
this.prop2 = value2;
}();
方法2和方法3之间的区别仅在于它们的继承链: (假设obj2来自第二种方法而obj3来自第三种方法)
obj2.__proto__ == Object.prototype; // false
obj3.__proto__ == Object.prototype; // true
obj2是从匿名类本身创建的:
obj2.__proto__.__proto__ == Object.prototype; // true (there's 2 level of inheritance here)
答案 3 :(得分:2)
方法1
这是一个单独的对象,没有类,如果它很复杂,你就无法定义更简单的
var obj = {
prop: value
}
方法2
非匿名函数。它将从'class'创建一个对象,normalle将该函数保存为类名,并且可以像下面一样轻松创建多个相同类型的对象:
var Bycicle= function() {
var prop1 = value1;
this.prop2 = value2;
}
var obj1 = new Bycicle(),
obj2 = new Bycicle();
方法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.
有关匿名函数的更多信息:http://helephant.com/2008/08/23/javascript-anonymous-functions/
其他方法
还有一个Object.create()
和一个new Object()
来创建新对象,它们都与方法1相同。
<强>结论强>
最后,除了第3个对象外,对象总是相同的,因为它是匿名的。
答案 4 :(得分:2)
还有:
var obj = Object.create({prop: ...});
这可以通过设置原型来实现。如果要让多个对象共享属性或方法,那么使用原型会更有效。
var proto = {foo: function() {}},
obj1 = Object.create(proto),
obj2 = Object.create(proto),
obj3 = {foo: function() {}},
obj4 = {foo: function() {}};
在这个例子中,obj1和obj2共享一个“foo”函数,在“proto”中定义。同时,obj3和obj4各有自己的“foo”。如果要创建大量具有大量属性的对象,这可能会对内存消耗甚至性能产生很大影响。
如果您使用命名函数并在使用new之前为函数的原型(例如:f.prototype.prop)指定属性,则使用“new”关键字可以共享此优势。
答案 5 :(得分:1)
我一直在处理JS,并想发布一些答案,希望对其他人也有帮助。
1)对象文字:您在创建对象时用文学方法写出了对象
library(dplyr)
library(zoo)
data.frame(C4 = seq(min(df$C2), max(df$C2), by = "5 min")) %>%
left_join(transform(df, C4 = C2)) %>%
na.locf()
# C4 C1 C2 C3
#1 2011-02-01 04:30:00 1 2011-02-01 04:30:00 4
#2 2011-02-01 04:35:00 1 2011-02-01 04:30:00 4
#3 2011-02-01 04:40:00 1 2011-02-01 04:30:00 4
#4 2011-02-01 04:45:00 2 2011-02-01 04:45:00 3
#5 2011-02-01 04:50:00 2 2011-02-01 04:45:00 3
#6 2011-02-01 04:55:00 2 2011-02-01 04:45:00 3
#7 2011-02-01 05:00:00 3 2011-02-01 05:00:00 5
#8 2011-02-01 05:05:00 3 2011-02-01 05:00:00 5
#9 2011-02-01 05:10:00 3 2011-02-01 05:00:00 5
#10 2011-02-01 05:15:00 4 2011-02-01 05:15:00 6
用法:要将数据传输到服务器时
2)构造函数: 当您要创建多个具有相同样式的对象时,可以使用构造函数。
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] + '.');
}
};
3)使用创建方法创建Javascript对象
Object.create()允许创建具有更多属性选项(例如value,可配置,可枚举和可写)的对象。 创建一个新对象,扩展作为参数传递的原型对象
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
原型: 每个对象都是由构造函数构造的。 构造函数使对象链接到其自己的原型 原型是构造函数和对象之间的任意链接。
4)使用ES6类创建Javascript
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
5)使用对象构造函数
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
创建空对象的最佳方法。
注意:我已从此链接https://codeburst.io/various-ways-to-create-javascript-object-9563c6887a47
中获取了大部分内容答案 6 :(得分:0)
对于一次性对象,方法2和3之间没有很大的区别。 (如果你要命名方法2中使用的函数,你就会定义一个可重用的构造函数。)我的印象是方法3更常用于这些情况,但我看不出它们之间有很大的区别。
应该注意的是,方法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。作为@Alexey Lebedev points out in his answer,两者之间的差异(可能是唯一的差异)是approach2Obj.constructor
和approach3Obj.constructor
会有所不同。 approach3Obj.constructor
将完全相同Object
,而approach2Obj.constructor
将是匿名函数。
答案 7 :(得分:0)
你的问题应该是2种方法,因为方法3 与方法1 完全一样,只有通过自我执行功能创建的方式。
关于制作像方法1 这样的对象的区别,你可以把它想象成只有像java一样的静态函数的对象。所以它总是活着而且你没有制作它的实例(类似于单身) - 所以当你创造这个对象时:
var obj = {
prop: value,
func: function(){
alert(this.prop);
}
};
您可以立即致电:
obj.prop = 'something else';
obj.func();
方法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')];
答案 8 :(得分:0)
为了理解方法2,读者需要了解一些关于新关键词的工作方式的技术性问题。具体来说,它实际上将匿名函数作为构造函数调用,而不是实例化一个新的函数对象并将其转储到obj变量中。
为了理解方法3,读者只需要了解IIFE模式。在过去两年中,这种模式在javascript代码中变得非常普遍,这可能是该版本更常用的原因。
两个版本都用于生成封装,两个版本都需要了解复杂语言功能才能理解。然而,方法三中所需的语言特征比理解方法二所需的语言特征更为人所知。这就是为什么三种方法在野外更常用的原因。