`

JS Class construct and extend

阅读更多
最近有点迷上javascript, 潜下心来, 仔细理了下JS的对象构造

关于对象构造, 大致有以下几种pattern

1. factory
工厂模式, 很传统的啦, 主要就是在构造函数里临时创建一个Object, 然后把所有资源都赋予这个实例, 最后返回这个实例的引用, 创建对象时不需要new, 工厂模式嘛,
缺点是, 因为最后的引用不是原来的Class, 所以Class的prototype完全废了

2. constructor
构造模式, 很Java的风格, 构造器里, 把所有资源赋给this, 然后返回这个this的引用
缺点是, 里面的方法也随着数据一样, 每new一个实例, 就重复一份
比较纠结的是, 一定要用new, 不然的话, 里面的this指针不定指哪去了,
一般指向最外层的window对象
另外, js构造器的特色, 在构造函数结束时, 会隐式执行代码
return this;

3. factory/constructor mix
在constructor的基础上, 把里面的方法放到外面, 利用prototype属性, 让每个实例都能访问,
注意不是静态函数那种, 想想如果是静态函数, 就没办法直接访问实例里的数据了


关于继承, 没想到啊, 我居然会琢磨起JS的继承来了, 想当年, 信誓旦旦地认为自己不会用JS的对象继承, 以免搞得太复杂了...

JS里确实没有继承的语法, 所以, 我们必须人为地虚拟它
主要的继承手段有
1, 通过指针欺骗
里子类里, 如父类为ClassA
this.parent=Class;  //指针指向父类构造函数
this.parent();      //执行父类构造函数, 这里, 父类的构造器里的this会指向子类, 所有资源的引用就都被骗到子类里了, 嘿嘿
delete this.parent; //销毁痕迹, 自欺欺人...

想不到, javascript看见大家都这样做之后, 居然也凑上一脚, 特别提供了2个函数方便大家作案
call(this, param1, param2, param3, ...)
apply(this, Array)
2个函数其实一样, 就是后面的参数不同而已, apply里用Array把第2个以后的参数全部打包到数组里了, 有这2个函数, 就可以取代上面的那3行代码了, 作案手法更专业了...
但可能父类的prototype里的方法都丢失了

2, 通过原型
原型链是JS里很值得钻研的东西, 这里只说有关继承的,
上面的方法, 虽然把构造器里的所有资源骗到手, 但prototype里的方法却损失了,
所以有了这个补充
父类A, 子类B
B.prototype=A.prototype  //这样写很好理解, 指针对上指针了
or
B.prototype=new A();  //为什么new个实例也可以, 因为返回的是this, prototype的方法就是直接由实例调用的, 而不是静态类调用

B.prototype=A; //这是错误的, 这样指针指向父类的构造函数了
这样, 父类的方法也就入手了

注意子类的方法要在这个prototype"继承"之后再写


以下是测试代码

<html>
  <head>
    <title></title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<style type="text/css">
		form input[type="button"] {width: 150px}
	</style>
	<script type="text/javascript">
	//declare Class in JavaScript
	
	/*
	 * factory pattern<br />
	 * point1, the duplication when new Car() every time<br />
	 * point2, new Car() and Car(), it's same result<br />
	 * point3, prototype is for Car, but the finger have been change in constructor,<br />
	 * so the method of prototype are be lost<br />
	 */
	function demoFactory(){
		//function Car, the same indicate, the comment isn't support by NetBean 6.8
		//var Car=function(color, brand, engineLv){}, recommandation, for comment view

		/**
		 * function description
		 * @param color
		 * @param brand
		 * @param enginelv
		 * @return 
		 */
		var Car=function(color, brand, engineLv){
			var e=new Object;
			e.color=color;
			e.brand=brand;
			e.engineLv=engineLv;
			e.getDetail=function(){alert(e.color+", "+e.brand+", "+e.engineLv);};	//*1
			return e;
		};
		Car.show=function(){alert("zoo zoo")};		//it's ok
		Car.prototype.show2=function(){alert("Car prototype")};	//it's wrong *3
		var car1=new Car('black', 'Mazda5', '2.0L');	//*2
		var car2=Car('black', 'Mazda5', '2.0L');
		try{
			car1.getDetail();
			car2.getDetail();
			Car.show();
			car2.show2();
		}catch(err){
			alert(err);
		}
	}

	/**
	 * constructor/prototype mix parttern, <u>recommendation in <b>ECMSscript</b></u><br />
	 * point1, the "this" must be, else the color are belong "window", it mean window.color<br />
	 * point2, same as point1, but the question of duplication still be<br />
	 * point3, the error that method of prototype is solved<br />
	 */
	function demoConstructor(){
		var Car=function(color, brand, engineLv){
			this.color=color;		//*1
			this.brand=brand;
			this.engineLv=engineLv;
			this.getDetail=function(){alert(this.color+", "+this.brand+", "+this.engineLv);};	//*2
		};
		Car.prototype.show2=function(){alert("Car prototype")};	//it's ok, *3
		Car.show=function(){alert("zoo zoo")};		//it's ok
		var car1=new Car('black', 'Mazda5', '2.0L');
		var car2=new Car('silver', 'Mazda5', '2.0L');
		try{
			car1.getDetail();
			car2.getDetail();
			Car.show();
			car2.show2();
		}catch(err){
			alert(err);
		}
	}


	/**
	 * constructor parttern<br />
	 * point1, the "this" must be, else the color are belong "window", it mean window.color<br />
	 * point2, declare the method to prototype method, the duplication question are solved<br />
	 * point3, the error that method of prototype is solved<br />
	 */
	function demoMix(){
		var Car=function(color, brand, engineLv){
			this.color=color;		//*1
			this.brand=brand;
			this.engineLv=engineLv;
		};
		Car.prototype.getDetail=function(){alert(this.color+", "+this.brand+", "+this.engineLv);};	//*2
		Car.show=function(){alert("zoo zoo")};		//it's ok
		Car.prototype.show2=function(){alert("Car prototype")};	//it's ok, *3
		var car1=new Car('black', 'Mazda5', '2.0L');
		var car2=new Car('silver', 'Mazda5', '2.0L');
		car1.getDetail();
		car2.getDetail();
		try{
			Car.show();
			car2.show2();
		}catch(err){
			alert(err);
		}
	}

	/**
	 * Extend demo: Object virtual<br />
	 * the expend is not support in JavaScript<br />
	 * so we must perform it throught by coding, and virtual the extend effect<br />
	 * point1, the prototype finger to CarGas, not Car, so the prototype method error
	 */
	function demoExtend1(){
		var Car=function(color, brand, engineLv){
			this.color=color;		//*1
			this.brand=brand;
			this.engineLv=engineLv;
			this.getDetail=function(){alert(this.color+", "+this.brand+", "+this.engineLv);};	//*2
		};
		Car.show=function(){alert("zoo zoo")};		//it's ok
		Car.prototype.show2=function(){alert("Car prototype")};	//it's ok, *3

		var CarGas=function(color, brand, engineLv, gasNo){
			this.gasNo=gasNo;
			this.extend=Car;
			this.extend(color, brand, engineLv);
			delete this.extend;		//it's no mind, either it delete or not delete
		}
		var car=new CarGas("back", "Mazda5", "2.0L", "97");
		try {
			alert(car.gasNo);
			car.getDetail();
			Car.show();
			car.show2();	//*1
		} catch (err) {
			alert(err);
		}
	}

	/**
	 * Extend Demo: Object virtual with method <b>call()</b> and <b>apply()</b><br />
	 * method <b>call</b> and <b>apply</b> is same except parameter<br />
	 * call's parameter: 1, "this", 2, param, 3, param, 4, param, ...<br />
	 * apply's parameter: 1, "this", 2, Array
	 */
	function demoExtend2(){
		var Car=function(color, brand, engineLv){
			this.color=color;		//*1
			this.brand=brand;
			this.engineLv=engineLv;
			this.getDetail=function(){alert(this.color+", "+this.brand+", "+this.engineLv);};	//*2
		};
		Car.show=function(){alert("zoo zoo")};		//it's ok
		Car.prototype.show2=function(){alert("Car prototype")};	//it's ok, *3

		var CarGas=function(color, brand, engineLv, gasNo){
			this.gasNo=gasNo;
			/*
			this.extend=Car;
			this.extend(color, brand, engineLv, gasNo);
			delete this.extend;
			*/
		   
		   //Car.call(this, color, brand, engineLv);
		   Car.apply(this, [color, brand, engineLv]);
		}
		var car=new CarGas("back", "Mazda5", "2.0L", "97");
		try {
			alert(car.gasNo);
			car.getDetail();
			Car.show();
			car.show2();	//*1
		} catch (err) {
			alert(err);
		}
	}

	/**
	 * Extend Demo: prototype mix<br />
	 * point1, CarGas prototype must be point to Car's <b>new Instance</b> or <b>Car.prototype</b><br />
	 * point2, this over Car's prototype method
	 */
	function demoExtend3(){
		var Car=function(color, brand, engineLv){
			this.color=color;		//*1
			this.brand=brand;
			this.engineLv=engineLv;
			this.getDetail=function(){alert(this.color+", "+this.brand+", "+this.engineLv);};	//*2
		};
		Car.show=function(){alert("zoo zoo")};		//it's ok
		Car.prototype.show2=function(){alert("Car prototype")};	//it's ok

		var CarGas=function(color, brand, engineLv, gasNo){
			this.gasNo=gasNo;
			Car.apply(this, [color, brand, engineLv]);
		}
		//CarGas.prototype=new Car();	//*1
		CarGas.prototype=Car.prototype;

		//CarGas.prototype.show2=function(){alert("CarGas prototype")};	//*2
		CarGas.prototype.show3=function(){alert("CarGas prototype")};

		var car=new CarGas("back", "Mazda5", "2.0L", "97");
		try {
			alert(car.gasNo);
			car.getDetail();
			Car.show();
			car.show2();
			car.show3();
		} catch (err) {
			alert(err);
		}
	}
	</script>
  </head>
  <body>
	  <form action="" >
		  <input type="button" value="FACTORY DEMO" onclick="demoFactory()" /><br />
		  <input type="button" value="CONSTRUCTOR DEMO" onclick="demoConstructor()" /><br />
		  <input type="button" value="CONSTR/PROTO MIX DEMO" onclick="demoMix()" /><br />
		  <br />
		  <hr size="1" />
		  <input type="button" value="EXTEND DEMO1" onclick="demoExtend1()" /><br />
		  <input type="button" value="EXTEND DEMO2" onclick="demoExtend2()" /><br />
		  <input type="button" value="EXTEND DEMO3" onclick="demoExtend3()" /><br />
	  </form>
  </body>
</html>

分享到:
评论

相关推荐

    Construct Binary Tree from Preorder and Inorder Traversal

    Construct Binary Tree from Preorder and Inorder Traversal 根据先序,中序建立二叉树

    Beginning JavaScript with DOM Scripting and Ajax: Second Editon

    Construct good JavaScript syntax following modern coding practices Use JavaScript to communicate with the server and retrieve data Dynamically manipulate markup, validate forms and deal with images ...

    Beginning JavaScript with DOM Scripting and Ajax (pdf + ePub)

    Construct good JavaScript syntax following modern coding practices Use JavaScript to communicate with the server and retrieve data Dynamically manipulate markup, validate forms and deal with images ...

    constructjs是一个用于创建字节级别数据结构的库

    在"construct-js-master"这个压缩包中,包含了constructjs库的源代码,开发者可以通过阅读源码来深入了解其内部实现和优化技巧。此外,示例代码和文档可以帮助初学者快速上手,掌握这个库的使用方法。 总的来说,...

    Construct 2 Repository v2 0.2

    《Construct 2 插件开发详解与RexRepo_v3工具使用指南》 在游戏开发领域,Construct 2是一款广受欢迎的2D游戏制作软件,它允许非程序员通过直观的界面构建复杂的游戏逻辑,极大地降低了游戏开发的门槛。其中,插件...

    Construct合成大西瓜H5游戏项目JavaScript源码Watermelon

    Construct合成大西瓜H5游戏项目源码 游戏简介: 游戏将两个相同的水果组合到游戏中的玻璃容器中,每个水果组合都会根据水果组合获得分数。水果越大,获得的分数就越高。 玩法: 按住游戏屏幕引导水果掉落,尝试瞄准...

    construct-2.8.17.tar.gz

    《构建工具Construct 2.8.17详解》 在软件开发过程中,构建工具起着至关重要的作用,它们能够自动化地完成源代码编译、打包、测试等繁琐工作,极大地提高了开发效率。本文将深入探讨名为"Construct"的构建工具,...

    construct2 三消示例

    一个H5游戏开发引擎Construct 2 的三消游戏工程文件 Demo, 注意,只能用construct 2 打开

    construct2新手简单制作

    Construct 2是一款无编程基础也能上手的游戏开发软件,它通过可视化界面和事件系统,使得游戏设计变得更为直观和简单。 “第一章”标签表明这是一个系列教程的第一部分,通常会涵盖基础概念和基本操作,包括软件...

    Construct游戏开发之小人成长.rar

    在游戏开发领域,Construct是一个非常受欢迎的2D游戏制作工具,尤其适合初学者和非编程背景的创作者。它提供了一个直观的图形用户界面,通过拖放事件块来创建游戏逻辑,降低了游戏开发的门槛。"Construct游戏开发之...

    construct2_html5游戏开发工具

    Construct2正是利用了这一优势,为开发者提供了一个无需编写复杂代码即可创建游戏的环境。它的拖放式界面和直观的事件系统,使得游戏逻辑的构建变得如同拼图一般简单。 Construct2的免费试用版本包含了大部分功能,...

    Construct2源码-笔记

    ### Construct2源码-笔记 #### 一、概述 Construct2是一款流行的2D游戏开发工具,它使用HTML5技术栈构建...此外,这种对细节的关注也为我们提供了一个优秀的学习案例,展示了如何编写高效、可维护的JavaScript代码。

    pax-construct

    **Pax Construct:构建OSGi项目的利器** 在Java开发领域,OSGi(Open Service Gateway Initiative)框架因其模块化、动态性以及对复杂系统的管理能力而备受推崇。它允许开发者将应用拆分成独立的模块,每个模块称为...

    Construct Binary Tree from Inorder and Postorder Traversa

    Construct Binary Tree from Inorder and Postorder Traversa.根据先序后续构建二叉树

    Python-Construct是一款声明式的二进制数据解析器和构建器

    Python-Construct是一个强大的工具,它在处理二进制数据时提供了高级抽象,使得解析和构建复杂的二进制数据流变得更加简单。与标准Python模块`struct`相比,Construct提供了声明式语法,允许开发者以更直观的方式...

    HTML5游戏引擎Construct2源码阅读

    源码中还涉及到了JavaScript语言的一些特性。例如,为了兼容不同浏览器,代码使用了`Object.getPrototypeOf`方法来获取对象的原型链,这在ECMAScript 5中被引入。如果浏览器不支持这个方法,代码会检查`__proto__`...

    construct2中文版HTML5游戏开发工具

    4. **construct2-r204-2-setup.exe**:这是Construct 2的安装程序,版本号为r204,用户可以通过它安装软件开始游戏创作之旅。 学习和掌握Construct 2将开启一个全新的游戏开发世界,无论是为了娱乐还是商业目的,都...

    Python库 | construct-2.8.3.tar.gz

    资源分类:Python库 所属语言:Python 资源全名:construct-2.8.3.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059

Global site tag (gtag.js) - Google Analytics