2015-01-31 4 views
1

Я пытался делать некоторые простой тип проверки на наличие ошибок, и имел следующий код:isPrototypeOf говорит «нет», но instanceof говорит «да» - что происходит?

function isError(x) { 
    return Error.isPrototypeOf(x) 
} 

Однако, если я вызываю функцию с экземпляром ошибки, я получаю false, например, так:

isError(new RangeError) // false 

Так я разжег узел (ну, во всяком случае io.js), и сделал следующее:

> Object.getPrototypeOf(Object.getPrototypeOf(new RangeError)) 
[Error] 

в конце концов, если я делаю CHEC к с instanceof, он работает, как так:

> (new RangeError) instanceof Error 
true 

Итак, что же здесь происходит?

ответ

2

instanceof смотрит на .prototype собственности (т.е. не [[Prototype]]/__proto__) указанной функции конструктора для вас (то есть он делает некоторую дополнительную работу).

isPrototypeOf не работает должным образом и требует указания точного экземпляра объекта, который вы хотите проверить в цепочке прототипов.

Error.isPrototypeOf(r = new RangeError); // false. 

false, так как функция Error не сидит на цепи прототипов r. Цепочка прототипов r является:

r =>RangeError.prototype (ый экземпляра из Error) =>Error.prototype (ых экземпляра из Object))

Нигде на этой цепи является функцией Error конструктора, следовательно, ложный.

Если мы изменим ваш пример следующим образом:

Error.prototype.isPrototypeOf(r = new RangeError); // true. 

Это возвращает истину, потому что .prototype свойство Error функции является на цепи прототипов r.

+0

Действительно ли 'RangeError.prototype' является экземпляром 'Error'? –

+0

@KubaWyrostek Да, я верю, что это так. Если вы знаете лучше, пожалуйста, дайте мне знать. – Ben

+1

Я не знаю лучше. Я просто спросил. :-) Не правда ли, что это 'RangeError.prototype = Object.create (Error.prototype)', а не 'RangeError.prototype = new Error()'? –

6

isPrototypeOf и getPrototypeOf Посмотрите на цепочку прототипов напрямую, а instanceof смотрит на свойство .prototype данной функции-конструктора. Вы должны использовать:

function isError(x) { 
    return Error.prototype.isPrototypeOf(x) 
} 

Ваши функциональные тесты ли x наследуется от Error конструктора функции объекта.

+0

Но проще просто использовать 'instanceof'? –

+0

Это имеет смысл, спасибо. Это заставило меня попробовать что-то еще: 'Object.getPrototypeOf (Error) .isPrototypeOf (new RangeError)' возвращает false, а 'Error.prototype.isPrototypeOf (new RangeError)' возвращает true - что здесь происходит? –

+2

'Object.getPrototypeOf (новая ошибка()).isPrototypeOf (new RangeError) 'возвращает true, вы должны понимать разницу между свойством prototype конструкторов и прототипом экземпляров, обычно' __proto__' –

Смежные вопросы