对象文字属性赋值奇怪:这里发生了什么?

时间:2014-01-15 03:44:11

标签: javascript object constructor prototype object-literal

我正在编写一个单元测试(在带有Chai的Mocha中),以查看某个对象o是否为instanceof ClassY。单元测试成功,但我可以使它失败取决于我如何创建一个对象文字,尽管生成的对象文字是相同的。

我知道,这有点模糊。让我解释一下。

ClassY是对象的一部分,我们将其称为Parent。这种关系看起来像这样:

Parent: {
  ClassY: function() {}
}

我使用Underscore扩展方法将Parent附加到Backbone
_.extend( Backbone, Parent )

这导致Backbone具有ClassY属性,可以通过Backbone.ClassY访问。

我的单元测试是:
expect( o ).to.be.instanceof( Backbone.ClassY );

我知道oBackbone.ClassY的实例。

如果我写的话传递

var Parent = {};
var ClassY = Parent.ClassY = function() {};

以及

var Parent = {};
var ClassY = function() {};
Parent.ClassY = ClassY;

但是当我写下以下内容时,单元测试失败

var ClassY = function() {};
var Parent = {  
  ClassY: ClassY  
};

失败的原因是:

TypeError: '[object Object]' is not a valid argument for 'instanceof'
(evaluating 'flag(this, 'object') instanceof constructor')

确实,在Chrome DevTools中检查Backbone会在失败的情况下向我显示,ClassY是一个对象。在成功的情况下,它是构造函数。

我想这是对象文字的一些简单属性,这让我望而却步。你知道这里发生了什么吗?

1 个答案:

答案 0 :(得分:1)

我不确定Backbone在这里做了什么(基于对JS中各种“类”/继承实现的了解,我有一些关于为什么会发生这种情况的想法,但我必须看看在图书馆)。

然而,我可以告诉你的是,这是图书馆正在做的事情,而不是对象本身的事情。

以下是您的证明:

var Parent_1 = {
        ClassX : function () { this.x = "x"; }
    },

    ClassY = function () { this.y = "y"; },

    Parent_2 = {
        ClassY : ClassY
    };


var littleX = new Parent_1.ClassX(),
    littleY = new Parent_2.ClassY();

littleX instanceof Parent_1.ClassX;
littleY instanceof Parent_2.ClassY;

这两个都应该是真的。

在JS中,当您执行以下操作时:

var x = {}, y = [];
x.y = y;

你给它引用了该对象的完全相同的实例(数字/字符串/布尔值的工作方式不同)。

所以x.y === y为真,而{} === {}为假,即使两个对象都具有相同的属性。

在骨干网中,我会想象你正在传递它,Backbone正在寻找一个构造函数并操纵它来附加助手或钩子,或者添加额外的继承或MVC功能/观察等等。

所以来自另一方的东西并不是完全相同的对象,在内存中 - 它可能埋在一个闭包中,然后Backbone可以在某个地方捅,然后将自己连接起来。再说一遍,还没看过来源,但那是我最初的反应。