`
lyunabc
  • 浏览: 530349 次
  • 性别: Icon_minigender_2
社区版块
存档分类
最新评论

从零开始学javascript之二------JavaScript的继承

 
阅读更多

虽然JavaScript是动态函数式语言,并不原生的支持面向对象,不过面向对象中一些好的设计思想还是值得借鉴的,例如设计模式。因为JavaScript中有原型(prototype),可以或多或少的模拟出一些面向对象的特性,在这一点上,JavaScript可能超出了脚本语言的范畴。原型(prototype)是一个很奇妙的东西,JavaScript能够实现继承很多时候都是靠它完成的。

因为JavaScript不是为面向对象设计的,所以我们通常通过JavaScript的一些特性来模拟面向对象的特性。继承方面,主要通过prototype属性和call()/apply()方法完成。

对象的实例化使用关键字new,这个跟一般的面向对象的语言没有太大的差别。不过对象里面使用的是this关键字,例如:

?
1
2
3
4
5
6
7
8
9
10
var newObject= function(){
this.name = 'floaytyears',
this.getName = function(){
return this.name;
}
}
newObject.prototype.sayHi(){
alert('hi!');
}
var obj = new newObject();

这样我们在实例化的时候,newObject函数里面this就指向了obj。我们实例化得到的所有所有实例,都会共用prototype属性。而在newObject中的属性或方法,在每个实例中都有一个副本。为了减少内存的占用,一般会将函数放在prototype中,当然有特殊目的的除外。

提了一下JavaScript实例化的实现,接着说一下继承的实现。

继承一般是通过原型链来实现。例如:

?
1
2
3
4
5
6
function superClass(){
this.name = 'floatyears';
}
superClass.prototype.sayHi = function(){
alert('Hi');
}

另外一个对象subClass继承superClass,原型链的方法是:

?
1
2
3
function subClass(){}
subClass.prototype = new superClass();
subClass.prototype.constructor = subClass;

这是利用了实例中的__proto__属性。例如:

?
1
2
var instance1 = new superClass();
alert(instance1.__proto__ === superClass.prototype); // true

当我们实例化subClass的时候,例如:var instance2 = new subClass();instance2的__proto__属性就会指向subClass.prototype。而subClass.prototype = new superClass();则subClass.prototype的__proto__属性指向了superClass.prototype。因为我们的属性是从实例到原型搜索的。如果一个属性在实例中没有,那么就搜索实例的__proto__所指的原型,如果还没有找到此属性,则搜索原型的__proto__所指的对象。这样,通过__proto__属性形成了一条原型链,而子类也继承了超类的原型属性和方法。

不过subClass.prototype = new superClass()这样的方式有一个缺点。例如,实例化subClass的时候传递了一个参数name:var instance = new subClass(name),我们无法将参数传递给超类。不过用另外一种方式可以解决:

?
1
2
3
function subClass(name){
arguments.callee.prototype = new superClass(name);
}

这样的方式有一个问题,超类中的实例属性变成了子类的原型属性,子类所有实例共享。为了将超类的实例属性也被继承为子类的实例属性,可以用如下的方式:

?
1
2
3
function subClass(name){
superClass.call(this,name); //将超类的实例属性继承为子类的实例属性
}

接下来,我们如果再次使用subClass.prototype = new superClass(),那么超类的实例属性在子类的实例和原型中都出现了,就是出现了两次,这个没有必要,所以要用到下面的函数:

?
1
2
3
4
5
6
extend(subClass,superClass){
var F = function(){};
F.prototype = superClass.prototype;
subClass.prototype = new F();
subClass.prototype.constructor = subClass;
}

这里用了一个空函数F()来做中介,使得继承的时候可以避开超类的实例属性。因为某些浏览器中,__proto__属性不可用,所以避免直接对__proto__属性赋值。最后两部分结合起来就完成了继承:

?
1
2
3
4
function subClass(name){
superClass.call(this,name);
}
extend(subClass,superClass);

上面的这种继承方式,算是所有继承中最完善的。还有其他的一些继承方式,不过都存在一些问题,在某些情况下才适合使用。

分享到:
评论

相关推荐

    JonasJavascript2021:完整JavaScript课程2021

    完整JavaScript课程2021:从零到专家 这个惊人的课程涵盖以下主题: JavaScript基础知识:变量,if / else,运算符,布尔逻辑,函数,数组,对象,循环,字符串等。 现代OOP:类,构造函数,原型继承,封装等。 ...

    Ext官方中文教程(可打包下载)

    从零开始Ext 设置基础页 Javascript中的作用域(scope)是什么?(一) Javascript中的作用域(scope)是什么?(二) Ext源码概述 Ext与RESTful Web Services 程序设计: 如何合理地规划一个应用程序 如何本地化ext的...

    正则表达式

    /[^"] * / //匹配零个或多个非引号字符. 正则表达式的复制字符 字符 含义 __________________________________________________________________ {n, m} 匹配前一项至少n次,但是不能超过m次 {n, } 匹配前一...

    精通CSS+DIV网页样式与布局视频教材

    1.3.1 从零开始 1.3.2 加入CSS控制 1.3.3 控制图片 1.3.4 CSS的注释 第2章 CSS的基本语法 2.1 CSS选择器 2.1.1 标记选择器 2.1.2 类别选择器 2.1.3 ID选择器 2.2 选择器声明 2.2.1 ...

    ZombieSlayer:一个简单的浏览器2D射击游戏

    特征游戏机制从零开始,包括碰撞检测,计分,重生,活力等。 利用我自己的算法(进行中)在死亡后找到安全的产卵点使用HTML5 Canvas完成的基于Sprite的绘图和动画一些愚蠢的死亡效果,以满足嗜血! 利用HTML5本地...

    庖丁解牛:纵向切入ASP.NET 3.5控件和组件开发技术

    第3章 从零开始开发服务器控件 27 3.1 选择基类 27 3.2 控件呈现顺序 28 3.3 render呈现控件的几种方式 30 3.3.1 使用htmltextwriter类输出 30 3.3.2 直接输出html标签 32 3.3.3 使用服务器控件的...

    庖丁解牛纵向切入ASP.NET 3.5控件和组件开发技术.pdf

    第3章 从零开始开发服务器控件27 3.1 选择基类27 3.2 控件呈现顺序28 3.3 render呈现控件的几种方式30 3.3.1 使用htmltextwriter类输出30 3.3.2 直接输出html标签32 3.3.3 使用服务器控件的rendercontrol方法...

    庖丁解牛 纵向切入ASP.NET 3.5控件和组件开发 part1

    第3章 从零开始开发服务器控件 27 3.1 选择基类 27 3.2 控件呈现顺序 28 3.3 render呈现控件的几种方式 30 3.3.1 使用htmltextwriter类输出 30 3.3.2 直接输出html标签 32 3.3.3 使用服务器控件的...

    庖丁解牛 纵向切入ASP.NET 3.5控件和组件开发 part2

    第3章 从零开始开发服务器控件 27 3.1 选择基类 27 3.2 控件呈现顺序 28 3.3 render呈现控件的几种方式 30 3.3.1 使用htmltextwriter类输出 30 3.3.2 直接输出html标签 32 3.3.3 使用服务器控件的...

    PHP和MySQL WEB开发(第4版)

    第二篇 使用MySQL 第8章 设计Web数据库 8.1 关系数据库的概念 8.1.1 表格 8.1.2 列 8.1.3 行 8.1.4 值 8.1.5 键 8.1.6 模式 8.1.7 关系 8.2 如何设计Web数据库 8.2.1 考虑要建模的实际对象 8.2.2 避免保存冗余数据 ...

    PHP和MySQL Web开发第4版pdf以及源码

    第二篇 使用MySQL 第8章 设计Web数据库 8.1 关系数据库的概念 8.1.1 表格 8.1.2 列 8.1.3 行 8.1.4 值 8.1.5 键 8.1.6 模式 8.1.7 关系 8.2 如何设计Web数据库 8.2.1 考虑要建模的实际对象 8.2.2 避免...

    PHP和MySQL Web开发第4版

    第二篇 使用MySQL 第8章 设计Web数据库 8.1 关系数据库的概念 8.1.1 表格 8.1.2 列 8.1.3 行 8.1.4 值 8.1.5 键 8.1.6 模式 8.1.7 关系 8.2 如何设计Web数据库 8.2.1 考虑要建模的实际对象 8.2.2 避免...

    工程硕士学位论文 基于Android+HTML5的移动Web项目高效开发探究

    申请学位类别 工 程 硕 士 学位授予单位 东 南 大 学 工程领域名称 软 件 工 程 论文答辩日期 研究方向 Android+HTML5 学位授予日期 答辩委员会主席 评阅人 硕士学位论文 基于Android+HTML5的移动...

Global site tag (gtag.js) - Google Analytics