3

我在理解Result以下代码中的错误原因时遇到了一些麻烦。

库中需要具有大小的其他对象将检查大小参数是否是InterfaceKit.Core.Size. 目前,instanceof正在返回假。

var InterfaceKit = {
    Core : {
        Size: function( i_Width, i_Height ){
            Object.defineProperties(this, {
                m_Width : {
                    value: Number( i_Width ) ? Number( i_Width ) : 0
                    , writable: true
                }
                , m_Height : {
                    value: Number( i_Height ) ? Number( i_Height ) : 0
                    , writable: true
                }

            }); 

            this.__proto__ = {
                SetWidth: function( i_Width ){
                    if( Number( i_Width ) )
                        this.m_Width = Number( i_Width ); 

                }
                , GetWidth: function(){
                    return this.m_Width; 
                }
                , SetHeight: function( i_Height ){
                    if( Number( i_Height ) )
                        this.m_Height = Number( i_Height ); 

                }
                , GetHeight: function(){
                    return this.m_Height; 
                }

            };

            this.__proto__.constructor = InterfaceKit.Core.Size; 

        }

    }

}; 

var Result = (new InterfaceKit.Core.Size( 10, 10 ) instanceof InterfaceKit.Core.Size); //false
4

3 回答 3

2

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/instanceof

instanceof运算符测试一个对象是否在其链prototype中具有构造函数的原型属性。

换句话说...

// an objects prototype chains has this as the root
object.__proto__ // set to: {}

// the prototype property of the constructor
A.B.prototype // unmodified prototype, some object set by JS engine. Probably: {}

// Equivalent objects are not equal, because they are different objects
{} === {} // false

因此构造函数的原型不在对象的原型链中。这意味着它不是instanceof构造函数,即使该构造函数确实“构造”了该对象。


但实际上,只是不要使用__proto__.

var A = {
    B: function() {}
};
A.B.prototype = {};

var Result = (new A.B() instanceof A.B); // true
于 2012-12-28T20:17:10.383 回答
1

来自ECMAScript 规范

11.8.6 instanceof 运算符

产生式 RelationalExpression : RelationalExpression instanceof ShiftExpression 的评估如下:

  1. 令 lref 为评估 RelationalExpression 的结果。
  2. 令 lval 为 GetValue(lref)。
  3. 令 rref 为计算 ShiftExpression 的结果。
  4. 设 rval 为 GetValue(rref)。
  5. 如果 Type(rval) 不是 Object,则抛出 TypeError 异常。
  6. 如果 rval 没有 [[HasInstance]] 内部方法,则抛出 TypeError 异常。
  7. 返回使用参数 lval 调用 rval 的 [[HasInstance]] 内部方法的结果。

...

15.3.5.3 [[HasInstance]] (V)

假设 F 是一个 Function 对象。

当 F 的 [[HasInstance]] 内部方法以值 V 被调用时,采取以下步骤:

  1. 如果 V 不是对象,则返回 false。
  2. 令 O 为使用属性名称“prototype”调用 F 的 [[Get]] 内部方法的结果。
  3. 如果 Type(O) 不是 Object,则抛出 TypeError 异常。
  4. 重复
    • 令 V 为 V 的 [[Prototype]] 内部属性的值。
    • 如果 V 为 null,则返回 false。
    • 如果 O 和 V 引用同一个对象,则返回 true。

注意使用 Function.prototype.bind 创建的函数对象具有在 15.3.4.5.3 中定义的 [[HasInstance]] 的不同实现。

基本上,如果左操作数在其继承链中具有右操作数的原型,则instanceof返回:truel.__proto__ === r.prototype || l.__proto__.__proto__ === r.prototype || ...

由于对象的左操作数的原型被覆盖(__proto__是内部[[prototype]]属性的专有别名)并且不是由 Javascript 分配的,new A.B()因此不再A.B.prototype像通常那样继承自 ,因此不是instanceof A.B

于 2012-12-28T20:20:41.330 回答
0

我发现这是最好的解决方案:

var InterfaceKit {
    Core: {
        Size : function( i_Width, i_Height ){
            this.__prototype__ = Object.getPrototypeOf( this ); 

            var m_Width  = 0; 
            var m_Height = 0; 

            this.__prototype__.SetWidth  = function( i_Width ){}; 
            this.__prototype__.GetWidth  = function(){}; 
            this.__prototype__.SetHeight = function( i_Height ){}; 
            this.__prototype__.GetHeight = function(){}; 

            {
                 this.SetWidth( i_Width ); 
                 this.SetHeight( i_Height ); 
            }

        }

    }

}; 

var Result = (new InterfaceKit.Core.Size( 10, 10 ) instanceof InterfaceKit.Core.Size); // true
于 2012-12-31T13:54:33.770 回答