def.js是以前在研究js继承的时候发现的一个颇有趣的js,恰巧如今前端团队中每周进行一次分享,就翻出来整理成一篇小文章javascript
先看一段def.js实现继承的方式前端
def ("Person") ({
init: function(name){
this.name = name;
},
speak: function(text){
alert(text || "Hi, my name is " + this.name);
}
});
def ("Ninja") < Person ({
init: function(name){
this._super();
},
kick: function(){
this.speak("I kick u!");
}
});
var ninjy = new Ninja("JDD");
ninjy.speak();
ninjy.kick();
复制代码
能够看到是以 < 实现的Ninja继承于Personjava
js中,当两个对象进行算术运算或大小比较时,若是运算符两边不是数值,则调用valueOf方法,因此def.js必定是重写了valueOf,在里面实现了继承git
下面看def.js的源码(为了阅读上下文方便,删除了中间空行)github
(function(global){
// def方法返回就是deferred方法,因此在继承时执行的valueOf为下文中看到的deferred.valueOf
var deferred;
// extend方法是经过混入的方式把deferred接收到的参数做为对象属性
function extend(source){
var prop, target = this.prototype;
for(var key in source) if(source.hasOwnProperty(key)){
prop = target[key] = source[key];
if('function' == typeof prop){
// 这两个属性是为了下文中实现._super调用超类的同名方法,起到标记做用
prop._name = key;
prop._class = this;
}
}
return this;
}
// 此方法用来调用超类的同名方法
function base(){
// callee已经在es5的严格模式中被弃用
var caller = arguments.callee.caller;
return caller._class._super.prototype[caller._name]
.apply(this, arguments.length ? arguments : caller.arguments);
}
function def(context, klassName){
klassName || (klassName = context, context = global);
// 在此处把经过def方法建立的类挂载到了global上
var Klass = context[klassName] = function Klass(){
if(context != this){
return this.init && this.init.apply(this, arguments);
}
// 把当前对象记录到deferred中,方便<左侧继承
deferred._super = Klass;
// 把超类后面的参数暂存在继承事后再把这些属性进行混入,相似一开始的例子中Person后面跟的参数
deferred._props = arguments[0] || { };
}
Klass.extend = extend;
deferred = function(props){
return Klass.extend(props);
};
function Subclass(){ }
deferred.valueOf = function(){
var Superclass = deferred._super;
if(!Superclass){
return Klass;
}
Subclass.prototype = Superclass.prototype;
var proto = Klass.prototype = new Subclass;
Klass._class = Klass;
Klass.toString = function(){
return klassName;
};
proto.constructor = Klass;
// 这个地方我把这两句放到一块儿的缘由,一个_super是在Klass对象上的,一个是在Klass.prototype上的
// 不明白的请复习原型链跟new的原理
Klass._super = Superclass;
proto._super = base;
deferred(deferred._props);
};
return deferred;
}
global.def = def;
}(this));
复制代码
最后还有一点就是def ("Ninja") < Person()
这句话的执行顺序app
固然现在es8都要来了,def.js也没什么使用场景了ui