之间究竟有什么区别
function ObjA() {
this.a = 'text';
}
var obj = new ObjA();
和
function ObjB() {
return {
a: 'text'
};
}
var obj = new ObjB();
我问,因为我正在阅读this question并且我在其中一个答案中注意到了以下内容:
function Test() {
this.a = 1;
return {
get A() { return this.a; },
set A(v) { this.a = v; }
};
}
所以我问自己,这和下面的区别是什么:
function Test() {
this.a = 1;
}
Test.prototype = {
get A() { return this.a; },
set A(v) { this.a = v; }
};
他们在评论中说,前者"记忆作为吸气剂和制定者是"独特"每个对象"。有人可以详细说明一下吗?
答案 0 :(得分:1)
你的上一个例子不起作用。
function Test() {
var a = 1;
}
Test.prototype = {
// This code has no clue what a is
get A() { return a; },
set A(v) { a = v; }
};
但如果是
function Test() {
this.a = 1;
}
Test.prototype = {
get A() { return this.a; },
set A(v) { this.a = v; }
};
然后两段代码将是相似的,除了使用Test.prototype
的代码创建Test
的实例,其中第一个示例(模块模式)总是创建一些基本类型{ {1}}使用Factory方法
答案 1 :(得分:1)
你实际上问了几个不同的问题。所以让我专注于第一个(修改变量名称以更容易地引用它们而不是覆盖Object
):
之间究竟有什么区别:
function ObjA() {
this.a = 'text';
}
var objA = new ObjA();
和
function ObjB() {
return {
a: 'text'
};
}
var objB = new ObjB();
不同之处在于前一版本维护原型链,而后一版本则丢弃原型链。请考虑以下代码行:
ObjA.prototype.b = "something";
ObjB.prototype.b = "something";
以下情况变为现实:
objA.b; //is "something"
objB.b; //is undefined
原因是从“构造函数”返回的对象不附加ObjB的原型链。这是一个全新的对象。这就是“差异”。
第二个例子(使用.prototype
与返回对象)实际上实际上并没有“浪费”内存,据我所知(请参阅更新)。因为在函数上调用new
运算符的过程将创建对象原型的副本,然后调用其函数。好的部分是当您使用.prototype
时,原型方法将在“构造函数”函数中可用,并且您将使用该版本维护原型链。但我不知道使用基于回归的方法有什么“错误”。
<强>更新强>
我查看了关于这个主题的ECMAScript规范(并且我的想法有点过时),看来我对内存浪费的看法不对。看起来“class”函数的prototype属性的方法/属性通过引用链接。所以它实际上浪费了一点内存来生成一个新对象,而不是使用原型。此外,在返回的对象中声明的任何属性都是实例级的,而在原型对象中声明的属性对于“类”是静态的(即由所有实例共享)。
正如其他人所说,您的示例有一个小错误(原型对象无法使用(我看到你修复了这个错误)。a
)。但这对于手头的问题来说有点无关紧要,所以我忽略了它。
答案 2 :(得分:1)
之间的区别
function Obj () {
this.a = 'text';
}
var obj = new Obj();
和
function Obj () {
return {
a: 'text'
};
}
var obj = new Obj();
这是第一个被认为是不安全的吗?也就是说,如果您忘记使用new
运算符,则会使用属性污染全局命名空间。
第二种定义对象的方法要好得多。您可以同时var obj = new Obj();
和var obj = Obj();
,结果将完全相同。
此外,在构造函数中使用var
将导致无法从构造函数本身的范围外访问它们。因此,您可以将它们用作私有并定义充当getter / setter的函数,例如:
function Obj () {
var privateVar = 'xxx';
return {
getPrivateVar: function () {
return privateVar;
},
setPrivateVar: function (val) {
privateVar = val;
}
};
}
这样你就可以从构造函数外部访问变量,但是如果没有调用正确的函数(setter),你将无法修改它。
使用原型是一个广泛的主题。它允许您节省内存(方法在对象实例之间共享,而不是在每次创建新对象时创建),它允许您仅通过修改原型来修改对象的所有实例中的方法。此外,原型可用于模仿继承(寻找“原型链”)。
答案 3 :(得分:0)
允许您创建没有私有方法/功能的对象(模拟,但它是)
function Object() {
// a can be change via OBJECTs API
this.a = 7;
}
允许使用函数和变量到“内部作业”,这在代码
中是不可访问的 function Object() {
// b CAN BE CHANGED FROM OBJECTs API
var b = 125;
return {
a: 7+b
};
}
答案 4 :(得分:0)
function Object() {
this.a = 'text';
}
var obj = new Object();
function Object() {
return {
a: 'text'
};
}
var obj = new Object();
每个都会像:
一样使用console.log(obj.a); // 'text'
然而,
function Test() {
var a = 1;
return {
get A() { return a; },
set A(v) { a = v; }
};
}
var obj = new Test();
将像
一样使用console.log(obj.A); // 1
obj.A = "banana";
console.log(obj.A) // 'banana'
它使a
变为私有,并向A
/ get
创建外部属性set
。这样做的好处是,它允许您创建属性static
或readonly
,在获取/设置时进行计算以及许多其他事情。