场景:项目环境中使用了SeaJS做模块化加载,每个js文件是相对独立的一个模块,模块之间的耦合度降低了,但是它没有提供JS类之间的继承机制。怎样通过类继承的方式打通类之间的关联,充分使用对象对象带来的好处呢,可以参考motools( http://mootools.net/ )提供的类继承机制。
motools在提供了类继承机制的同时也扩展了很多JS底层的类和方法,扩展的类和方法在不以motools为js基础库的项目中很少用到或没有用。所以对motools的源码进行了精简,只保留了JS类继承相关的代码。如下:
(function() { Function.prototype.overloadSetter = function(usePlural) { var self = this; return function(a, b) { if (a == null) return this; //如果不是字符串,则遍历所有的key,分别设置key对应的值 if (usePlural || typeof a != 'string') { for ( var k in a){ self.call(this, k, a[k]); } } else { self.call(this, a, b); } return this; }; }; //为当前类添加属性 Function.prototype.extend = function(key, value) { this[key] = value; }.overloadSetter(); //为父类添加属性 Function.prototype.implement = function(key, value) { this.prototype[key] = value; }.overloadSetter(); //类型判断方法 var typeOf = this.typeOf = function(item) { if (item == null){ return 'null'; } //判断是否为数组 if(item && typeof item =="object" && Object.prototype.toString.call(item)=='[object Array]'){ return 'array' ; } return typeof item; }; //基本的扩展方法 var cloneOf = function(item) { switch (typeOf(item)) { case 'array': return item.clone(); case 'object': return Object.clone(item); default: return item; } }; //为Array添加clone方法 Array.implement({ clone : function() { var i = this.length, clone = new Array(i); while (i--) clone[i] = cloneOf(this[i]); return clone; } , append : function(array) { this.push.apply(this, array); return this; } }); var mergeOne = function(source, key, current) { switch (typeOf(current)) { case 'object': if (typeOf(source[key]) == 'object') Object.merge(source[key], current); else source[key] = Object.clone(current); break; case 'array': source[key] = current.clone(); break; default: source[key] = current; } return source; }; Object.extend({ merge : function(source, k, v) { if (typeof k == 'string'){ return mergeOne(source, k, v); } for (var i = 1, l = arguments.length; i < l; i++) { var object = arguments[i]; for ( var key in object) mergeOne(source, key, object[key]); } return source; }, clone : function(object) { var clone = {}; for ( var key in object) clone[key] = cloneOf(object[key]); return clone; }, append : function(original) { for (var i = 1, l = arguments.length; i < l; i++) { var extended = arguments[i] || {}; for ( var key in extended) original[key] = extended[key]; } return original; } }); //创建class对象 var Class = this.Class = function(params) { //如果类的参数为一个函数,则将函数定义为构造方法 if ((typeof params) == 'function'){ params = { initialize : params }; } //newClass扩展了类Class和参数的所有属性。Class是定义中声明的,参数是构造对象时传入的。 //注:可以看到构造函数的参数和类的构造参数相同。 var newClass = function() { reset(this); if (newClass.$prototyping){ return this; } this.$caller = null; //调用initialize方法 var value = (this.initialize) ? this.initialize.apply(this,arguments) : this ; this.$caller = this.caller = null; return value; }.extend(this).implement(params); newClass.$constructor = Class ; newClass.prototype.$constructor = newClass ; newClass.prototype.parent = parent ; return newClass; } ; var parent = function() { if (!this.$caller) throw new Error('The method "parent" cannot be called.'); var name = this.$caller.$name, parent = this.$caller.$owner.parent, previous = (parent) ? parent.prototype[name] : null; if (!previous) throw new Error('The method "' + name + '" has no parent.'); return previous.apply(this, arguments); }; //重置对象,如果为object,则构造一个中间类,创建新的对象 var reset = function(object) { for ( var key in object) { var value = object[key]; switch (typeOf(value)) { case 'object': var F = function() { }; F.prototype = value; object[key] = reset(new F); break; case 'array': object[key] = value.clone(); break; } } return object; }; //对函数的重包装,实际上还是调用原来的方法 var wrap = function(self, key, method) { if (method.$origin) method = method.$origin; var wrapper = function() { if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.'); var caller = this.caller, current = this.$caller; this.caller = current; this.$caller = wrapper; var result = method.apply(this, arguments); this.$caller = current; this.caller = caller; return result; }.extend({ $owner : self, $origin : method, $name : key }); return wrapper; }; //实现属性的赋值 var implement = function(key, value, retain) { if (Class.Mutators.hasOwnProperty(key)) { value = Class.Mutators[key].call(this, value); if (value == null){ return this; } } if (typeOf(value) == 'function') { if (value.$hidden){ return this; } this.prototype[key] = (retain) ? value : wrap(this, key, value); } else { Object.merge(this.prototype, key, value); } return this; }; /** * 获取实例化的对象 */ var getInstance = function(klass) { klass.$prototyping = true; var proto = new klass; delete klass.$prototyping; return proto; }; //为class添加或覆盖implement方法 Class.implement('implement', implement.overloadSetter()); Class.Mutators = { Extends : function(parent) { this.parent = parent; this.prototype = getInstance(parent); }, Implements : function(items) { if(!items){ return ; } //将items转换为数组 if(typeOf(items)!='array'){ items = [items] ; } for (var i = 0; i < items.length; i++) { var item = items[i] ; var instance = new item; for ( var key in instance){ implement.call(this, key, instance[key], true); } } } }; //属性类 this.Options = new Class({ setOptions : function() { //合并当前对象的options和传入的options参数 var options = this.options = Object.merge.apply(null, [ {},this.options ].append(arguments)); return this; } }); //在window命名空间下运行 }.bind(window))();
相关推荐
所以我们再说对象就有些模糊了,很多同学会搞混类型的对象和对象本身这个概念,我们在接下来的术语中不提对象,我们使用和Java类似的方式,方便理解 方式一 类(函数模拟) function Person(name,id){ //实例变量...
这种说法原因一般都是觉得javascript作为一门弱类型语言与类似java或c#之类的强型语言的继承方式有很大的区别,因而默认它就是非主流的面向对象方式,甚至竟有很多书将其描述为’非完全面向对象’语言。其实个人觉得...
这种说法原因一般都是觉得javascript作为一门弱类型语言与类似java或c#之类的强型语言的继承方式有很大的区别,因而默认它就是非主流的面向对象方式,甚至竟有很多书将其描述为’非完全面向对象’语言。其实个人觉得...
站点索引页面声明“除非另有说明,本站点上的所有代码和文档均属于公共领域”纯功能的面向对象系统目前的代码实现了一个无类的、基于委托的 OO 系统,类似于 Self 或 Javascript 的系统。 这是一个成熟的 OO 系统,...
ctr是使用JavaScript构建CSS框架,可提供面向对象的功能,以允许继承CSS组件具有丰富的层次结构,从而更好地促进类似于OOCSSCSS体系结构。 尽管ctr和OOCSS在应用程序上有很大的不同,但是您可以使用允许ct的真实对象...
主要介绍了javascript基于prototype实现类似OOP继承的方法,实例分析了JavaScript使用prototype实现面向对象程序设计的中类继承的相关技巧,需要的朋友可以参考下
(ES6有关键字class和extend,继承的语法与Java等面向对象语言类似,但是,ES6 class,只是JavaScript原型继承的语法糖而已) 1. 类式继承 关键点:通过构造函数实现继承。 父类: function Parent(name) { this....
类和继承带上onExtend()和onInitialize()钩子等等 界面用于文档隐式接口和验证对象 方法重载帮助您清理函数标题行中参数的类型声明 类似关键字的功能简化复杂表达式和重复代码的一系列功能 安装 安装nodejs npm...
JavaScript和其它面向对象语言一样,对象类型采用引用方式。持有对象的变量只是一个地址,而基本类型数据是值。当原型上存储对象时,就可能有一些陷阱。 先看第一个例子 代码如下:var create = function() { ...
这个文件中定义了类模型中类似于其他面向对象语言中的Object类。 如何新建类 作为基类,类的定义使用 var NewClass = Class.new(); 来进行定义。 通过以上方式定义的类,可以继承: var BClass = NewClass.extend...
我用同样的概念来概述js的这些方仿面向对象的概念,因为他们的行为作用类似。 在js中有如下函数 代码如下: function test(){ var var_value; this.this_value; } 其中,var_value是静态成员,this_value是动态成员。...
本文将使用面向对象的方式,来教大家用原生js写出一个类似jQuery这样的类库。我们将会学到如下知识点: 闭包:减少变量污染,缩短变量查找范围 自执行函数在对象中的运用 extend的实现原理 如何实现跨浏览器的...
js作为一门面向对象的语言,自然也拥有了继承这一概念,但js中没有类的概念,也就没有了类似于java中的extends,所以,我觉得js中的继承主要依赖于js中的原型(链)。 那么,原型是什么呢?我们知道js中函数亦是一种...
与许多面向对象的编程语言不同,JavaScript 具有原型继承而不是经典继承。 这意味着对象可以直接继承其他对象,而不是子类从超类继承的经典语言,并且对象是类的实例。 许多类似的框架使用伪经典继承模式,它们试图...
11) JavaScript中面向对象的特性: a) 实例属性:在构造函数创建或初始化的属性。 b) 实例方法:在构造函数中把原型对象中的一个属性设为函数来实现。 c) 类属性:构造函数本身的属性。 d) 类方法:用合适的函数作为...
与多数面向对象的开发语言有所不同,虽然JavaScript没有引入类似类的概念(ES6已经引入了class语法糖),但它仍然能够大量的使用对象,那么如何将所有对象联系起来就成了问题。于是就有了本文中我们要讲到的原型和...
在使用一些 Javascript 框架时,或许会看到类似的代码 代码如下: var ...这是一种典型的面向对象的类机制应用,与原生的 Javascript 类机制相比,显得更为清晰和自然。并且,在此基础上,实现类的继承也较为方便。
资料仅供学习,勿作商用! Curl语言是一种编程语言,它被设计用于编写网络程序。它的目标是以一种单一的语言来取代HTML, ...Curl语言便于学习,编程效率高,是一种支持多重继承,范型等数据类型的面向对象编程语言。
这个类提供了一些扩展面向对象编程的一些反射方法,通过这个类我们可以注册类似.NET中的一些(如:命名空间,类,枚举等等)基本类型。这个Type类继承自window是一个Global类型,不属于任何命名空间。下面我们来看看...
面向对象的模板继承。 将过滤器和转换应用到模板中的输出。 自动转义所有输出以安全地呈现HTML。 支持许多迭代和条件。 健壮无肿胀。 可扩展和可定制的。 有关一些示例,请参见 。 良好的。 需要帮忙? 有...