2017-04-07 61 views
1
function A(){} 
A.prototype = "Foo bar"; 

new A() instanceof A; 
// TypeError: Function has non-object prototype 'Foo bar' in instanceof check 

正如您所看到的,如果构造函数的原型不是对象,它将失败并抛出错误。有没有办法确保instanceof不会失败?检查“instanceof”是否会失败

typeof new A().constructor.prototype === "object" 

typeof Object.getPrototypeOf(new A()) === "object" 

显然不起作用。

+2

也许把它包装在'try/catch'中? – Barmar

+1

'typeof A.prototype ===“object”'? – Barmar

+0

@Barmar我以前怎么没想到这件事?谢谢。 –

回答

1

错误说A.prototype需求是一个对象,所以你应该检查的是:

function isObject(x) { 
    return x != null && (typeof x == "object" || typeof x == "function"); 
} 

isObject(A.prototype)是不是你所能做的断言的instanceof通话不会抛出。按照规范,你应该测试

function allowsInstanceCheck(C) { 
    try { 
     if (!isObject(C)) return false; 
     var m = C[Symbol.hasInstance]; 
     if (m != null) return typeof m == "function"; 
     if (typeof C != "function") return false; 
     return isObject(C.prototype); 
    } catch (e) { 
     // any of the property accesses threw 
     return false; 
    } 
} 
1

使用try/catch来捕捉错误;

function isItA(obj) { 
 
    try { 
 
    return obj instanceof A; 
 
    } catch (e) { 
 
    return false; // 
 
    } 
 
} 
 

 
function A() {} 
 
A.prototype = "Foo bar"; 
 
function B() {} 
 
B.prototype = "Baz Quux"; 
 
console.log(isItA(new A())); 
 
console.log(isItA(new B()));

+0

虽然它避免了类型错误的不良影响,但它在返回true时会返回false。 :-( – RobG

+0

)如果对象有一个无效的原型,就没有办法判断它是否是'A',它默认返回'false',因为它不知道。 – Barmar

+0

如果'Foo.prototype'不是一个对象,那么由'new Foo()'创建的对象继承自Object.prototype,所以我猜* false *是可以的,因为不能有Foo的实例(不是有意义的办法)。 – RobG

1

也许不是一个真正的答案,而是一个有趣的结论。

当一个函数被调用作为构造,如果其原型属性不是一个对象,然后如在GetPrototypeFromConstructor描述的新实例被分配intrinsicDefaultProto作为其[[Prototpye]]

在创建新实例的过程中,intrinsicDefaultProto被传递的fallbackProto,这似乎是的值(在Firefox至少)Object.prototype中

而且由于Object.prototype中构造属性为对象,然后测试该实例的constructor属性是否引用的候选对象将不能工作。

function Foo(){} 
 
Foo.prototype = 'A'; 
 
var foo = new Foo(); 
 

 
// foo inherits directly from Object.prototype, not Foo 
 
console.log(Object.getPrototypeOf(foo) == Object.prototype) // true 
 

 
// foo also inherits constructor property from Object.prototype 
 
console.log(foo.constructor == Object) // true

于是一种情况,其中的instanceof失败可能指向程序设计或执行更严重的问题。隐藏这样的错误似乎不是一个好主意(除非意图是让代码中的陷阱留给未来的维护者去发现)。