Я понимаю, что, как свойство конструктора не было установлено проверка InstanceOf должна терпеть неудачу для новых экземпляров класса Child.
Нет, это неправильно. Фактически, до ES2015 (aka ES6), свойство constructor
не было использовано для чего-либо вообще в самом JavaScript. Это было определено как существующее на объектах по умолчанию, время выполнения присваивает свойству prototype
функции, но не .
instanceof
все равно construtor
. Рассмотрим:
o instanceof Foo
instanceof
будет выглядеть, чтобы увидеть, если объект Foo.prototype
указывает на это в любом месте на цепочке прототипов o
«s. (Если «цепочка прототипов» не является знакомым термином, см. * В конце ответа, а затем возвращайтесь.) Если это так, он возвращает true
; если нет, он возвращает false
.
Например, вот концептуальный implementaton из instanceof
, ручной отмахиваясь некоторые детали:
function isAnInstance(obj, func) {
var p;
for (p = Object.getPrototypeOf(obj); p; p = Object.getPrototypeOf(p)) {
if (p === func.prototype) {
return true;
}
}
return false;
}
Хотя это вытесняется в ES2015 спецификации, я ссылку на спецификацию ES5, потому что она написана в более доступной язык и этот аспект не изменился: instanceof
эффективно просто вызывает внутренний метод функции [[HasInstance]]
, defined here.
Мы можем видеть, что constructor
не участвует из вашего вопроса, а также от этой простой демонстрации:
var p = {};
var o = Object.create(p);
var Foo = function() {};
Foo.prototype = p;
snippet.log(o instanceof Foo); // true
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Заметим, что:
o
не было созданный через Foo
- На самом деле,
Foo
даже не существовать пока o
была создана
o
и его прототип не имеют constructor
собственности на всех
... и еще instanceof
говорит: «Да, внешность как будто это Foo. " :-) Чисто, потому что объект Foo.prototype
указывает на также на прототип цепи o
.
* "прототип цепь"
Вы четко знаете, что объекты JavaScript имеют прототип, из которых они наследуют свойство. Эти прототипы являются объектами, и поэтому у них есть прототипы. Таким образом, вы получаете «цепочку» прототипов.
Рассмотрим два уровня (возможно, три уровня) иерархии наследования, здесь в ES5:
function Base() {
}
function Derived() {
Base.call(this);
}
Derived.prototype = Object.create(Base.prototype);
Derived.prototype.constructor = Derived;
... или в ES2015:
class Base {
}
class Derived extends Base {
}
Теперь мы используем его:
var d = new Derived();
(Где увидеть «d
объект»и аналогичные в ниже, я, конечно, имею в виду„объект d
относится к“ — но это действительно многословным.)
Теперь прототип d
объекта является Derived.prototype
. Прототипом Derived.prototype
является Base.prototype
. Base.prototype
- прототип Object.prototype
. Object.prototype
не имеет прототипа (его внутренний номер [[Prototype]]
- null
).
Эти объекты являются цепочка прототипов, лежащий в основе d
, и они имеют в виду, что это d
instanceof Object
, instanceof Base
и instanceof Derived
.
Связанный: http://stackoverflow.com/questions/8453887/why-is-it-necessary-to-set-the-prototype-constructor –
@Bergi Хотя ответ на этот вопрос может быть связан с этим вопросом, ИМО вопросы разные. –
@AseemBansal: определение SO «дубликат» (возможно, удивительно) не о том, что * вопросы * одинаковы, но отвечает ли ответ * на более ранний вопрос на этот вопрос. (Это также не уничижительно, а дубликаты улучшают шансы найти ответ, формулируя вопросы по-разному.) Я думаю, что Берги прав. (Он хорош в дубликатах.) –