对于javascript中的继承,因为js中没有后端语言中的类式继承。所以js中的继承,一般都是原型继承(prototype)。

function P (name){
this.name = name;
this.say = function(){
console.log('p');
}
} function S (name,id){
this.id = id; this.eat = function(){
console.log('s');
}
} S.prototype = P.prototype; var s = new S();

以上代代码存在一个重要问题:

S.prototype = P.prototype;

该句代码会导致,在改动子类的prototype的时候,相同会影响父类的prototype元素。

解决方案一般採用new 父级对象的方式:

S.prototype = new P();

这里涉及到new 的工作原理,new P(), 会依据P的prototype对象建立一个实例,然后将构造方法中的成员变量和成员方法设置进去。

此种方式, 改动子类的prototype则不会影响父类的prototpye(因为是新建了一个对象,不再是指向同一个prototype).

设置prototype之后。还须要重置子类S的contrustor,让其重指向 S。而不是new P() 所相应的construstor. 例如以下:

S.prototype.constructor = S;

非常多时候这里不重置。不会出现故障,可是假设后面须要用到constructor 来创建实例,或者判定实例类型,则会出现错误。

所以这里最好是重置。

上面所述的原型继承。尽管能够通过JavaScript原型继承,可是相同存在不足。

此种继承方式。不可以继承在构造方法设置的成员变量和成员方法。仅仅能继承在原型中设置的方法,或者属性。

如:

var s = new S('yang','01');

当中的第一个參数,并不能传递给到name属性。

于是引出另外一种继承方式: 对象冒充。

function P (name){
this.name = name;
this.say = function(){
console.log('p');
}
} function S (name,id){
P.call(this,name);
this.id = id;
this.eat = function(){
console.log('s');
}
} var s = new S('yanghi','test');

在子类构造方法中,借用父类的构造方法。使子类具有父类的属性和方法。

例如以下:

P.call(this,name);

该句代码与例如以下效果一样:

this.name = name;
this.say = function(){}

从而将父类的属性复制到子类中。从而实现对象冒充。

那么该此种对象冒充方式。相同存在问题:

1 无法继承原型prototype中的属性和主法。

2 构造方法的成员方法在父类和子类中都会有一份拷贝,造成内存的添加。

所以最好的实现方式是:

1 对原型对象。採用原型继承

2 构造方法中的属性和方法。採用对象冒充。

这也是当前绝大对数的js继承库所採用的实现方式。例如以下:

function P (name){
this.name = name;
} P.prototype.say = function(){
console.log('say');
} function S (name,id){
P.call(this,name);
this.id = id;
} function Bare(){}
Bare.prototype = P.prototype;
S.prototype = new Bare();
S.prototype.constructor = S; S.prototype.eat = function(){
console.log('eat');
} var s = new S('yanghi','test');

这里的成员属性。採用对象冒充,成员方法採用原型继承。

注意一点。这里实现原型继承须要採用一个中间变量。例如以下:

S.prototype = new Bare();

假设不採用中间变量。直接new P() 的话,会出现故障。

因为new 会依照P的prototype对象模版,创建一个对象,这一步没有问题。

可是接下来。它会将P构造方法的成员属性也设置到这个对象中,就会导致对这个对象污染。

这里我们仅仅须要它的prototype就能够了。其他的成员变量採用对象冒充的方式就能够了。

第三种实现继承方式,採用ES5 Object.create实现。

//Shape - superclass
function Shape() {
this.x = 0;
this.y = 0;
} Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
console.info("Shape moved.");
}; // Rectangle - subclass
function Rectangle() {
Shape.call(this); //call super constructor.
} Rectangle.prototype = Object.create(Shape.prototype); var rect = new Rectangle(); rect instanceof Rectangle //true.
rect instanceof Shape //true. rect.move(1, 1); //Outputs, "Shape moved."

只是此方式最大的问题还是兼容性,须要 IE 9 + , safari 5 +,opera 11.6 +

以上就是对象继承的一些问题,以记录之,谨防忘记。

[ JavaScript ] JavaScript 实现继承.的更多相关文章

  1. javascript 之 prototype继承机制

    理解Javascript语言的继承机制 javascript没有"子类"和"父类"的概念,也没有"类"(class)和"实例&qu ...

  2. JavaScript寄生组合式继承分析

    JavaScript寄生组合式继承特点: 避免了在子类prototype上创建不必要多余的属性,相比直接继承基类的实例效率要高. 是JavaScript 实现继承的最有效方式. <script& ...

  3. 深入理解:JavaScript原型与继承

    深入理解:JavaScript原型与继承 看过不少书籍,不少文章,对于原型与继承的说明基本上让人不明觉厉,特别是对于习惯了面向对象编程的人来说更难理解,这里我就给大家说说我的理解. 首先JavaScr ...

  4. JavaScript学习13 JavaScript中的继承

    JavaScript学习13 JavaScript中的继承 继承第一种方式:对象冒充 <script type="text/javascript"> //继承第一种方式 ...

  5. 浅谈JavaScript中的继承

    引言 在JavaScript中,实现继承的主要方式是通过原型链技术.这一篇文章我们就通过介绍JavaScript中实现继承的几种方式来慢慢领会JavaScript中继承实现的点点滴滴. 原型链介绍 原 ...

  6. JavaScript 类式继承与原型继承

    交叉着写Java和Javascript都有2年多了,今天来总结下自己所了解的Javascript类与继承. Javascript本身没有类似Java的面向对象的类与继承术语,但其基于原型对象的思想却可 ...

  7. JavaScript中的继承(原型链)

    一.原型链 ECMAScript中将原型链作为实现继承的主要方法,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法. 实例1: function SupType() { this.pro ...

  8. 【JavaScript回顾】继承

    组合继承 组合继承(combination inheritance),有时候也叫做伪经典继承,指的是将原型链和借用构造函数的 技术组合到一块,从而发挥二者之长的一种继承模式.其背后的思路是使用原型链实 ...

  9. #JavaScript对象与继承

    JavaScript对象与继承 JavaScript是我在C语言之后接触的第二门编程语言,大一暑假的时候在图书馆找了一本中国人写的JavaScript程序设计来看.那个时候在编程方面几乎还是小白,再加 ...

  10. javascript中的继承方法

    从Javascript面向对象编程(二):构造函数的继承这里,可以看到详细的说明. 我只是将其中的例子做成html文件,便于调试罢了. 1. 构造函数绑定 <html> <head& ...

随机推荐

  1. HTTP协议头部字段释义

    1. Accept:告诉WEB服务器自己接受什么介质类型,*/* 表示任何类型,type/* 表示该类型下的所有子类型,type/sub-type. 2. Accept-Charset: 浏览器申明自 ...

  2. 再战primer——decltype 和引用

    刷primer看到原文讲到"引用从来都作为其所指对象的同义词出现,只有用在decltype处是一个例外.",我很是好奇. 这个“引用”当然是指引用类型,like this: ; i ...

  3. Android:用签名打包后微信分享失效

    刚开始使用微信分享,申请的微信appid也可以在直接使用,分享成功! 当我使用自己的签名打包分享时却分享失败,一闪而过,好郁闷的说,为什么之前没有打包就可以,签名打包后就不可以了... 开始查找各种资 ...

  4. 6、scala Map和Tuple

    1.  创建Map 2.访问Map元素 3.修改Map元素的值 4.遍历Map 5.SortedMap和LinkedHashMap 6.Map的元素类型Tuple 1.  创建Map 创建不可变的Ma ...

  5. 简述cookie ,localStrage,sessionStorage的区别?

    1.cookie: 是一个回话跟踪技术,信息存储在用户硬盘,可以做全局变量. 什么是会话:用户进入网站,开始浏览到结束的这样的一个过程,称为一次会话. 会话跟踪技术:浏览器和服务器之间进行多次请求数据 ...

  6. GFS分布式文件系统脚本

    #!/bin/bashfor i in $(fdisk -l | grep -wo "/dev/sd[b-z]" | sort)dodd if=/dev/zero of=$i bs ...

  7. php连接数据库的两种方式

    一.mysqli方式连接数据库 $mysql_conf = array( 'host' => 'localhost:3306', 'db' => 'ssql', 'db_user' =&g ...

  8. [C++] 配平化学方程式算法的封装

    有人已经实现了配平的方法,在此不再重复介绍. https://www.cnblogs.com/Elfish/p/7631603.html 但是,上述的方法所提供的代码还是存在着问题,需要进一步修改. ...

  9. 网际协议IP简述

    最近花了些时间重新回顾了谢希仁教授主编的<计算机网络>关于网络层的章节,这是一本高校教材,里面关于计算机网络的内容比较基础,并且讲的很细致,笔者针对网际协议IP地址部分觉得有必要进行阅读后 ...

  10. Java 初学者

    在有C++和C#基础之下开始学习Java,主要记录了一些和C++C#不同的或不知到的点 栈对象必须初始化,否则会报错.(其他的则有默认值) byte占用8位,char占用16位 接口默认为public ...