Проверка instanceof работает на подклассе без установки конструктора [duplicate]

1

У меня есть следующий код JavaScript

function Parent() {
}

function Child() {
}

Child.prototype = Object.create(Parent.prototype);

Обратите внимание на отсутствие утверждения

Child.prototype.constructor = Child;

Я понимаю, что, поскольку свойство constructor не было установлено, проверки instanceof должны завершиться неудачно для новых экземпляров класса Child.

var child = new Child();
child instanceof Child; //Should give false

Я проверил, что конструктор неправильно установлен Изображение 174551

Но когда я запустил child instanceof Child, он дал мне истинную

Изображение 174551

Но это должно быть false, поскольку свойство конструктора не установлено на прототипе Child как Child.

Окружающая среда

Google Chrome Version 48.0.2564.109 (64-bit)
Ubuntu 14.04 LTS
  • 0
    Похожие страницы : stackoverflow.com/questions/8453887/…
  • 0
    @Bergi Хотя ответ на этот вопрос может быть связан с этим вопросом, IMO вопросы различаются.
Показать ещё 1 комментарий
Теги:
constructor
prototype
subclass
prototypal-inheritance

1 ответ

3
Лучший ответ

Мое понимание состоит в том, что поскольку свойство конструктора не было установлено, проверка экземпляра должна завершиться неудачно для новых экземпляров класса Child.

Нет, это неверно. Фактически, до ES2015 (иначе ES6) свойство constructor не использовалось ни для чего вообще в самом JavaScript. Он был определен как существующий на объектах по умолчанию, время выполнения назначает свойство prototype для функций, но не используется.

instanceof вообще не заботится о construtor. Рассмотрим:

o instanceof Foo

instanceof будет выглядеть, если объект Foo.prototype указывает на то, что находится в цепочке прототипов o. (Если "цепочка прототипов" не является знакомым термином, см. * В конце ответа, а затем возвращайтесь.) Если это так, он возвращает true; если нет, он возвращает false.

Например, здесь концептуальная реализация 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]] внутренний метод, указанный здесь.

Мы можем видеть, что 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.

  • 0
    Не могли бы вы перефразировать это - «с объектом, который является свойством прототипа функции, которую вы использовали»? Я не могу понять его значение. Возможно простой пример?
  • 1
    @ AseemBansal: Вы знаете, я написал это предложение и подумал: «Хм, ясно, как грязь?» Посмотрим, смогу ли я это исправить. :-)
Показать ещё 12 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню