重温Javascript继承机制(3)
作者:瓜瓜 发布时间:2011-07-04 12:17:23
三、构造函数如何实现继承
现在有一个”MED”对象的构造函数(MED:Marketing Experience Design,营销体验设计)
function MED(){
this.aim = "营销体验设计";
}
依然是”WD”对象的构造函数,
function WD(skill,sex){
this.skill = skill;
this.sex = sex;
}
怎样才能使”WD”继承”MED”呢?
1. apply绑定构造函数实现
最简单的方法,大概就是使用call或apply方法,将父对象的构造函数绑定在子对象上,也就是在子对象构造函数中加一行:
function WD(skill,sex){
MED.apply(this, arguments);
this.skill = skill;
this.sex = sex;
}
var WD1 = new WD("Html","男");
console.log(WD1.aim); // "营销体验设计"
2. prototype模式实现
我们通常的做法是使用prototype属性。如果”WD”的prototype对象,指向一个MED的实例,那么所有”WD”的实例,就能继承MED了。
WD.prototype = new MED();//我们将WD的prototype对象指向一个MED的实例。
WD.prototype.constructor = WD;
var WD1 = new WD("Html","男");
console.log(WD1.aim); // 营销体验设计
这句
WD.prototype = new MED();
相当于完全删除了prototype 对象原先的值,然后赋予一个新值。那么第二行又是什么意思呢?
WD.prototype.constructor = WD;
原来,任何一个prototype对象都有一个constructor属性,指向它的构造函数。也就是说,WD.prototype 这个对象的constructor属性,是指向WD的。
我们在前一步已经删除了这个prototype对象原来的值,所以新的prototype对象没有constructor属性,需要我们手动加上去,否则后面的”继承链”会出问题。这就是第二行的意思。
注意,这是很重要的一点,编程时务必要遵守,下文都遵循这一点,即如果替换了prototype对象,
o.prototype = {};
那么,下一步必然是为新的prototype对象加上constructor属性,并将这个属性指回原来的构造函数。
o.prototype.constructor = o;
3. 从prototype直接继承实现
由于MED对象中,不变的属性都可以直接写入MED.prototype。所以,我们也可以让WD()跳过 MED(),直接继承MED.prototype。
现在,我们先将MED对象改写:
function MED(){ }
MED.prototype.skill = "MED";
然后,将WD的prototype对象指向MED的prototype对象,这样就完成了继承。
WD.prototype = MED.prototype;
WD.prototype.constructor = WD;
var WD1 = new WD("Html","男");
console.log(WD1.skill); // MED
与前一种方法相比,这样做的优点是效率比较高(不用执行和建立MED的实例了),比较省内存。缺点是 WD.prototype和MED.prototype现在指向了同一个对象,那么任何对WD.prototype的修改,都会反映到MED.prototype。
所以,上面这一段代码其实是有问题的。请看第二行
WD.prototype.constructor = WD;
这一句实际上把MED.prototype对象的constructor属性也改掉了!
console.log(MED.prototype.constructor); // WD
4. 利用一个空对象作为中介来实现
由于”直接继承prototype”存在上述的缺点,所以可以利用一个空对象作为中介。
var F = function(){};
F.prototype = MED.prototype;
WD.prototype = new F();
WD.prototype.constructor = WD;
F是空对象,所以几乎不占内存。这时,修改WD的prototype对象,就不会影响到MED的prototype对象。
console.log(MED.prototype.constructor); // MED
5.利用 prototype模式的封装函数
我们将上面的方法,封装成一个函数,便于使用。
function extend(Child, Parent) {
var F = function(){};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
}
使用的时候,方法如下
extend(WD,MED);
var WD1 = new WD("Html","男");
console.log(WD1.aim); // 营销体验设计
这个extend函数就是YUI库如何实现继承的方法。
6. 拷贝继承实现
上面是采用prototype方式来实现继承。其实既然子对象会拥有父对象的属性和方法,我们直接采用”拷贝”方法也可以达到效果。简单说,如果把父对象的所有属性和方法,拷贝进子对象,不也能够实现继承吗?
首先,还是把MED的所有不变属性,都放到它的prototype对象上。
function MED(){}
MED.prototype.aim = "营销体验设计";
然后,再写一个函数,实现属性拷贝的目的。
function extendCopy(Child, Parent) {
var p = Parent.prototype;
var c = Child.prototype;
for (var i in p) {
c[i] = p[i];
}
}
这个函数的作用,就是将父对象的prototype对象中的属性,一一拷贝给Child对象的prototype对象。
使用的时候,这样写:
extendCopy(WD, MED);
var WD1 = new WD("Html","男");
console.log(WD1.aim); // 营销体验设计


猜你喜欢
- 本文讲述了Java数据类型与MySql数据类型对照表。分享给大家供大家参考,具体如下:类型名称显示长度数据库类型JAVA类型JDBC类型索引
- python的字符串编码识别模块(第三方库):官方地址: http://pypi.python.org/pypi/chardetimport
- 本文实例总结了PHP常用字符串操作函数。分享给大家供大家参考,具体如下:/*常用的字符串输出函数** echo() 输出字符串* print
- 自动签到的python脚本源码新建一个python文件,checkin.py,保存到电脑上某个位置,我这里保存到的是E:\pyproject
- asp使用fso读取驱动器信息:<%vv=drive()response.write vv funct
- python版本:3.8class object: """ The most base type "
- myhash.go/** * Created with IntelliJ IDEA. * User: liaojie * Date: 12-
- 本篇介绍Python中的引用。首先想一想如图示例。在python中,值是靠引用来传递来的。用id()来判断两个变量是否为同一个值的引用。如图
- 这篇文章是入门级别的应用Python + Selenium进行自动化测试,包括环境搭建及简单的实例。基本思想是用Firefox Seleni
- php 如何获取请求的xml数据,对方通过http协议post提交过来xml数据,php如何获取到这些数据呢?<?php $xml_d
- 简单替代密码简单替换密码是最常用的密码,包括为每个密文文本字符替换每个纯文本字符的算法.在这个过程中,与凯撒密码算法相比,字母表是混乱的.示
- 字典对象的核心是散列表。散列表是一个稀疏数组(总是有空白元素的数组),数组的每个单元叫做 bucket。每个 bucket 有两部分:一个是
- example:models中的表# modelsclass UserInfo(models.Model): id = mode
- think-queue是ThinkPHP官方提供的一个消息队列服务,是专门支持队列服务的扩展包。think-queue消息队列适用于大并发或
- 一、tooltip(提示框) 源码文件: Tooltip.jsTooltip.scss实现原理: 1、获取当前
- 本文整理了一部分我们平时在项目中经常遇到的关于go语言JSON数据与结构体之间相互转换的问题及解决办法。基本的序列化首先我们来看一下Go语言
- 一、安装pip install xlwt二、创建表格并写入import xlwt# 创建一个workbook并设置编码workbook =
- 1.InnoDB的锁定机制InnoDB存储引擎支持行级锁,支持事务处理,事务是有一组SQL语句组成的逻辑处理单元,他的ACID特性如下:原子
- 实例如下:import urllib.requestimport urllib.parseimport jsonwhile True: &n
- 之前mysql用着好着,可是今天在启动mysql后输入密码出现了闪退,在任务管理器中发现mysql服务没有启动,当手动启动时提示拒绝访问。在