我有两个初始化对象的函数。 init和differentInit。
function init(){
return {a:5};
}
function differentInit(){
this.a =5;
}
obj = init();
newobj = new differentInit()
对象obj和newobj有何不同? 这就是JavaScript解释器显示为两个对象的内容。
>obj
<·Object {a: 5}
>newobj
<·differentInit {a: 5}
编辑:由于答案(非常好)已经指出newobj
有一个额外的原型differentInit.prototype
。我原以为只能使用Object.create()
方法使用其他原型创建对象。我不知道这是一个太普通的问题,但有多少其他方法可以用原型创建对象?并且可以将此问题中使用的方法视为使用原型创建对象的好方法吗?
答案 0 :(得分:8)
对象obj和newobj有何不同?
鉴于您已经展示的功能,唯一真正的区别是第二个在它和constructor
之间有一个额外的原型(具有不同的Object.prototype
属性)。第一个直接继承自Object.prototype
:
,例如obj
:
+----------+ Object.prototype-------------+--->| toString | | | valueOf | | | ... | | +----------+ +---------------+ | obj---->| [[Prototype]] |----+ | a: 5 | +---------------+
VS。 newObj
:
+----------+ Object.prototype--------------------------------------+--->| toString | | | valueOf | | | ... | | +----------+ +---------------+ | differentInit.prototype------+--->| [[Prototype]] |---+ | +---------------+ | | +---------------+ | newObj->| [[Prototype]] |----+ | a: 5 | +---------------+
(请注意,Oriol points out为Object.prototype
和differentInit.prototype
指向的对象都具有constructor
属性,指向Object
和differentInit
分别为obj.constructor
。Object
将newObj.constructor
differentInit
differentInit.prototype
。我已将其添加到图表中,但是它不必要地使它们变得复杂......)
除非您向json
添加内容,否则它不会产生任何重大的实际差异。
由于您已对问题Object.create()
进行了标记,我们只是注意到您的问题中没有任何JSON被使用。 JSON是用于数据交换的文本符号。如果您正在处理程序源代码而不处理字符串,那么您就不会处理JSON。
我一直认为只能使用
Object.create(null)
方法使用原型创建对象。
在JavaScript中,所有对象都有原型,除非他们使用null
创建(在[[Prototype]]
内部插槽中为obj = {}
提供原型,例如,他们没有原型)。
...有多少其他方法可以用原型创建对象?
您可以通过以下方式创建原型对象:
使用对象初始值设定项,例如Object.prototype
,使用new
作为原型来创建它。
通过prototype
运算符使用函数;函数的new
属性引用的对象被指定为function
创建的对象的原型。使用class
(或prototype
)关键字创建的所有函数都会获得一个prototype
属性,其中包含空白对象;然后可以添加或替换。 (如果函数null
为new
,Object.prototype
则使用new
。)
请注意,与function
一起使用的功能可以是使用// Using `function`
function Foo() {
}
Foo.prototype.bar = function() {
console.log("Foo instance says 'bar'!");
};
var f = new Foo();
f.bar();
关键字定义的任何功能:
class
或ES2015,使用class Foo {
bar() {
console.log("Foo instance says 'bar'!");
}
}
var f = new Foo();
f.bar();
关键字定义的函数:
Foo
除了一些小细节之外,上面的两个片段做同样的事情:他们定义了一个名为new
的函数,您需要通过Foo.prototype
调用该函数,该函数具有bar
其上有Object.create(p)
。
使用p
,其中p
被指定为生成对象的原型。与上面的#2不同,null
可以null
来创建一个没有原型的对象。这是在ES5中添加的,尽管它可以是shimmed(除Reflect.setPrototypeOf
位之外)。 (可选的第二个参数无法填充。)
您可以通过以下两种方式设置对象的原型:
使用Reflect.setPrototypeOf(target, proto)
或非常相似的Object.setPrototypeOf(target, proto)
,这是ES2015中的新功能。 (它们之间的唯一区别是target
如果你将Object.setPrototypeOf
作为非对象传递将会抛出; Reflect
只会在这种情况下返回你给它的不变对象。一些JavaScript引擎尚未拥有Object.prototype
对象,但很快就会出现。)
(仅限向后compat)使用__proto__
property,前提是对象从({1}}继承(直接或间接)。 备注:强>
一个。这仅适用于Web浏览器中的JavaScript引擎。
B中。它不是ES2015之前的规范的一部分。
℃。由于在ES2015之前它不在规范中,因此仅在Web浏览器上定义,如果对象不从Object.prototype
继承,则会在非常罕见中失败如果您需要在创建对象的原型后动态设置它,请改用Reflect.setPrototypeOf
。
这个问题中使用的方法可以被认为是用原型创建对象的好方法吗?
如果通过&#34;方法&#34;你的意思是new differentInit
,是的,这是一种用特定原型创建对象的完全正常的方法。通常,当您要创建几个对象时,您可以使用该表单(对于一般意义上的对象的#34;类&#34;对象,例如,占多数的对象)共同的特征)。对于该用例使用Object.create
也是完全正常和正常的(有些人根本不想使用new
运算符)。如果你只是想要一个特定对象从另一个特定对象继承的一次性,那么Object.create
就是你的选择。
答案 1 :(得分:4)
最实际的区别是
obj.constructor === Object
newobj.constructor === differentInit
Object.getPrototypeOf(obj) === Object.prototype;
Object.getPrototypeOf(newobj) === differentInit.prototype;
obj instanceof differentInit === false
newobj instanceof differentInit === true
否则(除非你修改differentInit.prototype
),它们基本相同。