1:如何模拟一個類
在sencha touch2 系列裡面定義一個類和new出這個類的對象
Ext.define(
"Animal", {
config: {
name: null
},
constructor: function(config) {
this.initConfig(config);
},
speak: function() {
console.log('說點什麼');
}
}
)
var my=Ext.create("Animal",{name:"bb"})
my.speak();
上面代碼裡面constructor在create的時候會自動調用,然後初始化config對象配置的屬性。constructor完全就像面對象裡面的構造函數……
下面我模拟一下
// 在sencha中new一個對象傳了兩個參數Ext.create("Animal",{name:"bb"})
// 這裡就不模拟sencha的命名空間了,是以生成該類的對象的時候傳一個配置對象即可
// 把命名空間(mss)和命名單獨提取出來,new mss.define({});
var mss = {} //建立一個命名空間
mss.define = function(config) {
if(typeof config !== 'object') {
console.log('參數錯誤');
return;
}
var interface = function() { //當new 該define傳回的函數,會自動執行atrr和init
this.attr && this.attr();
this.init && this.init.apply(this, arguments);
}
for(var i in config) {
config.hasOwnProperty(i) &&(interface.prototype[i] = config[i]);
}
return interface;
}
var Car = mss.define({
attr: function() {
this.type = '汽車';
},
init: function() {
console.log(this.type);
},
speank: function() {
console.log('我是' + this.type);
}
});
var car1 = new Car();
car1.speank();
輸出
汽車
我是汽車
[Finished in 0.1s]
這樣就模拟成了:define一個類,然後new出來調用其方法;
2:如何在此基礎上繼承一個類
首先看看sencha touch2系列的繼承
Ext.define(
"Person", {
extend: "Animal",
speak: function() {
console.log('我是人');
}
}
)
加多一個屬性extend搞定。
下面在mss.define模拟一下
// 在sencha中new一個對象傳了兩個參數Ext.create("Animal",{name:"bb"})
// 這裡就不模拟sencha的命名空間了,是以生成該類的對象的時候傳一個配置對象即可
// 把命名空間(mss)和命名單獨提取出來,new mss.define({});
var _mss = {} //建立一個命名空間
_mss.Define = function(parClass, curConfig) {
// 若sup 是個object,表示這是一個新類
// 若sup 是個function,表示這是一個繼承
if(typeof parClass === 'object') {
curConfig = parClass;
parClass = function() {};
}
// 定義傳回類
// 當new 該define傳回的函數,會自動執行atrr和init
var interface = function() {
this.attr && this.attr();
this.init && this.init.apply(this, arguments);
}
// 傳回類繼承 parClass
interface.prototype = new parClass();
// 為傳回類包含的兩個初始化函數定義基礎方法
// 獲得繼承的init方法 和attr方法
// 如果parClass存在init方法,那麼nterface.prototype.init
// 和new parClass().init相等
var parInit = interface.prototype.init || function() {};
var curInit = curConfig.init || function() {};
var parAttr = interface.prototype.attr || function() {};
var curAttr = curConfig.attr || function() {};
// 為傳回類原型初始化目前屬性,這裡注意可能被後面的方法重寫
for(var i in curConfig) {
curConfig.hasOwnProperty(i) && (interface.prototype[i] = curConfig[i]);
}
// 如果目前傳回類已經繼承了init,重寫該方法
if(arguments.length && arguments[0].prototype && arguments[0].prototype.init === parInit) {
interface.prototype.init = function() {
var scope = this;
var args = [function() {
parInit.apply(scope, arguments);
}];
var slice = [].slice;
curInit.apply(scope, args.concat(slice.call(arguments)));
}
}
// 如果目前傳回類已經繼承了attr,重寫attr 或者是首次構造改方法(新類)
interface.prototype.attr = function() {
parAttr.call(this);
curAttr.call(this);
}
// 繼承父類的成員屬性
for(var i in parClass) {
parClass.hasOwnProperty(i) && (interface[i] = parClass[i]);
}
return interface;
}
var Car = _mss.Define({
attr: function() {
this.type = '汽車';
},
init: function() {
console.log(this.type);
},
speank: function() {
console.log('我是' + this.type);
}
});
var car1 = _mss.Define(Car, {
})
new car1().speank();
輸出
汽車
我是汽車
[Finished in 0.1s]
對于call實作繼承
interface.prototype.attr = function() {
parAttr.call(this);
curAttr.call(this);
}
在Chorome控制台列印這段代碼就可以解釋一下這段代碼了
var _Attr = function() {
this.a = 1;
}
var B = function() {
this.attr();
};
B.prototype.attr = function(){_Attr.call(this);}
console.log(new B());
VM665:9 B {a: 1}a: 1__proto__: Battr: (){_Attr.call(this);}constructor: () {__proto__: Object