日期:2014-05-16 浏览次数:20436 次
//继承 //实现singlaton //可以调用基类函数 //JavaScript通过构造函数和原型的方式模拟实现了类的功能。 var Class = (function(){ //IE不会遍历几个特殊属性:"constructor", "toString", "valueOf" var IS_DONTENUM_BUGGY = void function(){ for (var p in { toString: 1}) return false; return true; }(); function create(options){ var options = options || {}, uniqueInstance = null; //判定是否需要实现单例 var singleton = !!options.singleton; delete options.singleton; //父类 var superclass = options.inherit || {}; delete options.inherit; function klass(){ if (!singleton) this.init.apply(this, arguments); } //添加类方法 $U.extend(klass, Class.Methods); //是否继承 if ($U.isFunction(superclass)) { var bridge = function(){}; bridge.prototype = superclass.prototype; klass.prototype = new bridge; klass.superclass = superclass; } //添加原型方法 klass.addMethods(options); if (!klass.prototype.init) klass.prototype.init = function(){ }; //修正constructor klass.prototype.constructor = klass; //__proto__是什么?我们在这里简单地说下。每个对象都会在其内部初始化一个属性,就是__proto__,当我们访问一个对象的属性时,如果 //这个对象内部不存在这个属性,那么他就会去__proto__里找这个属性,这个__proto__又会有自己的__proto__,于是就这样 //一直找下去,也就是我们平时所说的原型链的概念。 //按照标准,__proto__是不对外公开的,也就是说是个私有属性,但是Firefox的引擎将他暴露了出来成为了一个共有的属性, //我们可以对外访问和设置。 //修复IE与Opera中的第二条原型链 if (!klass.prototype.__proto__) klass.prototype.__proto__ = klass.prototype; //处理函数:如果singleton模式,则private constructor return singleton ? { getInstance: function(){ if (!uniqueInstance) {// Instantiate only if the instance doesn't exist. uniqueInstance = new klass; uniqueInstance.init.apply(uniqueInstance, arguments); } return uniqueInstance; } } : klass; } function addMethods(source){ var ancestor = this.superclass && this.superclass.prototype, properties = $U.keys(source); //处理IE不能遍历的特殊属性。 if (IS_DONTENUM_BUGGY) { if (source.toString != Object.prototype.toString) properties.push("toString"); if (source.valueOf != Object.prototype.valueOf) properties.push("valueOf"); } for (var i = 0, length = properties.length; i < length; i++) { var property = properties[i], value = source[property]; //在C#中,如果子类有意隐藏基类成员,使用关键字"new" //使用base关键字显示调用基类构造函数 //这这里约定如果子类方法第一个参数是“$super”,则调用父类的方法. if (ancestor && $U.isFunction(value) && (value.argumentNames()[0] === "$super")) { var method = value; //var f = (function(m){ return function(){ return ancestor[m].apply(this, arguments)}})(property) //f.wrap(method) //F.prototype[name] = (function(name, fn) { // return function() { // var that = this; // $super = function() { // return baseClass.prototype[name].apply(that, arguments); // }; // return fn.apply(this, Array.prototype.concat.apply($super, arguments)); // }; //})(name, prop[name]); //总之,实现把基类函数作为子函数的第一个参数,以此调用父函数。 value = ancestor[property].wrap(method); value.valueOf = method.valueOf.bind(method); // 因为我们改变了函数体,所以重新定义函数的toString方法 // 这样用户调用函数的toString方法时,返回的是原始的函数定义体