Привет, читатель. Я попробовал переписать функцию Ext.extend(), которая используется для реализации наследования в ExtJS, в простом для понимания виде. Также в конце заметки содержится схемка, визуально показывающая возникающие в процессе наследования связи.
Посмотрим исходный код Ext.extend(), который можно найти в adapter/ext/ext-base-debug.js:
Ext.apply(Ext, {
extend : function() {
// inline overrides
var io = function(o){
for(var m in o){
this[m] = o[m];
}};
var oc = Object.prototype.constructor;
return function(sb, sp, overrides){
if(typeof sp == 'object'){
overrides = sp;
sp = sb;
sb = overrides.constructor != oc ?
overrides.constructor :
function(){sp.apply(this, arguments);};
}var F = function(){},
sbp,
spp = sp.prototype;
F.prototype = spp;
sbp = sb.prototype = new F();
sbp.constructor=sb;
sb.superclass=spp;
if(spp.constructor == oc){
spp.constructor=sp;
}sb.override = function(o){
Ext.override(sb, o);
};
sbp.superclass = sbp.supr = (function(){
return spp;
});
sbp.override = io;
Ext.override(sb, overrides);
sb.extend = function(o){return Ext.extend(sb, o);};
return sb;
};
}()
});
Попытка сразу отследить все связи в уме слегка вынесла мозг. Я решил разложить все по полочкам. Используя Ext.apply() можно сгруппировать разбросанные присваивания в удобочитаемый вид. Вот что у меня вышло:
Ext.apply(Ext, {
extend : function() {
// inline overrides
var io = function(o) {
for (var m in o) {
this[m] = o[m];
}};
return function(sb, sp, overrides) {
// Если передается только конструктор и объект со свойствами
// для нового прототипа (далее объект конфигурации)
if (typeof sp === 'object') {
overrides = sp;
sp = sb;
// Если конструктор указан в объекте конфигурации, то
// используем его
if (overrides.constructor !== Object) {
sb = overrides.constructor;
}// Если не указано конструктора, то генерируем дефолтный
else {
sb = function() {
sp.apply(this, arguments);
};
}}// <-- Теперь sb это конструктор класса потомка,
// <-- sp это конструктор класса предка
// Ссылка на прототип класса предка
var spp = sp.prototype;
// Создаем пустой конструктор с прототипом класса предка
var F = function() {};
F.prototype = spp;
Ext.apply(sb, {
// Создаем ссылки на Ext.override и Ext.extend для использования
// напрямую из объекта конструктора
override : function(o) {
Ext.override(sb, o);
},
extend : function(o) {
return Ext.extend(sb, o);
},
// Прототип класса потомка - объект, прототип которого
// ссылается на прототип класса предка
prototype : new F(),
// Ссылка на прототип класса предка
superclass : spp
});
// <-- Теперь конструктор sb содержит пустой объект, прототип которого
// <-- ссылается на прототип класса предка
// Наполняем прототип класса потомка
Ext.apply(sb.prototype, {
// Ссылка на конструктор класса потомка
constructor : sb,
// Получение прототипа класса предка
superclass : function() {
return spp;
},
supr : sb.prototype.superclass,
override : io
});
// <-- Теперь объект прототипа содержит ссылку на конструктор
if (spp.constructor == Object) {
spp.constructor = sp;
}// Пишем свойства объекта конфигурации в прототип конструтора
// класса потомка
Ext.override(sb, overrides);
// <-- Наследование завершено
return sb;
};
}()
});
Комментарии должны тебе помочь понять все этапы работы Ext.extend(). В компактном виде функцию можно представить так:
Ext.apply(Ext, {
extend : function() {
var io = function(o) {
for (var m in o) {
this[m] = o[m];
}};
return function(sb, sp, overrides) {
if (typeof sp === 'object') {
overrides = sp;
sp = sb;
sb = (overrides.constructor !== Object) ?
overrides.constructor :
function() { sp.apply(this, arguments); };
}var F = function() {};
F.prototype = sp.prototype;
Ext.apply(sb, {
override : function(o) { Ext.override(sb, o); },
extend : function(o) { return Ext.extend(sb, o); },
prototype : Ext.apply(new F(), {
constructor : sb,
superclass : function() { return sp.prototype; },
supr : sb.prototype.superclass,
override : io
}),
superclass : sp.prototype
});
if (sp.prototype.constructor == Object) {
sp.prototype.constructor = sp;
}Ext.override(sb, overrides);
return sb;
};
}()
});
Следующей схемой можно представить связки, которые возникают при наследовании:

Надеюсь тебе помогла эта заметка лучше разобраться в наследовании, которое применяется в ExtJS.
Для меня осталось непонятным для чего нужны строки 72-74 ?