JavaScript代码复用模式详解


Posted in Javascript onNovember 07, 2014

代码复用及其原则

代码复用,顾名思义就是对曾经编写过的代码的一部分甚至全部重新加以利用,从而构建新的程序。在谈及代码复用的时候,我们首先可以想到的是继承性。代码复用的原则是:

优先使用对象组合,而不是类继承

在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

JavaScript代码复用模式详解

那么,当使用var kid = new Child()创建新对象时会发生什么?如下图:

JavaScript代码复用模式详解

使用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;
}

JavaScript代码复用模式详解

子对象和父对象共享同一个原型,并且可以同等的访问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>
Javascript 相关文章推荐
javascript定时保存表单数据的代码
Mar 17 Javascript
取得窗口大小 兼容所有浏览器的js代码
Aug 09 Javascript
Js日期选择器并自动加入到输入框中示例代码
Aug 02 Javascript
jQuery链使用指南
Jan 20 Javascript
JavaScript中SetInterval与setTimeout的用法详解
Nov 10 Javascript
微信小程序 wx:key详细介绍
Oct 28 Javascript
详解node中创建服务进程
May 09 Javascript
在bootstrap中实现轮播图实例代码
Jun 11 Javascript
Vue.2.0.5实现Class 与 Style 绑定的实例
Jun 20 Javascript
JS 60秒后重新发送验证码的实例讲解
Jul 26 Javascript
详解vue移动端项目的适配(以mint-ui为例)
Aug 17 Javascript
如何用Node写页面爬虫的工具集
Oct 26 Javascript
JavaScript中的style.cssText使用教程
Nov 06 #Javascript
JavaScript组合拼接字符串的效率对比测试
Nov 06 #Javascript
5个书写JavaScript代码的坏习惯,看看你中枪了没?
Nov 06 #Javascript
javascript解析json实例详解
Nov 05 #Javascript
JavaScript中发布/订阅模式的简单实例
Nov 05 #Javascript
JavaScript不刷新实现浏览器的前进后退功能
Nov 05 #Javascript
Javascript检查图片大小不要让大图片撑破页面
Nov 04 #Javascript
You might like
深入eAccelerator与memcached的区别详解
2013/06/06 PHP
php进程间通讯实例分析
2016/07/11 PHP
如何正确配置Nginx + PHP
2016/07/15 PHP
php微信公众平台配置接口开发程序
2016/09/22 PHP
thinkPHP实现签到功能的方法
2017/03/15 PHP
php精度计算的问题解析
2019/06/21 PHP
JavaScript实现两个Table固定表头根据页面大小自行调整
2014/01/03 Javascript
利用js判断手机是否安装某个app的多种方案
2017/02/13 Javascript
js实现下拉菜单效果
2017/03/01 Javascript
Angular2搜索和重置按钮过场动画
2017/05/24 Javascript
Material(包括Material Icon)在Angular2中的使用详解
2018/02/11 Javascript
vue-router传参用法详解
2019/01/19 Javascript
VUE简单的定时器实时刷新的实现方法
2019/01/20 Javascript
Python中针对函数处理的特殊方法
2014/03/06 Python
Python实现配置文件备份的方法
2015/07/30 Python
Python批量提取PDF文件中文本的脚本
2018/03/14 Python
Python3中lambda表达式与函数式编程讲解
2019/01/14 Python
详解Python 字符串相似性的几种度量方法
2019/08/29 Python
python中的split()函数和os.path.split()函数使用详解
2019/12/21 Python
Kipling凯浦林美国官网:世界著名时尚休闲包袋品牌
2016/08/24 全球购物
美国唇部护理专家:Sara Happ
2019/06/19 全球购物
世界排名第一的运动鞋市场:Flight Club
2020/01/03 全球购物
单位办理社保介绍信
2014/01/10 职场文书
优秀学生干部推荐材料
2014/02/03 职场文书
环境建设实施方案
2014/03/14 职场文书
新年联欢会主持词
2014/03/27 职场文书
数控机床专业自荐信
2014/05/19 职场文书
党的群众路线教育实践活动教师自我剖析材料
2014/10/09 职场文书
幼儿园见习报告范文
2014/10/30 职场文书
订货会邀请函
2015/01/31 职场文书
争先创优个人总结
2015/03/04 职场文书
政审证明材料
2015/06/19 职场文书
2016党校学习心得体会
2016/01/07 职场文书
党员观看《筑梦中国》心得体会
2016/01/18 职场文书
2016中秋晚会开幕词
2016/03/03 职场文书
python实现简单的名片管理系统
2021/04/26 Python