<disclaimer>
What follows is the fruits of a thought experiment. What I'm doing
isn't the issue; the symptoms are. Thank you.
</disclaimer>
Наконец-то я сосредоточился на конструкторах, прототипах и наследовании прототипов в JavaScript.Но метод SomethingSpectactular в приведенном ниже примере дает мне сообщение:
function FinalClass() {
return {
FinalFunction : function() { return "FinalFunction"; },
TypeName : "FinalClass",
SomethingSpectacular : function() {
return FinalClass.prototype.SubFunction.call(this);
}
}
}
FinalClass.prototype = new SubClass();
FinalClass.constructor = FinalClass;
var f = new FinalClass();
Причины, по которым меня это беспокоит:
- JavaScript , по-видимому, не сканирует прототипцепочка для методов так же, как и для свойств.То есть
f.SubFunction()
генерирует ошибку. - Чтобы перейти к методу на прототипе, вам нужно выполнять как минимум 3 операции с точками каждый раз, когда вы хотите это сделать.FinalClass DOT прототип DOT Subfunctino DOT вызова.Вы понимаете.
- Методы базового класса (прототипа) не отображаются в Intellisense так, как я ожидал.Это очень раздражает.
Итак, мысленный эксперимент состоял в том, чтобы определить, что произойдет, если я напишу версию inherits
, которая вставит функции-заглушки в подкласс, который делегировал вам прототип.Например, он автоматически создаст следующую функцию и добавит ее в FinalClass
:
function SubFunction() { SubClass.prototype.SubFunction.call(this); }
Теперь у меня есть почти все, что намечено и работает.Метод inherits
, который является расширением как Object.prototype
, так и Function.prototype
, принимает Function
в качестве единственного аргумента.Это базовый класс.Подкласс определяется путем анализа Object.prototype.inherits.caller
.
. После этого я устанавливаю prototype
и constructor
для подкласса, а затем начинаю анализировать методы нового прототипа подкласса.Я создаю массив, содержащий методы как для прототипа, так и для открытого интерфейса базового класса.Конечным результатом является хороший массив, который содержит методы, предоставляемые либо через прототип, либо с помощью оператора return
конструктора базового класса.
Как только я это получу, я начну искать каждый метод в подклассе.Если его там нет, я добавляю его в подкласс с тем же именем и подписью.Однако тело метода просто перенаправляет вызов в базовый класс.
Теперь я могу пройтись по всему этому коду, и он работает чудесно, пока я не создаю экземпляров подклассы.Вот когда все становится не так.Вот что я наблюдал, используя Visual Studio 2008 (SP1) и Internet Explorer 8:
- До создания экземпляра
BaseClass
не предоставляет открытых методов.Этого следовало ожидать.Методы, предоставляемые с помощью оператора return
конструктора класса, не появятся, пока не будут созданы его экземпляры.У меня все хорошо. - До создания экземпляра
SubClass
предоставляет методы из BaseClass
.Это именно то, что я ожидал. - Как только я объявляю экземпляр
BaseClass
, в нем есть все члены, которых я ожидаю.Он имеет свои методы typeName
и BaseFunction
. - Как только я объявляю экземпляр
SubClass
, он имеет только те методы, которые возвращаются оператором return
его конструктора.Нет членов из базового класса нет.Похоже, что вся работа, выполненная в методе наследования для сопоставления методов базового класса с подклассом, была потеряна.
Большая загадка для меня здесь - это исчезновение методов, которые я добавил в подклассво время исполнения наследства.Во время его выполнения я ясно вижу, что SubClass изменяется, и что функции BaseClass распространяются.Но в тот момент, когда я создаю набор SubClass, этой информации больше нет.
Я предполагаю, что это как-то связано с конструктором, порядком событий или чем-то еще, чего я просто не вижу.
Заключительное примечание: Этот проект возник как попытка понять сложности JavaScript и то, как работает его система наследования прототипов.Я знаю, что существуют библиотеки.Я знаю, что заново изобретаю колесо.Я изобретаю это специально.Иногда лучший способ понять вещь - это построить ее самостоятельно.Это уже был огромный опыт обучения, но я просто озадачен этим конкретным моментом.
КОД
sti.objects.inherits = function inherits(baseClass) {
var subClass = sti.objects.inherits.caller;
var baseClassName = sti.objects.getTypeName(baseClass);
var methods = sti.objects.getMethods(baseClass);
if(!sti.objects.isDefined(baseClass.typeName))
baseClass.typeName = baseClassName;
var subClass = sti.objects.inherits.caller;
var subClassName = sti.objects.getTypeName(subClass);
var temp = function() {};
temp.prototype = new baseClass();
subClass.prototype = temp.prototype;
subClass.constructor = subClass;
subClass.typeName = subClassName;
subClass.baseClass = baseClass.prototype; // Shortcut to the prototype's methods
subClass.base = baseClass; // Cache the constructor
for(var index = 0; index < methods.items.length; index++) {
var resource = methods.items[index].getFunction();
var methodName = methods.items[index].getName();
if(methodName != "" && ! sti.objects.isDefined(subClass[methodName])) {
var method = sti.objects.createOverride(baseClassName, resource);
subClass[methodName] = method;
if(typeof subClass.prototype[methodName] == "undefined") {
subClass.prototype[methodName] = method;
}
}
}
}
Object.prototype.inherits = sti.objects.inherits;
Function.prototype.inherits = sti.objects.inherits;
function BaseClass() {
return {
A : function A() {return "A";}
};
}
function SubClass() {
inherits(BaseClass);
return {
B : function B() { return "B"; }
}
}
var b = new BaseClass();
var s = new SubClass();