javascript对象继承详解
问题
比如我们有一个“动物”对象的构造函数。
function animal() {
this.type = '动物';
}
还有一个“猫”对象的构造函数。
function cat(name,color) {
this.name = name;
this.color = color;
}
我们知道猫也属于动物,如果这个猫对象想要继承动物对象的属性,我们该怎么做呢?
构造函数绑定
使用构造函数绑定是最简单的方法,使用call或者apply将父对象绑定在自对象上就可以了。
function cat(name,color) {
animal.apply(this,arguments);
this.name = name;
this.color = color;
}
var cat1 = new cat("haha", 'red');
console.log(cat1.type); //动物
不过这种方法比较少见。
拷贝继承
如果把父对象的所有属性和方法,拷贝进子对象,也可以实现继承。
function extend(Child, Parent) {
var p = Parent.prototype;
var c = Child.prototype;
for (var i in p) {
c[i] = p[i];
}
c.uber = p; //桥梁作用
}
使用方法:
extend(cat, animal);
var cat1 = new cat("haha","red");
alert(cat1.type); // 动物
原型继承(prototype)
相比于上面的直接绑定,原型继承的方法比较常见,对于prototype,我自己简单总结了一下。
每个函数都有一个prototype属性,这个属性是指向一个对象的引用,当使用new关键字创建新实例的时候,这个实例对象会从原型对象上继承属性和方法。
也就是说,如果将“猫”构造函数的prototype属性指向一个“动物”实例,那么再创建“猫”对象实例的时候,就继承了“动物”对象的属性和方法了。
继承实例
cat.prototype = new animal();
cat.prototype.constructor = cat;
var cat1 = new cat("haha","red");
console.log(cat1.constructor == cat); //true
console.log(cat1.type); // 动物
代码第一行,我们将cat函数的prototype对象指向一个animal对象的实例(其中就包含了animal的type属性了)。
代码第二行是什么意思呢?
首先,假如我们没有加这行代码,运行
cat.prototype = new animal();
console.log(cat.prototype.constructor == animal); //true
也就是说,其实每个prototype对象都有一个constructor属性,指向它的构造函数。
我们再看下面的代码
cat.prototype = new animal();
var cat1 = new cat("haha", 'red');
console.log(cat1.constructor == animal); //true
由上我们看到实例cat1的构造函数是animal,所以,显然是不对的。。。cat1明明是new cat()才生成的,所以我们应该手动纠正。cat.prototype对象的constructor值改为cat。
所以这也是我们应该注意的一点,如果我们替换了prototype对象,就应该手动纠正prototype对象的constructor属性。
o.prototype = {};
o.prototype.constructor = o;
直接继承prototype
由于在animal对象中,不变的属性可以直接写在animal.prototype中。然后直接让cat.prototype指向animal.prototype也就实现了继承。
现在我们先将animal对象改写成:
function animal() {
}
animal.prototype.type = '动物';
然后再实现继承:
cat.prototype = animal.prototype;
cat.prototype.constructor = cat;
var cat1 = new cat("haha","red");
console.log(cat1.type); // 动物
与上一种方法相比,这种方法显得效率更高(没有创建animal实例),节省了空间。但是这样做正确吗?答案是不正确,我们继续看。
cat.prototype = animal.prototype;
这行代码让cat.prototype和animal.prototype指向了同一个对象,所以如果改变了cat.prototype的某一个属性,都会反映到animal.prototype上,这显然不是我们想要看到的。
比如我们运行:
console.log(animal.prototype.constructor == animal) //false
结果看到是false,为什么呢?cat.prototype.constructor = cat;
这一行就会把animal.prototype的constructor属性也改掉了。
利用空对象作为中介
var F = function(){};
F.prototype = animal.prototype;
cat.prototype = new F();
cat.prototype.constructor = cat;
结合上面两种方法,因为F是空对象,所以几乎不占内存。这时修改cat的prototype对象,就不会影响到animal的prototype对象。
console.log(animal.prototype.constructor == animal); // true
然后我们将上面的方法封装一下:
function extend(Child, Parent) {
var F = function(){};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.uber = Parent.prototype;
}
使用的时候,方法如下:
extend(cat,animal);
var cat1 = new cat("haha","red");
console.log(cat1.type); // 动物
Child.uber = Parent.prototype;
这行代码就是个桥梁作用,让子对象的uber属性直接指向父对象的prototype属性,等于在自对象上打开一条叫uber的通道,让子对象的实例能够使用父对象的所有属性和方法。
javascript对象继承详解的更多相关文章
- JavaScript 面向对象继承详解
题记 由于js不像java那样是完全面向对象的语言,js是基于对象的,它没有类的概念.所以,要想实现继承,一般都是基于原型链的方式: 一.继承初探 大多数JavaScript的实现用 __proto_ ...
- <JavaScript> 寄生继承详解
// 将原型继承和非原型继承组合为一体的继承方式叫做组合继承,但是这种方法的继承是有一点小缺陷的,下级函数继承了无用的属性,所以我们有了寄生继承来解决污染问题; //创建上级构造函数-食物 funct ...
- [原创]JavaScript继承详解
原文链接:http://www.cnblogs.com/sanshi/archive/2009/07/08/1519036.html 面向对象与基于对象 几乎每个开发人员都有面向对象语言(比如C++. ...
- javascript event(事件对象)详解
javascript event(事件对象)详解 1. 事件对象 1. 事件对象 Event 对象代表事件的状态,比如事件在其中发生的元素.键盘按键的状态.鼠标的位置.鼠标按钮的状态. 什 ...
- 从mixin到new和prototype:Javascript原型机制详解
从mixin到new和prototype:Javascript原型机制详解 这是一篇markdown格式的文章,更好的阅读体验请访问我的github,移动端请访问我的博客 继承是为了实现方法的复用 ...
- JavaScript数组方法详解
JavaScript数组方法详解 JavaScript中数组的方法种类众多,在ES3-ES7不同版本时期都有新方法:并且数组的方法还有原型方法和从object继承的方法,这里我们只介绍数组在每个版本中 ...
- JavaScript严格模式详解
转载自阮一峰的博客 Javascript 严格模式详解 作者: 阮一峰 一.概述 除了正常运行模式,ECMAscript 5添加了第二种运行模式:"严格模式"(strict m ...
- openerp经典收藏 对象定义详解(转载)
对象定义详解 原文地址:http://shine-it.net/index.php/topic,2159.0.htmlhttp://blog.sina.com.cn/s/blog_57ded94e01 ...
- [转]javascript console 函数详解 js开发调试的利器
javascript console 函数详解 js开发调试的利器 分步阅读 Console 是用于显示 JS和 DOM 对象信息的单独窗口.并且向 JS 中注入1个 console 对象,使用该 ...
随机推荐
- 那些年,在AngularJS的路上遇到的坑
使用AngularJS这么久以来,遇到过一些坑,之前一直没有以书面的形式整理下,现在好好总结下,以供后面查备. 一.angular scope 在ng-if与ng-show下的区别(两者作用域的差别) ...
- 数据可视化(8)--D3数据的更新及动画
最近项目组加班比较严重,D3的博客就一拖再拖,今天终于不用加班了,赶紧抽点时间写完~~ 今天就将D3数据的更新及动画写一写~~ 接着之前的博客写~~ 之前写了一个散点图的例子,下面可以自己写一个柱状图 ...
- [java] 汇率换算器实现(2)
[java] 汇率换算器实现(2) // */ // ]]> // */ // ]]> [java] 汇率换算器实现(2) Table of Contents 1 系列文章地址 2 前 ...
- plsql修改表报错:ORA-25150
几次通过plsql修改表结构出现这个错误,为人不求甚解真是要不得.我甚至对老大大言不惭的说没有权限,即便是sql语句都不行.结果赤果果地打脸. 最终找到如下原因: 1.操作用户表空间的默认值问题: 这 ...
- bash魔法堂:History用法详解
Brief 又要敲那条长到没朋友的命令了,真心不再爱了... 有了history这条命令我想大家可以再爱一次了吧! >history 语法: history [n | -c | -raw his ...
- 【分享】学长的安利来了~~O(∩_∩)O
前言:应栋哥要求,学长把演讲稿稍微整理下发布出来,这可以算是一篇安利文,也可以说是一篇经历文吧.作为一个确确实实从软工里收获到挺多东西的过来人,学长希望可以通过学长的经历来让你们对软工更加期待. 安利 ...
- Emit学习(4) - Dapper解析之数据对象映射(一)
感觉好久没有写博客了, 这几天有点小忙, 接下来会更忙, 索性就先写一篇吧. 后面估计会有更长的一段时间不会更新博客了. 废话不多说, 先上菜. 一.示例 1. 先建类, 类的名称与读取的表名并没有什 ...
- jQuery uploadify在谷歌和火狐浏览器下无法上传
原因: 由于jQuery uploadify是借助flash来实现上传的,每一次向后台发送数据流请求时,ie会自动把本地cookie存储捆绑在一起发送给服务器.但firefox.chrome不会这样做 ...
- ASP.NET MVC ValueProvider小结
在Model绑定中,Model的数据来源有很多种,在MVC里面则定义了一套ValueProvider的组件来处理Model数据来源多样性的问题,ValueProvider整个结构类似于字典(Dictr ...
- C#中的枚举类型enum用法
定义一个简单的枚举类型: enum Days {Sat, Sun, Mon, Tue, Wed, Thu, Fri}; //这时候 Days.Sat = 0 ,后面依 ...