`
lp895876294
  • 浏览: 279643 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

JS类以面向对象的方式继承

    博客分类:
  • JS
 
阅读更多

       场景:项目环境中使用了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))();

 

分享到:
评论

相关推荐

    详解JS面向对象编程

    所以我们再说对象就有些模糊了,很多同学会搞混类型的对象和对象本身这个概念,我们在接下来的术语中不提对象,我们使用和Java类似的方式,方便理解 方式一 类(函数模拟) function Person(name,id){ //实例变量...

    Javascript中的几种继承方式对比分析

    这种说法原因一般都是觉得javascript作为一门弱类型语言与类似java或c#之类的强型语言的继承方式有很大的区别,因而默认它就是非主流的面向对象方式,甚至竟有很多书将其描述为’非完全面向对象’语言。其实个人觉得...

    Javascript编程中几种继承方式比较分析

    这种说法原因一般都是觉得javascript作为一门弱类型语言与类似java或c#之类的强型语言的继承方式有很大的区别,因而默认它就是非主流的面向对象方式,甚至竟有很多书将其描述为’非完全面向对象’语言。其实个人觉得...

    Purely-functional-Object-Oriented-System:纯功能的面向对象系统——目前的代码实现了一个无类的、基于委托的 OO 系统,类似于 Self 或 Javascript 的系统。 这是一个成熟的 OO 系统,具有封装、对象标识、继承和多态性。 它也是一个纯粹的功能系统

    站点索引页面声明“除非另有说明,本站点上的所有代码和文档均属于公共领域”纯功能的面向对象系统目前的代码实现了一个无类的、基于委托的 OO 系统,类似于 Self 或 Javascript 的系统。 这是一个成熟的 OO 系统,...

    使用JavaScript构建的面向对象CSS框架-JavaScript开发

    ctr是使用JavaScript构建CSS框架,可提供面向对象的功能,以允许继承CSS组件具有丰富的层次结构,从而更好地促进类似于OOCSSCSS体系结构。 尽管ctr和OOCSS在应用程序上有很大的不同,但是您可以使用允许ct的真实对象...

    javascript基于prototype实现类似OOP继承的方法

    主要介绍了javascript基于prototype实现类似OOP继承的方法,实例分析了JavaScript使用prototype实现面向对象程序设计的中类继承的相关技巧,需要的朋友可以参考下

    聊聊JavaScript如何实现继承及特点

    (ES6有关键字class和extend,继承的语法与Java等面向对象语言类似,但是,ES6 class,只是JavaScript原型继承的语法糖而已) 1. 类式继承 关键点:通过构造函数实现继承。 父类: function Parent(name) { this....

    mayjs:一个javascript面向对象的库

    类和继承带上onExtend()和onInitialize()钩子等等 界面用于文档隐式接口和验证对象 方法重载帮助您清理函数标题行中参数的类型声明 类似关键字的功能简化复杂表达式和重复代码的一系列功能 安装 安装nodejs npm...

    浅析JavaScript原型继承的陷阱

    JavaScript和其它面向对象语言一样,对象类型采用引用方式。持有对象的变量只是一个地址,而基本类型数据是值。当原型上存储对象时,就可能有一些陷阱。 先看第一个例子 代码如下:var create = function() { ...

    Class.Model.js:118行实现的一个简单的Javascript的对象模型

    这个文件中定义了类模型中类似于其他面向对象语言中的Object类。 如何新建类 作为基类,类的定义使用 var NewClass = Class.new(); 来进行定义。 通过以上方式定义的类,可以继承: var BClass = NewClass.extend...

    js 静态动态成员 and 信息的封装和隐藏

    我用同样的概念来概述js的这些方仿面向对象的概念,因为他们的行为作用类似。 在js中有如下函数 代码如下: function test(){ var var_value; this.this_value; } 其中,var_value是静态成员,this_value是动态成员。...

    利用不到200行代码写一款属于你自己的js类库

    本文将使用面向对象的方式,来教大家用原生js写出一个类似jQuery这样的类库。我们将会学到如下知识点: 闭包:减少变量污染,缩短变量查找范围 自执行函数在对象中的运用 extend的实现原理 如何实现跨浏览器的...

    javaScript中的原型解析【推荐】

    js作为一门面向对象的语言,自然也拥有了继承这一概念,但js中没有类的概念,也就没有了类似于java中的extends,所以,我觉得js中的继承主要依赖于js中的原型(链)。 那么,原型是什么呢?我们知道js中函数亦是一种...

    fringejs:基于原型的 JavaScript Web 应用程序框架

    与许多面向对象的编程语言不同,JavaScript 具有原型继承而不是经典继承。 这意味着对象可以直接继承其他对象,而不是子类从超类继承的经典语言,并且对象是类的实例。 许多类似的框架使用伪经典继承模式,它们试图...

    javascript学习笔记.docx

    11) JavaScript中面向对象的特性: a) 实例属性:在构造函数创建或初始化的属性。 b) 实例方法:在构造函数中把原型对象中的一个属性设为函数来实现。 c) 类属性:构造函数本身的属性。 d) 类方法:用合适的函数作为...

    一篇文章让你搞懂JavaScript 原型和原型链

    与多数面向对象的开发语言有所不同,虽然JavaScript没有引入类似类的概念(ES6已经引入了class语法糖),但它仍然能够大量的使用对象,那么如何将所有对象联系起来就成了问题。于是就有了本文中我们要讲到的原型和...

    JavaScript 模拟类机制及私有变量的方法及思路

    在使用一些 Javascript 框架时,或许会看到类似的代码 代码如下: var ...这是一种典型的面向对象的类机制应用,与原生的 Javascript 类机制相比,显得更为清晰和自然。并且,在此基础上,实现类的继承也较为方便。

    Curl语言学习资料

    资料仅供学习,勿作商用! Curl语言是一种编程语言,它被设计用于编写网络程序。它的目标是以一种单一的语言来取代HTML, ...Curl语言便于学习,编程效率高,是一种支持多重继承,范型等数据类型的面向对象编程语言。

    [ASP.NET AJAX]Function对象及Type类的方法介绍

    这个类提供了一些扩展面向对象编程的一些反射方法,通过这个类我们可以注册类似.NET中的一些(如:命名空间,类,枚举等等)基本类型。这个Type类继承自window是一个Global类型,不属于任何命名空间。下面我们来看看...

    swig-templates:一窥JavaScript最佳模板引擎

    面向对象的模板继承。 将过滤器和转换应用到模板中的输出。 自动转义所有输出以安全地呈现HTML。 支持许多迭代和条件。 健壮无肿胀。 可扩展和可定制的。 有关一些示例,请参见 。 良好的。 需要帮忙? 有...

Global site tag (gtag.js) - Google Analytics