使用函数初始化带有和不带return语句的JavaScript对象有什么区别?

时间:2016-02-05 11:47:14

标签: javascript

我有两个初始化对象的函数。 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()方法使用其他原型创建对象。我不知道这是一个太普通的问题,但有多少其他方法可以用原型创建对象?并且可以将此问题中使用的方法视为使用原型创建对象的好方法吗?

2 个答案:

答案 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 outObject.prototypedifferentInit.prototype指向的对象都具有constructor属性,指向ObjectdifferentInit分别为obj.constructorObjectnewObj.constructor differentInit differentInit.prototype。我已将其添加到图表中,但是它不必要地使它们变得复杂......)

除非您向json添加内容,否则它不会产生任何重大的实际差异。

由于您已对问题Object.create()进行了标记,我们只是注意到您的问题中没有任何JSON被使用。 JSON是用于数据交换的文本符号。如果您正在处理程序源代码而不处理字符串,那么您就不会处理JSON。

  

我一直认为只能使用Object.create(null)方法使用原型创建对象。

在JavaScript中,所有对象都有原型,除非他们使用null创建(在[[Prototype]]内部插槽中为obj = {}提供原型,例如,他们没有原型)。

  

...有多少其他方法可以用原型创建对象?

您可以通过以下方式创建原型对象:

  1. 使用对象初始值设定项,例如Object.prototype,使用new作为原型来创建它。

  2. 通过prototype运算符使用函数;函数的new属性引用的对象被指定为function创建的对象的原型。使用class(或prototype)关键字创建的所有函数都会获得一个prototype属性,其中包含空白对象;然后可以添加或替换。 (如果函数nullnewObject.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)

  3. 使用p,其中p被指定为生成对象的原型。与上面的#2不同,null可以null来创建一个没有原型的对象。这是在ES5中添加的,尽管它可以是shimmed(除Reflect.setPrototypeOf位之外)。 (可选的第二个参数无法填充。)

  4. 您可以通过以下两种方式设置对象的原型:

    1. 使用Reflect.setPrototypeOf(target, proto)或非常相似的Object.setPrototypeOf(target, proto),这是ES2015中的新功能。 (它们之间的唯一区别是target如果你将Object.setPrototypeOf作为非对象传递将会抛出; Reflect只会在这种情况下返回你给它的不变对象。一些JavaScript引擎尚未拥有Object.prototype对象,但很快就会出现。)

    2. (仅限向后compat)使用__proto__ property,前提是对象从({1}}继承(直接或间接)。 备注:

      一个。这仅适用于Web浏览器中的JavaScript引擎。

      B中。它不是ES2015之前的规范的一部分。

      ℃。由于在ES2015之前它不在规范中,因此仅在Web浏览器上定义,如果对象不从Object.prototype继承,则会在非常罕见中失败如果您需要在创建对象的原型后动态设置它,请改用Reflect.setPrototypeOf

    3.   

      这个问题中使用的方法可以被认为是用原型创建对象的好方法吗?

      如果通过&#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),它们基本相同。