[ JavaScript ] JavaScript 实现继承.
对于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 实现继承.的更多相关文章
- javascript 之 prototype继承机制
理解Javascript语言的继承机制 javascript没有"子类"和"父类"的概念,也没有"类"(class)和"实例&qu ...
- JavaScript寄生组合式继承分析
JavaScript寄生组合式继承特点: 避免了在子类prototype上创建不必要多余的属性,相比直接继承基类的实例效率要高. 是JavaScript 实现继承的最有效方式. <script& ...
- 深入理解:JavaScript原型与继承
深入理解:JavaScript原型与继承 看过不少书籍,不少文章,对于原型与继承的说明基本上让人不明觉厉,特别是对于习惯了面向对象编程的人来说更难理解,这里我就给大家说说我的理解. 首先JavaScr ...
- JavaScript学习13 JavaScript中的继承
JavaScript学习13 JavaScript中的继承 继承第一种方式:对象冒充 <script type="text/javascript"> //继承第一种方式 ...
- 浅谈JavaScript中的继承
引言 在JavaScript中,实现继承的主要方式是通过原型链技术.这一篇文章我们就通过介绍JavaScript中实现继承的几种方式来慢慢领会JavaScript中继承实现的点点滴滴. 原型链介绍 原 ...
- JavaScript 类式继承与原型继承
交叉着写Java和Javascript都有2年多了,今天来总结下自己所了解的Javascript类与继承. Javascript本身没有类似Java的面向对象的类与继承术语,但其基于原型对象的思想却可 ...
- JavaScript中的继承(原型链)
一.原型链 ECMAScript中将原型链作为实现继承的主要方法,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法. 实例1: function SupType() { this.pro ...
- 【JavaScript回顾】继承
组合继承 组合继承(combination inheritance),有时候也叫做伪经典继承,指的是将原型链和借用构造函数的 技术组合到一块,从而发挥二者之长的一种继承模式.其背后的思路是使用原型链实 ...
- #JavaScript对象与继承
JavaScript对象与继承 JavaScript是我在C语言之后接触的第二门编程语言,大一暑假的时候在图书馆找了一本中国人写的JavaScript程序设计来看.那个时候在编程方面几乎还是小白,再加 ...
- javascript中的继承方法
从Javascript面向对象编程(二):构造函数的继承这里,可以看到详细的说明. 我只是将其中的例子做成html文件,便于调试罢了. 1. 构造函数绑定 <html> <head& ...
随机推荐
- ansible publishing service
# ansible 初始化服务机 - hosts: newserver vars: - basedir: opt tasks: - name: 安装常用依赖环境 yum: name={{ item } ...
- 软件架构自学笔记-- 转载“虎牙在全球 DNS 秒级生效上的实践”
虎牙在全球 DNS 秒级生效上的实践 这次分享的是全球 DNS 秒级生效在虎牙的实践,以及由此产生的一些思考,整体上,分为以下 5 各部分: 背景介绍: 方案设计和对比: 高可用: 具体实践和落地: ...
- gtest ASSERT_TRUE和EXPECT_TRUE
调用ASSERT_TRUE的函数,返回值类型定义必须是void,如果想返回别的类型,就用EXPECT_TRUE: void abc::fun() { ASSERT_TRUE(fun1()); } bo ...
- 详解HashMap数据结构实现
HashMap的设计是由数组加链表的符合数据结构,在这里用自己的语言以及结合源码去总结一下,如果有不对的地方希望评论指正,先拱手谢谢. HashMap是日常中非常常用的一种数据结构,我们要想深入了解学 ...
- url取值乱码问题,url加中文导致页面不能加载问题 js unicode转码,以及解码
很多时候写H5或其他适配时,打不开url.很多原因是因为浏览器不支持中文url,从url拿 出来的中文值也会乱码,这时候就必须把中文转化成Unicode值,去进行页面传值 中文转Unicode fun ...
- 铁大FaceBook的使用体验副本
铁大FaceBook是一个类似QQ和微信等聊天程序的缩小版网站,并且其针对领域较为狭窄:即只针对校园的学生和导员等人员.但其有值得推广的潜力性和可能性. 对于使用它的体验:第一点我感觉这个网站的界面很 ...
- Python学习【第5篇】:Python之函数(自定义函数,内置函数,装饰器,迭代器,生成器、模块)
一.为什么要使用函数? 1.避免代码重用 2.提高代码的可读性 二.函数的定义与调用 1. def 函数名(参数1,参数2): ''' 函数注释''' print('函数体') return 返回值 ...
- CentOS 7.2安装配置Vsftp服务器
一.配置防火墙,开启FTP服务器需要的端口 CentOS 7.2默认使用的是firewall作为防火墙,这里改为iptables防火墙. 1.关闭firewall: systemctl stop fi ...
- java 常见问题
1.Cannot convert value '0000-00-00 00:00:00' from column 1 to TIMESTAMP 2.怎么解决BigDecimal里面无限循环小数的问题啊 ...
- C#关键字详解第六节
3.28 日志记录:前段时间参加技能大赛,所以未更新博客,特此补上,第一次写博客,希望自己认真下去,努力,天道酬勤! 比赛给我的感悟很深!古语云:山外有山,强中自有强中手! do:执行语句 说do之前 ...