`
lp895876294
  • 浏览: 285426 次
  • 性别: 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))();

 

分享到:
评论

相关推荐

    Javascript面向对象编程.

    在JavaScript中,面向对象主要通过以下三种方式实现: 1. **构造函数(Constructor)**:构造函数是一种特殊的函数,用于创建和初始化对象。我们可以通过`new`关键字来调用构造函数,创建一个新的对象实例。例如: ...

    Javascript 面向对象的JavaScript进阶

    在探讨面向对象的JavaScript之前,我们首先需要了解面向对象编程(Object-Oriented Programming, OOP)的基本特性:封装性、抽象性、继承性和多态性。 ##### 8.1.1 封装性 **定义:** 封装性是面向对象编程的一个...

    JavaScript 面向对象编程详细讲解文档

    JavaScript的核心在于对象、原型和隐式继承,这些都是理解其面向对象特性的重要概念。 首先,让我们深入理解对象。在JavaScript中,一切皆为对象,包括函数。你可以直接通过对象字面量或者构造函数来创建对象。对象...

    JS面向对象汇总PDF

    **JS面向对象汇总PDF**是针对JavaScript编程语言中面向对象编程概念的一个综合性的学习资料,主要探讨了JavaScript如何实现面向对象编程(OOP)的设计原则和模式。在JavaScript中,面向对象编程是一种重要的编程范式...

    JS实现面向对象继承的5种方式分析

    本文将详细介绍五种JS实现面向对象继承的方法。 1. **对象冒充实现继承** 这种方式允许实现多继承。其原理是将父类的构造函数作为子类的一个方法,并在子类的构造函数中调用这个方法,通过`this`关键字为子类的...

    老生常谈javascript的面向对象思想

    以上知识点详细介绍了JavaScript面向对象编程中的基本特性、对象的定义方式以及如何通过不同方式实现封装、继承和多态。通过深入理解这些概念,可以帮助开发者更加高效和规范地进行JavaScript编程,编写出更加优雅...

    基于JavaScript的面向对象程序设计研究.pdf

    研究发现,JavaScript语言具有良好的面向对象特性,特别是在封装性、继承性和多态性等方面。本文对JavaScript的面向对象语言特性进行了详细分析,并给出了具体的分析实例。 封装是面向对象的首要特征。 JavaScript...

    JavaScript面向对象基础.ppt

    面向对象编程的基础包括类、对象、继承和多态等概念。类是对象的模板或蓝图,定义了一组属性(数据成员)和方法(函数)。对象则是类的实例,具备类所定义的属性和行为。JavaScript虽然没有传统的类定义,但可以通过...

    JavaScript的面向对象

    这篇博文将深入探讨JavaScript中的面向对象特性,包括类的概念、对象的创建、继承机制以及封装。 首先,JavaScript的类并非像Java或C++那样是真正的类,而是语法糖,它提供了更接近于传统类的语法结构,但底层仍然...

    javascript面向对象教程

    尽管它的名称中没有“对象”这个词,但JavaScript确实支持面向对象的编程范式。本文将深入探讨JavaScript的面向对象特性,帮助读者理解这个语言鲜为人知的一面。 首先,我们要明白JavaScript中的对象和类型系统。...

    JavaScript 面向对象程序设计

    通过构造函数和原型,JavaScript实现了类和对象的继承,以及动态属性的添加,从而支持了面向对象编程的关键特性。 总结来说,JavaScript的面向对象编程主要包括以下几个方面: 1. **通过函数定义类**:函数作为...

    JavaScript面向对象的编程

    7. **类(Class)语法**:虽然JavaScript原生支持基于原型的继承,但在ES6中引入了类语法,这使得JavaScript的面向对象编程更接近传统的类式继承模型。然而,即使有了类,JavaScript的实质仍然是基于原型的。 8. **...

    猜拳游戏:java面向对象,kotlin面向对象,js面向对象,3个方法开发.zip

    《猜拳游戏:Java、Kotlin与JavaScript的面向对象实现》 在计算机科学领域,面向对象编程(Object-Oriented Programming, OOP)是一种广泛采用的编程范式,它通过模拟现实世界中的对象来构建软件系统。本项目“猜拳...

    JavaScript中的面向对象.pdf

    JavaScript,作为一种广泛使用的脚本语言,常常被误解为非面向对象的语言,但实际上,JavaScript完全支持面向对象编程(OOP)的三大核心原则:封装、继承和多态。尽管它的实现方式与传统的面向对象语言(如Java或C++...

    js面向对象知识

    在JavaScript中,面向对象编程(Object-Oriented Programming, OOP)是其核心概念之一,帮助开发者创建复杂、可复用的代码结构。在黑马2013赵栋的JS视频教程中,他深入讲解了这一主题,包括自己编写的源码示例。 1....

    面向对象Javascript核心支持代码分享

    为了深入理解这一概念,我们首先要探讨面向对象编程(OOP)的基本原理及其在JavaScript中的实现方式,然后将通过分析提供的代码片段,揭示这些核心代码如何模拟OOP特性。 面向对象编程是一种编程范式,它依赖于对象...

    js对象,五种继承 详细讲解

    JavaScript是一种广泛用于网页和网络应用的脚本语言,它具有灵活的数据类型和强大的面向对象特性。在JavaScript中,对象的定义和继承是核心概念。本文将深入探讨JavaScript的五种对象定义方法以及五种继承方式。 1....

Global site tag (gtag.js) - Google Analytics