JavaScript OOP не работает как Java или C#, не ожидайте этого, и не пытайтесь это сделать. Единственное, что может возникнуть в результате этого, - это недоразумения. Вместо того, чтобы пытаться заставить ваши старые парадигмы на языке, который создан совершенно по-другому, скорее узнайте, как работает OOP JavaScript.
JavaScript является объектно-ориентированным, но это не значит, что он имеет классы. По крайней мере, не так, как большинство разработчиков, пришедших с Java или подобных языков, думают о классах. У него также нет классического наследования. Тем не менее, все они могут быть «фальшивыми» или имитируемыми (именно это вы и пытаетесь сделать). Проблема с этим заключается в том, что разработчики, выходящие из Java или похожих, видят код, который выглядит как классы и классическое наследование, поэтому они считают, что это классы с классическим наследованием, и ожидают, что он будет вести себя как таковой, тогда как он может полностью работать другой.
Начнем с функции SuperClass
(потому что это то, что есть. Это функция, а не класс). Прежде всего, ваш код не является даже корректным синтаксисом, потому что ваша функция SuperClass
не заключает в скобки. Правильный синтаксис будет function SuperClass() { ... }
.
Во-вторых, JavaScript использует прототипы для обработки наследования между объектами (а не классами), и если вы хотите сделать прототипное наследование (какое из них предлагает ваш код), вы не можете вернуть новый анонимный объект из функция SuperClass
. Позвольте мне немного проиллюстрировать, что здесь происходит.
Когда вы называете SuperClass
функции (либо из функции childClass
, или из любого другого места), используя new
ключевое слово, как в var inst = new SuperClass();
, то, что эффективно происходит это следующим образом:
- JavaScript создает новый пустой объект, прототип которого равен
prototype
-property о функции, которую вы вызываете. В коде это будет var temp = Object.create(SuperClass.prototype);
.
- JavaScript вызывает вашу функцию с этим объектом как объект
this
. В коде это будет SuperClass.call(temp, <arguments>)
.
- Если функция возвращает что-либо, значение
inst
установлено в это значение, иначе оно установлено в значение temp
.
Теперь в вашей SuperClass
функции вы выполните следующие действия:
//Constructor implementation of this class
//public functions
return {
parentPublicFunction: function() {
//Public function implementation
}
}
function privateFunction() {
//Private function implementation.
}
Что здесь происходит, что ваш метод SuperClass
получить диалоги вызываются с this
, который является экземпляром SuperClass
, то есть. он имеет SuperClass.prototype
в своей прототипной цепочке. Это означало бы, что если вы, например, сделали this instanceof SuperClass
, вы бы получили true
, как и следовало ожидать. Затем вы идете и возвращаете новый анонимный объект, у которого есть свойство с именем parentPublicFunction
(которое просто является функцией, но может быть чем угодно). Этот новый объект, который вы возвращаете, не является экземпляром SuperClass
. Он не имеет SuperClass.prototype
в его собственности. Вы создали ситуацию, когда я делаю (new SuperClass()) instanceof SuperClass
, вы получаете false. Другими словами, экземпляр, который вы возвращаете из функции конструктора SuperClass
, не реализует ваш «класс». Это, вероятно, совсем не то, что вы намеревались, что является одной из причин, по которым вы не можете просто переложить классические принципы наследования на JavaScript и ожидать, что все будет работать одинаково.
Теперь, что мы имеем до сих пор, это имя функции SuperClass
, которое возвращает Object
без какого-либо отношения к SuperClass
. SuperClass
имеет прототип, который пуст, а это значит, что даже если вы каким-то образом создали объекты с SuperClass.prototype
в цепочке прототипов прототипа, он ничего не наследовал бы от SuperClass
, потому что нет ничего определенного для наследования. Что приводит нас к функции childClass
.
Прежде всего, я буду называть его ChildClass
вместо childClass
. Любая функция в JavaScript, которую вы ожидаете, вызовет людей с помощью new
, должна начинаться с верхнего регистра. Любую функцию, которую вы не ожидаете вызывать с new
, следует начинать с нижнего регистра. В JavaScript нет способа узнать, должна ли функция быть вызвана с или без new
, поэтому это используется для обозначения.
Теперь ChildClass.prototype
устанавливается как экземпляр SuperClass
, а это означает, что любые методы в прототипе SuperClass
«s будет вызывать из экземпляра ChildClass
. И любой экземпляр ChildClass
также является экземпляром SuperClass
(как и следовало ожидать).Однако, как уже объяснялось, прототип SuperClass
пуст, поэтому его не наследует. Таким образом, единственное, что дает ChildClass
, состоит в том, что a instanceof ChildClass
подразумевает, что a instanceof SuperClass
. Однако, как и в случае с SuperClass
, вы возвращаете анонимный объект от ChildClass
, что также приводит к тому, что (new ChildClass()) instanceof ChildClass
является ложным.
И в этом, ложь (большинство) ваших проблем. Решение состоит в том, чтобы узнать, как работает ООП в JavaScript и обнимает это при выполнении JavaScript, вместо того, чтобы пытаться склонить его к тому, как вы предполагаете, что нужно работать.
Переместить parentPublicFunction в прототип. – lujcon
@lujcon: Это само по себе не решит проблему. –