JavaScript代码复用模式
2015-09-22 15:48
423 查看
转自:http://segmentfault.com/a/1190000000762220
在js中,由于没有类的概念,因此实例的概念也就没多大意义,js中的对象是简单的键-值对,可以动态的创建和修改它们。
但在
例如:
传统的继承模式是需要
当使用
那么,当使用
使用
当执行
执行到这里的时候并没有完,在
更详细的讨论请查看我这篇文章:JavaScript学习总结(五)原型和原型链详解
子对象和父对象共享同一个原型,并且可以同等的访问
在原型模式中,并不需要使用对象字面量来创建父对象。如下代码所示,可以使用构造函数来创建父对象,这样做的话,自身的属性和构造函数的原型的属性都将被继承。
本模式中,可以选择仅继承现有构造函数的原型对象。对象继承自对象,而不论父对象是如何创建的,如下实例:
首先,在
这是
代码复用及其原则
代码复用,顾名思义就是对曾经编写过的代码的一部分甚至全部重新加以利用,从而构建新的程序。在谈及代码复用的时候,我们首先可以想到的是
继承性。代码复用的原则是:
优先使用对象组合,而不是类继承
在js中,由于没有类的概念,因此实例的概念也就没多大意义,js中的对象是简单的键-值对,可以动态的创建和修改它们。
但在
js中,我们可以使用构造函数和
new操作符来实例化一个对象,这与其他使用类的编程语言在语法上有其相似之处。
例如:
var trigkit4 = new Person();
js在调用构造函数
Person时似乎看起来是一个类,但其实际上仍然是一个函数,这让我们产生了一些假定在类的基础上的开发思路和继承模式,我们可以称之为“类式继承模式”。
传统的继承模式是需要
class关键字的,我们假定以上的类式继承模式为
现代继承模式,这是一种不需要以类的方式考虑的模式。
类式继承模式
看下面两个构造函数Parent()和
Child()的例子:
<script type="text/javascript"> function Parent(name){ this.name = name || 'Allen'; } Parent.prototype.say = function(){ return this.name; } function Child(name){} //用Parent构造函数创建一个对象,并将该对象赋值给Child原型以实现继承 function inherit(C,P){ C.prototype = new P();//原型属性应该指向一个对象,而不是函数 } //调用声明的继承函数 inherit(Child,Parent); </script>
当使用
new Child()语句创建一个对象时,它会通过原型从
Parent()实例获取它的功能,比如:
var kid = new Child(); kid.say();//Allen
原型链
讨论一下类式继承模式下原型链的工作原理,我们将对象看做是内存中某处的块,该内存块包含数据以及指向其他块的引用。当用new Parent()语句创建一个对象时,就会创建如下图左边的这样一个块,这个块保存了
name属性,如果想访问
say()方法,我们可以通过指向构造函数
Parent()的
prototype(原型)属性的隐式链接
__proto__,便可访问右边区块
Parent.prototype。
那么,当使用
var kid = new Child()创建新对象时会发生什么?如下图:
使用
new Child()语句所创建的对象除了隐式链接
__proto__外,它几乎是空的。这种情况下,
__proto__指向了在
inherit()函数中使用
new Parent()语句所创建的对象
当执行
kid.say()时,由于最左下角的区块对象并没有
say()方法,因此他将通过原型链查询中间的区块对象,然而,中间的区块对象也没有
say()方法,因此他又顺着原型链查询到最右边的区块对象,而该对象正好有
say()方法。完了吗?
执行到这里的时候并没有完,在
say()方法中引用了
this.name,this指向构造函数所创建的对象,在这里,它指向了
new Child()这个区块,然而,
new Child()中并没有
name属性,为此,将查询中间区块,而中间区块正好有
name属性,至此,原型链的查询完毕。
更详细的讨论请查看我这篇文章:JavaScript学习总结(五)原型和原型链详解
共享原型
本模式的法则在于:可复用的成员应该转移到原型中而不是放置在this中。因此,处于继承的目的,任何值得继承的东西都应该放在原型中实现。所以,可以将子对象的原型与父对象的原型设置为相同即可,如下示例所示:function inherit(C,P){ C.prototype = P.prototype; }
子对象和父对象共享同一个原型,并且可以同等的访问
say()方法。然而,子对象并没有继承
name属性
原型继承
原型继承是一种“现代”无类继承模式。看如下实例:<script type="text/javascript"> //要继承的对象 var parent = { name : "Jack" //这里不能有分号哦 }; //新对象 var child = Object(parent); alert(child.name);//Jack </script>
在原型模式中,并不需要使用对象字面量来创建父对象。如下代码所示,可以使用构造函数来创建父对象,这样做的话,自身的属性和构造函数的原型的属性都将被继承。
<script type="text/javascript"> //父构造函数 function Person(){ this.name = "trigkit4"; } //添加到原型的属性 Person.prototype.getName = function(){ return this.name; }; //创建一个新的Person类对象 var obj = new Person(); //继承 var kid = Object(obj); alert(kid.getName());//trigkit4 </script>
本模式中,可以选择仅继承现有构造函数的原型对象。对象继承自对象,而不论父对象是如何创建的,如下实例:
<script type="text/javascript"> //父构造函数 function Person(){ this.name = "trigkit4"; } //添加到原型的属性 Person.prototype.getName = function(){ return this.name; }; //创建一个新的Person类对象 var obj = new Person(); //继承 var kid = Object(Person.prototype); console.log(typeof kid.getName);//function,因为它在原型中 console.log(typeof kid.name);//undefined,因为只有该原型是继承的 </script>
继承一个对象的功能
使用构造函数链的概念和Function.apply()方法,来模拟js中传统的类继承行为:<script> function oldObject(param1){ this.param1 =param1; this.getParam = function () { return this.param1; } } function newObject(param1,param2){ this.param2 =param2; this.getParam2 = function () { return this.param2; }; oldObject.apply(this,arguments); this.getAllParams = function () { return this.getParam() + "" + this.getParam2(); } } window.onload = function () { newObject.prototype = new oldObject(); var obj = new newObject("value1","value2"); //打印出两个参数 alert(obj.getAllParams()); }; </script>
首先,在
newObject的构造函数中,在
oldObject上调用一个
apply方法,传入对新的对象的引用和参数数组。
apply方法继承自
Function对象
newObject.prototype = new oldObject();
这是
js中构造函数链的一个示例。当创建一个
newObject的新实例的时候,
newObject以这样一种方式继承了旧对象的方法和属性。
相关文章推荐
- JS实现3D图片旋转展示效果代码
- js:有关TypeError: invalid 'in' operand obj的错误
- EXTJS-panel对象的创建
- JSON.parse()和JSON.stringify()
- js 地图坐标转换
- javascript组件化
- JavaScript继承方式详解
- CVS && HTML && XML && JSON
- 9月29日An Introduction to MeteorJS
- DWR3 搭建(转载)
- JavaScript脚本判断蜘蛛来源的方法
- JSP学习经验小结分享
- JSP起源、JSP的运行原理、JSP的执行过程
- ExtJS 等待两个/多个store加载完再执行操作的方法
- JSP中文乱码常见3个例子及其解决方法
- js 限制只能输入数字和一个小数,且第一位不能为小数
- JavaScript 经典实例收集整理
- JavaScript作用域和执行环境
- 判断非法字符串的类方法,与jsp
- JS的数组操作函数