场景:项目环境中使用了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))();
相关推荐
在JavaScript中,面向对象主要通过以下三种方式实现: 1. **构造函数(Constructor)**:构造函数是一种特殊的函数,用于创建和初始化对象。我们可以通过`new`关键字来调用构造函数,创建一个新的对象实例。例如: ...
在探讨面向对象的JavaScript之前,我们首先需要了解面向对象编程(Object-Oriented Programming, OOP)的基本特性:封装性、抽象性、继承性和多态性。 ##### 8.1.1 封装性 **定义:** 封装性是面向对象编程的一个...
JavaScript的核心在于对象、原型和隐式继承,这些都是理解其面向对象特性的重要概念。 首先,让我们深入理解对象。在JavaScript中,一切皆为对象,包括函数。你可以直接通过对象字面量或者构造函数来创建对象。对象...
**JS面向对象汇总PDF**是针对JavaScript编程语言中面向对象编程概念的一个综合性的学习资料,主要探讨了JavaScript如何实现面向对象编程(OOP)的设计原则和模式。在JavaScript中,面向对象编程是一种重要的编程范式...
本文将详细介绍五种JS实现面向对象继承的方法。 1. **对象冒充实现继承** 这种方式允许实现多继承。其原理是将父类的构造函数作为子类的一个方法,并在子类的构造函数中调用这个方法,通过`this`关键字为子类的...
以上知识点详细介绍了JavaScript面向对象编程中的基本特性、对象的定义方式以及如何通过不同方式实现封装、继承和多态。通过深入理解这些概念,可以帮助开发者更加高效和规范地进行JavaScript编程,编写出更加优雅...
研究发现,JavaScript语言具有良好的面向对象特性,特别是在封装性、继承性和多态性等方面。本文对JavaScript的面向对象语言特性进行了详细分析,并给出了具体的分析实例。 封装是面向对象的首要特征。 JavaScript...
面向对象编程的基础包括类、对象、继承和多态等概念。类是对象的模板或蓝图,定义了一组属性(数据成员)和方法(函数)。对象则是类的实例,具备类所定义的属性和行为。JavaScript虽然没有传统的类定义,但可以通过...
这篇博文将深入探讨JavaScript中的面向对象特性,包括类的概念、对象的创建、继承机制以及封装。 首先,JavaScript的类并非像Java或C++那样是真正的类,而是语法糖,它提供了更接近于传统类的语法结构,但底层仍然...
尽管它的名称中没有“对象”这个词,但JavaScript确实支持面向对象的编程范式。本文将深入探讨JavaScript的面向对象特性,帮助读者理解这个语言鲜为人知的一面。 首先,我们要明白JavaScript中的对象和类型系统。...
通过构造函数和原型,JavaScript实现了类和对象的继承,以及动态属性的添加,从而支持了面向对象编程的关键特性。 总结来说,JavaScript的面向对象编程主要包括以下几个方面: 1. **通过函数定义类**:函数作为...
7. **类(Class)语法**:虽然JavaScript原生支持基于原型的继承,但在ES6中引入了类语法,这使得JavaScript的面向对象编程更接近传统的类式继承模型。然而,即使有了类,JavaScript的实质仍然是基于原型的。 8. **...
《猜拳游戏:Java、Kotlin与JavaScript的面向对象实现》 在计算机科学领域,面向对象编程(Object-Oriented Programming, OOP)是一种广泛采用的编程范式,它通过模拟现实世界中的对象来构建软件系统。本项目“猜拳...
JavaScript,作为一种广泛使用的脚本语言,常常被误解为非面向对象的语言,但实际上,JavaScript完全支持面向对象编程(OOP)的三大核心原则:封装、继承和多态。尽管它的实现方式与传统的面向对象语言(如Java或C++...
在JavaScript中,面向对象编程(Object-Oriented Programming, OOP)是其核心概念之一,帮助开发者创建复杂、可复用的代码结构。在黑马2013赵栋的JS视频教程中,他深入讲解了这一主题,包括自己编写的源码示例。 1....
为了深入理解这一概念,我们首先要探讨面向对象编程(OOP)的基本原理及其在JavaScript中的实现方式,然后将通过分析提供的代码片段,揭示这些核心代码如何模拟OOP特性。 面向对象编程是一种编程范式,它依赖于对象...
JavaScript是一种广泛用于网页和网络应用的脚本语言,它具有灵活的数据类型和强大的面向对象特性。在JavaScript中,对象的定义和继承是核心概念。本文将深入探讨JavaScript的五种对象定义方法以及五种继承方式。 1....