重操JS旧业第八弹:面向对象与继承
js里面没有语言语法层面的继承机制,但这并不意味着js就不能实现继承,利用js属性和方法动态性来模拟实现继承,通过总结大概有如下方法实现:
1 原型链继承
我们知道原型在对象中扮演着重要的角色,函数本身自带原型对象,通过对象创建便让对象拥有指向原型对象的指针,再次原型属性和方法的搜索覆盖机制,以及原型属性和方法的动态性
实现原理:手动将对象的原型对象修改为要继承的对象,如:
function Person(name,sex){
this.name=name;
Person.prototype.say=function(){
console.log('说中国话');
}
}
原型继承
function Child(){
Child.prototype=new Person();
}
var child=new Child();child.name;child.say();
1)手动修改对象的原型对象来达到继承目的
2)由于原型的静态性,这里也就具有原型静态性的优势和缺点
3)原型链,所有对象都来自Object,自然原型链也就会搜索到Object级别,这种自底向上的搜索机制构成了原型链;
4)缺点嘛:原型共享和没有构造函数向基类传递参数;
2 借用构造函数
既然原型链没办法像基类传递参数,这里使用函数的call,apply,bind方法来这样实现:
借用构造函数继承
function Child(name,sex){
Person.call(this,name,sex);
}
1)这样讲this传入了基类之中,本质上仅仅是基类的扩展
2)现在子类child的原型并没有被改变,所以不会搜索到基类的原型方法;
3)借用构造函数的实现过程就知道,丢掉了基类的接口方法,在避免原型链继承的同时又丢掉了原型链继承的优势;
3 组合继承
既然原型链主要目的是继承了原型方法,而借用构造实现了属性的顺利继承,那么将两则结合起来各取所长;
function Child(name,sex){
Person.call(this,name,sex);
Child.prototype=new Person();
}
1)很好的实现了借用构造和原型链的优势,因此成为非常常用的继承模式
2)但是通过2次调用基类构造函数,因此基类的构造函数会被执行2次;
4 原型式继承
这个东西的意思是说,将对象作为其他对象的原型对象,这里需要与原型链继承加以区别;
function Object(o){
function F();
F.prototype=o;
return new F();//通过构造函数复制了一份o的指针;
}
1)这个过程中并没有创建新的类型
2)这个过程是将现有对象进行封装扩展
3)适合那些不需要有类型的对象,适合相对临时创建的对象;
var obj={
name:'zhangsan',
friends:['lishi','wangwu']
};
var person=Object(obj);
person.friends.push('maliu');
相当于将obj这个对象进行了一次复制这样:var person=复制obj;得到与obj一样的副本,再创建扩展方法,也可以直接对之前拥有的成员操作;但是这里的复制仅仅是指针的复制并没有改变对象本身;
因此呢,obj对于子对象来说都是共享的;
4)这种继承方式使用面很少,因为没有明显优势
5 寄生式继承
寄生继承其本质上跟上面的原型式继承一样的,只不过扩展了点方法再返回
function Object(o){
function F();
F.prototype=o;
var f= new F();//通过构造函数复制了一份o的指针;
//返回之前扩展下方法,这样我们就叫寄生式,概念很高级吗,本质却很简单,不是么;
f.say=function(){console.log('xxxx')};
return f;
}
不用多说跟原型式继承应用返回也差不多;
6 寄生组合式继承
这种是解决组合继承模式下缺点而提出来的,由于组合继承模式会2次调用构造函数,且对于父类的属性会存在2份,自然的在重复调用构造函数的同时,又造成了内存的浪费,因为放在原型上的总会被实例属性所覆盖
解决这种问题,怎么办?
这是组合继承
function Child(name,sex){
Person.call(this,name,sex);//第二次调用构造函数
Child.prototype=new Person();//第一次调用构造函数
}
这个过程我们知道原型上的属性终会被第二次调用借用构造函数得到的属性所覆盖,那么也就意味着原型中我们只需要父类的方法即可,而原型的方法可以通过函数的原型属性访问到即
Person.prototype;那么我们只需要将原型属性丢给子类即可
其原理过程如下:
function Child(name,sex){
Person.call(this,name,sex);//第二次调用构造函数
Child.prototype=Person.prototype;//直接将原型丢给子类嘛,但是有个问题由于原型拥有一个constructor属性会指向Person
//这里还需要手动修改下
Child.prototype.constructor=Child;
}
我们也可以这样理解,伪代码
function(superType,subType){
subType.prototype=superType.prototype;//顺利的得到了父类的原型对象
subType.constructor=subType;//由于可能丢失类型,这里再次指向回来
}
再进一步封装
function(superType,subType){
//使用原型式得到一个临时对象
var obj=Object(superType.prototype);//看吧这里只是把原型取出来了
obj.constructor=subType;
subType.prototype=obj;//顺利的得到了父类的原型对象
}
js的继承与面向对象创建对象的思路一脉相承,都有临时和经典模式,只是看使用场合而选择哪种模式。
重操JS旧业第八弹:面向对象与继承的更多相关文章
- 重操JS旧业第七弹:面向对象与对象创建
JS是一种完全面向对象的程序设计语言,在面向对象处理方面,具有多种多样的实现方式,加之对象成员的动态性使得这门语言更加灵活:而js对象成员动态性也是创建和扩展对象的有力方式. 1 对象成员动态性 属性 ...
- 重操JS旧业第五弹:函数
函数在任何编程语言中起着非常重要的位置,因为他是功能的最小单元,在js中函数是一种类型 Function 1 申明与定义 显示声明:function cc(){};函数名其实是函数的一个指针,函数名某 ...
- 重操JS旧业第十一弹:BOM对象
BOM对象即浏览器内置对象,现今流行的浏览器内核有Safri,Firefox,Chrome,Opera,IE其中IE的兼容性是最蛋疼的在10及其过后还好点,但是现在IE基本上淘汰,而国内像360这种垃 ...
- 重操JS旧业第十弹:闭包
闭包是js最难理解,也是最蛋疼的一个名词,仿佛只可意会不可言传一样,有人说闭包说白了就是函数嵌套,也有人说闭包就是函数能够访问函数外部的变量,而内部的外部访问不了: 貌似都非常有道理,其实仔细想来只不 ...
- 重操JS旧业第六弹:基本类型包装
在前面已经知道js中的类型有boolean,string,number,undefined,function,object,其中boolean,number,string为值类型.所谓的基本类型包装, ...
- 重操JS旧业第四弹:Date与Global对象
1 Date原理 Date类型表示时间,js中采用UTC国际协调时间,以1971年1月1日0分0秒0微秒开始,经过的毫秒数来表示时间,比如一年的时间计算 1分:1000*60: 1小时:1000(毫秒 ...
- 重操JS旧业第三弹:Array
数组在任何编程语言中都是非常重要的,因为函数在最大程度上代表了要实现的功能,而数组则是这些函数所要操作的内存一部分. 1 构建数组 js与其他非脚本语言的灵活之处在于要实现一个目标它可能具有多种方式, ...
- 重操JS旧业第九弹:函数表达式
函数表达式,什么概念,表达式中的函数表达式. 1 函数申明 function 函数名([函数参数]){ //函数体 } js中无论像这样的显示函数什么放在调用之前还是调用之后,都不影响使用,因为js解 ...
- 重操JS旧业第二弹:数据类型与类型转换
一 数据类型 1 js中的数据类型 1.1 数据类型列举 1)number类型 2)boolean类型 3)string类型 4)对象类型 5)函数类型 6)undefined类型 1.2 数据类型获 ...
随机推荐
- [置顶] linux常用命令手册
前言:整理了一份linux常用命令手册,与大家分享.这是一些比较常用的命令. 我已经整理成一份PDF带书签的手册,可以到CSDN免费下载. 下载地址:http://download.csdn.net/ ...
- SeekBar 样式设置
1 SeekBar简介 SeekBar是进度条.我们使用进度条时,可以使用系统默认的进度条:也可以自定义进度条的图片和滑块图片等. 2 SeekBar示例 创建一个activity,包含2个SeekB ...
- Android:自己定义输入法(输入password时防止第三方窃取)
对于Android用户而言.一般都会使用第三方的输入法. 但是,在输入password时(尤其是支付相关的password),使用第三方输入法有极大的安全隐患. 眼下非常多网银类的APP和支付宝等软件 ...
- Android 启动APP时黑屏白屏的三个解决方案(转载)
你会很奇怪,为什么有些app启动时,会出现一会儿的黑屏或者白屏才进入Activity的界面显示,但是有些app却不会如QQ手机端,的确这里要做处理一下.这里先了解一下为什么会出现这样的现象,其实很简单 ...
- linux命令sysctl使用
以前没有注意过这个命令,直到有次在单位安装greenplum的时候,在没有配置系统参数的情况下,出现了设备空间不足的报错信息. 当然,安装的不是我的本机,而是公用的服务器,编辑修改系统参数后,仍然出现 ...
- 配置greenplum参数
在进行一个greenplum安装之前需要进行配置一下相关的系统参数,否则很容易出现意想不到的错误. 1.修改系统参数 编辑 /etc/sysctl.conf ,以下是最小配置 kernel.shmma ...
- [HDU 4842]--过河(dp+状态压缩)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4842 过河 Time Limit: 3000/1000 MS (Java/Others) Mem ...
- mysqldump 备份数据说明+ 避免锁表
1.mysqldump命令备份Mysql数据库的参数说明 在用mysqldump备份使用那些参数选项是最完美的组合呢?--skip-opt--create-option ...
- Ural 1297 Palindrome 【最长回文子串】
最长回文子串 相关资料: 1.暴力法 2.动态规划 3.中心扩展 4.Manacher法 http://blog.csdn.net/ywhorizen/article/details/6629268 ...
- 转:Javascript继承机制的设计思想
我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类"的概念,也没有"类"(class)和"实例" ...