Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   "Классический" ООП в JavaScript (https://javascript.ru/forum/misc/2740-klassicheskijj-oop-v-javascript.html)

Андрей Параничев 05.02.2009 22:50

"Классический" ООП в JavaScript
 
Несколько раз начинал писать этот пост, но в итоге решил не распинаться, а спросить коротко и ясно.

Используете ли вы эмуляцию "классического" ООП (с классами и наследованием на классах) в своих проектах, или пользуетесь конструкторами и наследованием на прототипах? Или вообще не пользуетесь наследованием?

Kolyaj 05.02.2009 23:43

Зависит от используемого фреймворка. В данный момент в основном Ext, соответственно и наследование через Ext.extend. Если что-то делается без фреймворка, то, как правило, и наследование не особо нужно.

Андрей Параничев 05.02.2009 23:51

Kolyaj,
Другими словами, если бы ты решал задачу уровня ExtJS, но без фреймворка, то реализовал бы классическую модель ООП?

Kolyaj 05.02.2009 23:55

Цитата:

Сообщение от Андрей Параничев
если бы ты решал задачу уровня ExtJS, но без фреймворка

Пожалуй задачу уровня ExtJS не то что без фреймворка, а с любым другим трудновато решить.

Цитата:

Сообщение от Андрей Параничев
то реализовал бы классическую модель ООП?

Давай определимся, чтобы не говорить о разном: что есть классическая модель ООП?

Dmitry A. Soshnikov 06.02.2009 00:00

Чтобы более точно представить картину, надо понять, что, если говорить о разнице в подходах, то нужно говорить больше не о "класс vs. прототип" и даже не о "наследование vs. делегация", а в большей мере о "статика vs. динамика".

Я практически всегда для примера привожу классовую модель Python'a, чтобы показать, что разницы между "динамическим ООП на классах" и "ООП на прототипах" практически нет (если нужно будет привести примеры и показать сходство, скажите).

Что же касается статической классовой ООП модели (aka Java или C++), то ее просто физически нельзя сделать в JS (даже эмуляцию). Во сколько бы обертор мы не обернули бы конструкторы, внутри все равно будет prototype-base inheritance.

Единственное, для чего можно использовать обертки - это улучшение code reuse - вынос повторяющегося блока наследования (обеспечение связки прототипов) в обертку. Как потом эту обертку называют - "Class", "Extend", "Inherit" и т.д. - не суть важно, главное, чтобы человек понимал, что он делает. Другой вопрос, когда начинается непонимание технологии ввиду того, что человек не имеет достаточного объема информации и может доказывать то, что к JS не имеет никакого отношения. Часто причиной этому могут быть статьи с громкими заголовками типа "Наследование на классах в JS", которые подсознательно могут откладываться в умах людей, который пока поверхностно разбираются в JS, как "доведем до ума этот бесклассовый недоязык". Это уже неправильно.

А в целом - никто не ограничивает делать обертки (для улучшения code reuse'a) и называть как вздумается. У меня в одном проекте был виджет-фреймворк написан, где было построено наследование виджетов (aka Widget -> WidgetPanel -> WidgetWindow -> WidgetDialog и т.д.). Для чего я использовал там обертку? - Чтобы вынести в нее блок кода, обеспечивающий связку прототипов. Все. Объективно, это единственная причина, т.к. вся эта мишура с оберткой, могла бы быть описана и без нее - и без потери какой-либо читабельности и функциональности. Но мне было удобней с обреткой.

Поэтому, если анализировать различия, то, повторю, в большей мере надо говорить о "статика vs. динамика"; пара же "прототип vs. класс" очень больших отличий не покажет.

Андрей Параничев 06.02.2009 00:00

Kolyaj,
Цитата:

Сообщение от Kolyaj
Пожалуй задачу уровня ExtJS не то что без фреймворка, а с любым другим трудновато решить.

Ну это вопрос чисто теоретический. Скорее вопрос должен был звучать "если бы ты писал ExtJS, ты бы использовал эмуляцию классического ООП?".

Цитата:

Сообщение от Kolyaj
Давай определимся, чтобы не говорить о разном: что есть классическая модель ООП?

Я по этим понятием подразумеваю описание классов и наследование, которое основывается на классах.

Kolyaj 06.02.2009 00:11

Цитата:

Сообщение от Андрей Параничев
если бы ты писал ExtJS, ты бы использовал эмуляцию классического ООП?

Так а че там? Сделали функцию-обертку для связывания прототипов, вот тебе и классическое ООП настолько, насколько это возможно и нужно в JavaScript.

Dmitry A. Soshnikov 06.02.2009 00:15

Цитата:

Сообщение от Kolyaj
вот тебе и классическое ООП

Вот тебе и ООП с оберткой. "Классическое", "основанное на классах" - не стоит в противоположном углу, относительно "прототипное". Противопоставляется только динамика-статика.

Kolyaj 06.02.2009 00:19

Dmitry A. Soshnikov,
ну я в рамках предложенного определения
Цитата:

Сообщение от Андрей Параничев
Я по этим понятием подразумеваю описание классов и наследование, которое основывается на классах.


Андрей Параничев 06.02.2009 00:34

Dmitry A. Soshnikov,
Спорить по вопросу статика vs. динамика в рамках JavaScript, как я понимаю, бессмысленно. Поэтому мы говорим только о динамической модели. Ясно, что реализация динамического классового ООП на JavaScript это то же прототипное ООП, вид сбоку.

Практически все фреймворки стремятся к динамической классовой модели, причем это не только обертка для перелинковки прототипов, но и установка дополнительных свойств и фабрика конструкторов. Насколько это оправданно? И насколько сложнее реализация/поддержка/рефакторинг без такой обертки?

Kolyaj,
Цитата:

Сообщение от Kolyaj
насколько это возможно и нужно в JavaScript.

Ключевое слово - нужно, а без такой обертки не реализовать удобное наследование?

Просто я не видел пример "элегантного" наследования на прототипах, которое бы сохраняло функциональность конструктора родительского класса, выстраивала цепочку прототипов (для instanceOf) и правильно линковала constructor. И чтоб она была без прослойки.

Kolyaj 06.02.2009 09:02

Цитата:

Сообщение от Андрей Параничев
Просто я не видел пример "элегантного" наследования на прототипах, которое бы сохраняло функциональность конструктора родительского класса

Его просто не может существовать, т.к. наследуются не классы, а объекты.

Dmitry A. Soshnikov 06.02.2009 11:37

Цитата:

Сообщение от Андрей Параничев
Ясно, что реализация динамического классового ООП на JavaScript это то же прототипное ООП, вид сбоку.

Это не только вид сбоку, это 97% - то же самое, только в другой терминологии. Неназванная связка "конструктор + прототип" в JS - есть "ссылка на класс + класс" в Python'e.

Ну вот найди сильные отличия:

# python

class A(object):
  def __init__(self):
    self.a = 10

// аналог на JS

function A() {
  this.a = 10
}

x = A() # py
var x = new A(); // js

x.a # 10, py
x.a // 10, js

A.b = 20 # добавим новое свойство в класс, доступное всем инстансам
A.prototype.b = 20; // аналог на js

x.b # 20, py
x.b // 20, js

// Однако, свойство "b" не является родным для объектов "x"
// сделаем его родным

x.b = 30 # py
x.b = 30 // js

x.b # 30, py
x.b // 30, js

// Удалим родное свойство "b"

del x.b # py
delete x.b // js

// Снова, за счет делегации к классу (к цепи классов; в Питоне)
// и к прототипу (к цепи прототипов; в JS)
// доступно свойство "b"

x.b # 20, py
x.b // 20, js

// Более того, можно расширять класс / прототип через инстанс:

x.__class__.c = 30 # py
x.__proto__.c = 30 // js (__proto__ - спечифично для конкретной реализации, но - не суть)

x.c # 30, py
x.c // 30, js

// Наследование

# py

class B(A):
  def __init__(self):
    A.__init__(self)

// js

function B() {
  B.superclass.apply(this, arguments);
}

// блок, для вынесения в обертку (для улучшения code reuse, чтобы каждый раз не повторять одно и то же)

// одна из реализаций

var __inheritance = function () {};
__inheritance.prototype = A.prototype;
B.prototype = new __inheritance();
B.prototype.constructor = B;
B.superclass = A;

// при этом, конструктор может издохнуть после порождения
// объекта, и объект за счет своей (неявной) ссылки на прототип
// будет иметь доступ к прототипу

// аналогичная картина и Python'e:
// сслыка на класс - "А" - может издохнуть,
// но порожденный объект все еще будет иметь
// доступ к классу за счет ссылки на класс, включая явную - __class__

// примеры не привожу, здесь понятно.


Цитата:

Сообщение от Андрей Параничев
Спорить по вопросу статика vs. динамика в рамках JavaScript, как я понимаю, бессмысленно. Поэтому мы говорим только о динамической модели.

Да мы и не спорим, мы рассуждаем. Просто когда говорят о "классовая модель", это может восприниматься как классы из статической модели. В то время, как, практически нет отличий в динамической классовой модели от прототипной (и в Python'e можно динамически менять классы (просто меняя ссылку __class__) и apply'ить (делегировать) к изначально несвязанным методам). Поэтому можно спросить: что такое "Практически все фреймворки стремятся к динамической классовой модели", если уже изначально практически отличий нет. Я вижу ответ, как - лишь добавить обертку для наследования, ну, и, может, добавить пару слотов для какого-нибудь еще синтаксического сахара. В принципе, это удобно.

Андрей Параничев 06.02.2009 15:22

Dmitry A. Soshnikov,
Спасибо за разъяснения. Получается, что простая реализация наследования реализуется с избыточным кодом:
var __inheritance = function () {};
__inheritance.prototype = A.prototype;
B.prototype = new __inheritance();
B.prototype.constructor = B;
B.superclass = A;


Который рациональнее прятать в отдельную функцию. Получается, что это скорее "стандартный прием", чем простое упрощение.

Цитата:

Сообщение от Dmitry A. Soshnikov
что такое "Практически все фреймворки стремятся к динамической классовой модели", если уже изначально практически отличий нет.

Да это так, единственное отличие в том, что python получает ссылку на родительский класс "наглядно", а в JavaScript - конструкцией из 4х строк минимум.

Фреймворки и убирают этот момент, делая динамические классы:
var myClass = new Class({
    "extend": myParentClass,
    "constructor": function() { /* "конструктор" */ },
    "property": "value"
});


Я и хотел узнать, насколько такой подход необходим и насколько считается "плохим тоном", говоря о JavaScript. Получается, что такой вариант помогает убрать избыточность, которую порождает обычный подход конструктор-прототип. Хоть я и разобрался в наследовании на прототипах, но думал, что что-то упустил. Потому что не понимал, зачем во фреймворках используется "эмуляция классического ООП", а именно - вид динамического ООП на классах.

Dmitry A. Soshnikov 06.02.2009 17:33

Цитата:

Сообщение от Андрей Параничев
Я и хотел узнать, насколько такой подход необходим и насколько считается "плохим тоном", говоря о JavaScript.

Если человек понимает, что он делает и зачем (и это, действительно, технологически обосновано) - никакого плохого тона здесь нет. "Плохой тон" начинается тогда, когда человек начинает мыслить (в виду недостатка информации) о JS, как о "недоязыке, который даже языком не является, т.к. в нем нет классов". Но, если начинаются такие мысли, то, я думаю, такой человек смутно понимает и ООП на классах (да и программирование в целом).

Касательно же обертки - никакого плохого тона. Иначе "плохим тоном" можно было бы назвать и это:

for (var k = 0; k < 3; k++) {
  alert(k);
}


У нас есть повторяющийся кусок кода, мы его выносим в цикл. Можно было бы привести пример - выносим в функцию - не суть, то же самое.

Иначе:

alert(0);
alert(1);
alert(2);


Это, стало быть, не "плохой тон", т.к. мы не используем обертку для повторяющегося куска кода. Ну, да, code reuse методом copy-paste - очень "красивый" метод ;)

Zeroglif 06.02.2009 20:01

Цитата:

Я и хотел узнать, насколько такой подход необходим и насколько считается "плохим тоном", говоря о JavaScript.
А какой подход-то? Я вижу обычный вызов, в аргументе объект... давайте что ли в нутрь 'Class' посмотрим, чего там происходит против "стандартного" способа.

Андрей Параничев 06.02.2009 21:54

Zeroglif,
Там ничего против, естественно, не происходит. Я просто хотел узнать насколько необходимо использование оберток в реализации наследования.

Zeroglif 06.02.2009 22:43

Цитата:

Сообщение от Андрей Параничев (Сообщение 12221)
Zeroglifнасколько необходимо использование оберток в реализации наследования.

Острой необходимости нет. ;)

Pavel_Volodko 02.03.2009 20:22

Вставлю свои "пять копеек"...

Основная суть данной темы - не красивость или какая-то верность принципам классического ООП. Просто классовое наследование может существенно облегчить жизнь при реализации сложных проектов.

Что я понимаю под классовым наследованием?

1. Возможность четкого определения принадлежности объекта классу (instanceOf)
2. Возможность вызова конструктора или любого метода базового класса

Это то, что хочется получить. Очевидно, что в JavaScript без "обёрток" не обойтись. Ну, а чем "элегантнее" и проще это будет сделано, тем лучше.

Кстати, интересно будет узнать ваше мнение, коллеги, по поводу моей "обёртки" (Классическое наследование в JavaScript).

Буду благодарен за любые отзывы :yes:

Kolyaj 02.03.2009 21:14

Цитата:

Сообщение от Pavel_Volodko
Ну, а чем "элегантнее" и проще это будет сделано, тем лучше.

Че-та на простоту у вас не тянет.

Pavel_Volodko 02.03.2009 21:26

Цитата:

Сообщение от Kolyaj (Сообщение 13439)
Че-та на простоту у вас не тянет.

Вы про статью? Или про результат :no:

var DerivedClass = function() {

    arguments.callee.$super.call(this);

}.$extends( BaseClass ).$class( function ($super) {

    this.someMethod = function () {
        return $super.someMethod.call(this);
    }

});


Что тут сложного? Вопрос серьёзный, т.к. мне интерестно узнать мнения разных людей.

Kolyaj 02.03.2009 21:32

Благополучно забыв, что в вашей статье описывается (т.е. читая вышеприведеный код без знания вашего механизма наследования), я не понимаю, что делают функции $class и самая первая.

Во-вторых, определение функций в конструкторе а-ля this.someMethod = function() {} создает для каждого объекта свой набор методов, вместо ссылок на прототип.

Pavel_Volodko 02.03.2009 21:50

Цитата:

Сообщение от Kolyaj (Сообщение 13442)
Благополучно забыв, что в вашей статье описывается (т.е. читая вышеприведеный код без знания вашего механизма наследования), я не понимаю, что делают функции $class и самая первая.

Во-вторых, определение функций в конструкторе а-ля this.someMethod = function() {} создает для каждого объекта свой набор методов, вместо ссылок на прототип.

Ага! :victory: Значит, что делает функция $extends() понятно. Соответственно, не всё так плохо (имеется ввиду в моей "обёртке").

Первая функция - конструктор класса DerivedClass (исправил название класса в предыдущем посте).
Функция $class() - нужна для "финальной сборки" класса.

Об этом, правда, подробнее можно узнать из статьи. Нет смысла здесь дублировать.

Что касается "определение функций в конструкторе а-ля this.someMethod" - эту проблему тоже решает функция $class().
Функция someMethod создается только один раз для всего класса.

P.S. Спасибо за отзыв :yes:

Kolyaj 02.03.2009 21:59

Вы не поняли, я не прошу объяснять код, а говорю, что если мне придется читать подобный код, уйдет слишком много времени на осмысливание обертки.

Лично у меня сейчас модифицированный способ из Prototype, в Ext'е похожий по использованию.
var A = Class.create({
    init: function() {
    },

    method1: function() {
    },

    method2: function() {

    }
});

var B = Class.extend(A, {
    init: function() {
    },

    method3: function() {
    },

    method4: function() {

    }
})

Pavel_Volodko 02.03.2009 22:08

Первое, что мне лично не нравится - Prototype (как и многие другие фрэймворки) создаёт "наследование" путём копирования свойств и методов из одного класса в другой. Полагаю instanceOf тут не работает?

Второе - а как насчет вызова конструктора и методов базового класса? Вот это на самом деле и есть главная задача. По крайней мере, моя.

Kolyaj 02.03.2009 22:13

Цитата:

Сообщение от Pavel_Volodko
создаёт "наследование" путём копирования свойств и методов из одного класса в другой

Неверное предположение.

Цитата:

Сообщение от Pavel_Volodko
а как насчет вызова конструктора и методов базового класса?

var B = Class.extend(A, {
    init: function() {
        B.superclass.init.apply(this, arguments);
    }
});

Pavel_Volodko 02.03.2009 22:49

Цитата:

Сообщение от Kolyaj (Сообщение 13451)
Неверное предположение.

Разве?

Ну, посмотрим в Prototype (version 1.6.0.3, метод Class.create()):

...
for (var i = 0; i < properties.length; i++)
      klass.addMethods(properties[i]);
...


Хотя instanceof, надо признать, всё же работает (для вашего примера).

Kolyaj 02.03.2009 22:55

Это не наследование реализуется, а новые методы навешиваются. Наследование там стандартное
klass.prototype = new subclass;


Впрочем сейчас в Prototype слишком много всего непонятно для чего.

Pavel_Volodko 02.03.2009 22:59

Цитата:

Сообщение от Kolyaj (Сообщение 13457)
Это не наследование реализуется, а новые методы навешиваются. Наследование там стандартное
klass.prototype = new subclass;


Впрочем сейчас в Prototype слишком много всего непонятно для чего.

Вот и я о том же. "Навешивание методов" из той же оперы.

Zeroglif 02.03.2009 23:18

Pavel_Volodko,

Сходу скачал только финальный вариант, сразу возник вопрос - почему передаются функции, а не заранее созданный объект-прототип? В смысле, в чём фишка? ;)

upd а, идею функций понял, нужен верный $className...
upd2 и не хочется копировать...

Kolyaj 02.03.2009 23:19

А чем ваш способ this.method = function() {} отличается от приведенного прототайповского? (ну кроме того, что в прототайпе лучше тем, что вешается все на prototype)

Zibba 02.03.2009 23:21

Pavel_Volodko,
И мелкий же шрифт исходников у Вас в блоге, чуть глаза не сломал :/

x-yuri 03.03.2009 03:53

Цитата:

Я просто хотел узнать насколько необходимо использование оберток в реализации наследования
имхо, наследование на основе прототипов - естественное для javascript. Мне вот интересно, для чего эмулировать классическое наследование? Для людей которые к нему привыкли? Или есть еще причины?

p.s. эмулировать классическое наследование не сложнее чем использовать наследование, основанное на прототипах? Т.е. естественный вариант должен быть проще, по идее

Zeroglif 03.03.2009 13:16

Цитата:

Сообщение от x-yuri
Или есть еще причины?

Реюз со своими тараканами. Например, автор характеризует классовое наследование, как:
Цитата:

1. Возможность четкого определения принадлежности объекта классу (instanceOf)
Чёткость в js почти невозможна ;) , а instanceоf ни разу не показывает принадлежность к "классу".
Цитата:

2. Возможность вызова конструктора или любого метода базового класса
Так ли важно цепляться за структуру, сохраняя суперы? Не знаю, у каждого свои тараканы.

Dmitry A. Soshnikov 03.03.2009 13:45

Цитата:

Сообщение от Zeroglif
Реюз со своими тараканами.

Вероятно, это единственная причина подобных (удобных, относительно своих тараканов) обёрток.

Pavel_Volodko 03.03.2009 15:17

Цитата:

Сообщение от Zeroglif (Сообщение 13462)
Pavel_Volodko,

Сходу скачал только финальный вариант, сразу возник вопрос - почему передаются функции, а не заранее созданный объект-прототип? В смысле, в чём фишка? ;)

upd а, идею функций понял, нужен верный $className...
upd2 и не хочется копировать...

Не совсем понял что значит "нужен верный $className"...
Фишка действительно в использовании функции вместо объекта-прототипа. Хотя, на самом деле, всё гениальное просто: для создания связной иерархии классов нужно цеплять прототипы к функциям-конструкторам. Имея только объект-прототип, мы такой возможности не имеем. Приходится извращаться со всякими __proto__, копированием методов или созданием фэйковых подклассов. А вот имея функцию-конструктор для создания объекта-прототипа всё делается элементарно.

upd копировать и не обязательно. Я сам очень настороженно отношусь к решениям, которым мне не до конца понятны. Я просто поделился тем, что сделал под себя. Just FYI, как говорится.

Цитата:

Сообщение от Kolyaj (Сообщение 13463)
А чем ваш способ this.method = function() {} отличается от приведенного прототайповского? (ну кроме того, что в прототайпе лучше тем, что вешается все на prototype)

В принципе, описано чуть выше.
На мой взгляд, достаточно заглянуть в метод Class.create() от Prototype, чтобы задаться кучей вопросов. Кроме того, выражение "вешается все на prototype" мне кажется странным (хотя, думаю, я понимаю что вы имеете ввиду) и уж тем более я не считаю это лучшим решением.

Kolyaj 03.03.2009 15:36

Цитата:

Сообщение от Pavel_Volodko
На мой взгляд, достаточно заглянуть в метод Class.create() от Prototype, чтобы задаться кучей вопросов.

Когда я привожу в пример Prototype, я имею в виду версию где-то 1.5, где было еще поменьше лишнего. Другими словами принцип, а не реализация.

Цитата:

Сообщение от Pavel_Volodko
Кроме того, выражение "вешается все на prototype" мне кажется странным

Свойство -- prototype, фреймворк -- Prototype.

Pavel_Volodko 03.03.2009 15:37

Цитата:

Сообщение от Zibba (Сообщение 13464)
Pavel_Volodko,
И мелкий же шрифт исходников у Вас в блоге, чуть глаза не сломал :/

Звиняйте, уж больно много кода было. В следующий раз будет по-крупнее.

Цитата:

Сообщение от x-yuri (Сообщение 13490)
имхо, наследование на основе прототипов - естественное для javascript. Мне вот интересно, для чего эмулировать классическое наследование? Для людей которые к нему привыкли? Или есть еще причины?

p.s. эмулировать классическое наследование не сложнее чем использовать наследование, основанное на прототипах? Т.е. естественный вариант должен быть проще, по идее

Дело не в эмулировании. Дело в том, что я расширяю стандартные возможности javascript или пытаюсь сделать что-то немного удобнее для использования при разработке. Если решение мне помогает - цель достигнута.
Насчет "естественный вариант должен быть проще, по идее" - проще не значит лучше. Я и сам за простые решения.
Кстати, с этой точки зрения, моё решение абсолютно естественное, т.к. построено на элементарных возможностях прототипного наследования.

Pavel_Volodko 03.03.2009 15:46

Цитата:

Сообщение от Zeroglif (Сообщение 13520)
Реюз со своими тараканами. Например, автор характеризует классовое наследование, как:

Чёткость в js почти невозможна ;) , а instanceоf ни разу не показывает принадлежность к "классу".

Так ли важно цепляться за структуру, сохраняя суперы? Не знаю, у каждого свои тараканы.

Я бы даже сказал: "чёткость в javascript - понятие расплывчатое" :agree:

По поводу instanceоf - по-подробнее плиз :stop:

Что касается "цепляться за структуру, сохраняя суперы" - только там где это нужно, естественно.

Цитата:

Сообщение от Dmitry A. Soshnikov (Сообщение 13526)
Вероятно, это единственная причина подобных (удобных, относительно своих тараканов) обёрток.

Тараканы - двигатель прогресса (c) :yes:

Zeroglif 03.03.2009 16:02

Цитата:

Сообщение от Pavel_Volodko
А вот имея функцию-конструктор для создания объекта-прототипа всё делается элементарно.

Не намного элементарнее. Вы объединили несколько задач в одну. Цепочка наследования (делегирования) выстраивается с помошью объекта-прототипа, созданного "промежуточным" конструктором в стиле (паттерн by Lasse Reichstein Nielsen):

function inheritObject(object) { 
  function Dummy(){}; 
  Dummy.prototype = object; 
  return new Dummy(); 
}


Одновременно вместо Dummy для "подклассов" используется заранее подготовленная и заложенная в функцию структура. То есть, получив правильно прилинкованный объект-прототип, вы вместо:

Person.prototype.x =//...
Person.prototype.y =//...


используете:
this.x = //...
this.y = //...


что, в принципе, почти то же самое кроме доступа к локальным переменным функции из методов. Отсюда 2 вывода - то ли вам важны локальные переменные ($className), то ли вам не нравится "обвешивать" объект-прототип руками или через for-in...

Zeroglif 03.03.2009 16:15

Цитата:

Сообщение от Pavel_Volodko
По поводу instanceоf - по-подробнее плиз

instanceof не оправдывает своего названия буквально и является терминологической натяжкой из чужого class-based мира, в js объекты наследуют от объектов, понятия "класс" не просто нет, а если бы оно даже и было, то мы бы столкнулись с задачей определения, что включить в этот термин - прототип или прототипы, конструктор или конструкторы, или всё вместе, что участвовало в создании цепочки или её составляет, при этом, если цепь прототипов после содания хе-хе "instance" можно считать стабильной и связанной с ним, то свойству 'prototype' конструкторов можно присваивать другие значения, что делает алгоритм instanceof в этом случае бесполезным.


Часовой пояс GMT +3, время: 03:29.