2017-04-07 148 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失敗可能指向程序設計或執行更嚴重的問題。隱藏這樣的錯誤似乎不是一個好主意(除非意圖是讓代碼中的陷阱留給未來的維護者去發現)。