浅谈js中的三种继承方式及其优缺点


Posted in Javascript onAugust 10, 2016

第一种,prototype的方式:

//父类 
function person(){ 
  this.hair = 'black'; 
  this.eye = 'black'; 
  this.skin = 'yellow'; 
  this.view = function(){ 
    return this.hair + ',' + this.eye + ',' + this.skin; 
  } 
} 

//子类 
function man(){ 
  this.feature = ['beard','strong']; 
} 

man.prototype = new person(); 
var one = new man(); 

console.log(one.feature); //['beard','strong'] 
console.log(one.hair); //black 
console.log(one.eye); //black 
console.log(one.skin); //yellow 
console.log(one.view()); //black,black,yellow

这种方式最为简单,只需要让子类的prototype属性值赋值为被继承的一个实例就行了,之后就可以直接使用被继承类的方法了。

prototype 属性是啥意思呢? prototype 即为原型,每一个对象 ( 由 function 定义出来 ) 都有一个默认的原型属性,该属性是个对象类型。

并且该默认属性用来实现链的向上攀查。意思就是说,如果某个对象的属性不存在,那么将通过prototype属性所属对象来查找这个属性。如果 prototype 查找不到呢?

js会自动地找prototype的prototype属性所属对象来查找,这样就通过prototype一直往上索引攀查,直到查找到了该属性或者prototype最后为空 (“undefined”);

例如上例中的one.view()方法,js会先在one实例中查找是否有view()方法,因为没有,所以查找man.prototype属性,而prototype的值为person的一个实例,

该实例有view()方法,于是调用成功。

第二种,apply的方式:

//父类 
function person(){ 
  this.hair = 'black'; 
  this.eye = 'black'; 
  this.skin = 'yellow'; 
  this.view = function(){ 
    return this.hair + ',' + this.eye + ',' + this.skin; 
  } 
} 

//子类 
function man(){ 
  // person.apply(this,new Array()); 
  person.apply(this,[]); 
  this.feature = ['beard','strong']; 
} 

var one = new man(); 

console.log(one.feature); //['beard','strong'] 
console.log(one.hair); //black 
console.log(one.eye); //black 
console.log(one.skin); //yellow 
console.log(one.view()); //black,black,yellow

注意:如果apply参数为空,即没有参数传递,则通过 new Array() 、[] 来传递,null 无效。

第三种,call+prototype的方式:

//父类 
function person(){ 
  this.hair = 'black'; 
  this.eye = 'black'; 
  this.skin = 'yellow'; 
  this.view = function(){ 
    return this.hair + ',' + this.eye + ',' + this.skin; 
  } 
} 

//子类 
function man(){ 
  // person.apply(this,new Array()); 
  person.call(this,[]); 
  this.feature = ['beard','strong']; 
} 

man.prototype = new person(); 
var one = new man(); 

console.log(one.feature); //['beard','strong'] 
console.log(one.hair); //black 
console.log(one.eye); //black 
console.log(one.skin); //yellow 
console.log(one.view()); //black,black,yellow

call方式的实现机制却要多一条 man.prototype = new person(); 为啥呢?
那是因为call方法只实现了方法的替换而没有作对象属性的复制操作。
google Map API 的继承就是使用这种方式。

上面总结了三种继承方式的实现。但是每种方法都有其优缺点。

假如父类是这样的:

//父类 
function person(hair,eye,skin){ 
  this.hair = hair; 
  this.eye = eye; 
  this.skin = skin; 
  this.view = function(){ 
    return this.hair + ',' + this.eye + ',' + this.skin; 
  } 
}

子类应该如何设计,使子类man在创建对象的同时传递参数到父类person,prototype的继承方式就不适用了,
必须采用apply或者call的方式了:

//apply方式 
//子类 
function man(hair,eye,skin){ 
  person.apply(this,[hair,eye,skin]); 
  this.feature = ['beard','strong']; 
} 
//call方式 
//子类 
function man(hair,eye,skin){ 
  person.call(this,hair,eye,skin); 
  this.feature = ['beard','strong']; 
}

但是用apply方法也还是有缺点的,为什么?在js中,我们有个非常重要的运算符就是”instanceof”,该运算符用来比较某个对向是否为某种类型。

对于这个例子,one实例除了是man类型,也应该是person类型,但是apply方式继承之后,one却不属于person类型,即(one instanceof person)的值为false。

经此种种,最好的继承方式就是call+prototype方式了,之后你可以试一下(one instanceof BaseClass)的值是否为true。

第三种继承方式也有缺陷:子类new对象时要传一遍父类所需的参数,而且会重现父类中的属性和方法,下面这种继承方式才是完善的:

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

Person.prototype.getName = function() { 
  return this.name; 
} 

function Chinese(name, nation) { 
  Person.call(this, name); 
  this.nation = nation; 
} 

//继承方法 
function inherit(subClass, superClass) { 
  function F() {} 
  F.prototype = superClass.prototype; 
  subClass.prototype = new F(); 
  subClass.prototype.constructor = subClass.constructor; 
} 

inherit(Chinese, Person); 

Chinese.prototype.getNation = function() { 
  return this.nation; 
}; 

var p = new Person('shijun'); 
var c = new Chinese("liyatang", "China"); 

console.log(p); // Person {name: "shijun", getName: function} 
console.log(c); // Chinese {name: "liyatang", nation: "China", constructor: function, getNation: function, getName: function} 


console.log(p.constructor); // function Person(name){} 
console.log(c.constructor); // function Chinese(){} 

console.log(c instanceof Chinese); // true 
console.log(c instanceof Person); // true

以上这篇浅谈js中的三种继承方式及其优缺点就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
让插入到 innerHTML 中的 script 跑起来的实现代码
Jul 01 Javascript
用JS提交参数创建form表单在FireFox中遇到的问题
Jan 16 Javascript
js中cookie的添加、取值、删除示例代码
Oct 21 Javascript
jQuery计算textarea中文字数(剩余个数)的小程序
Nov 28 Javascript
jquery左边浮动到一定位置时显示返回顶部按钮
Jun 05 Javascript
在JavaScript中构建ArrayList示例代码
Sep 17 Javascript
使用js画图之正弦曲线
Jan 12 Javascript
JS实现一个按钮的方法
Feb 05 Javascript
JavaScript使用yield模拟多线程的方法
Mar 19 Javascript
javascript去除空格方法小结
May 21 Javascript
一张Web前端的思维导图分享
Jul 03 Javascript
js实现简易计算器小功能
Nov 18 Javascript
jQuery+HTML5+CSS3制作支持响应式布局时间轴插件
Aug 10 #Javascript
基于js中的原型、继承的一些想法
Aug 10 #Javascript
新入门node.js必须要知道的概念(必看篇)
Aug 10 #Javascript
jQuery制作圣诞主题页面 更像是爱情影集
Aug 10 #Javascript
jquery实现拖动效果
Aug 10 #Javascript
JS弹出新窗口被拦截的解决方法
Aug 09 #Javascript
只要1K 纯JS脚本送你一朵3D红色玫瑰
Aug 09 #Javascript
You might like
ThinkPHP中数据操作案例分析
2015/09/27 PHP
关于onScroll事件在IE6下每次滚动触发三次bug说明
2011/09/21 Javascript
VBS通过WMI监视注册表变动的代码
2011/10/27 Javascript
JavaScript利用正则表达式去除日期中的-
2014/06/09 Javascript
用NODE.JS中的流编写工具是要注意的事项
2016/03/01 Javascript
基于javascript实现九九乘法表
2016/03/27 Javascript
nodeJs内存泄漏问题详解
2016/09/05 NodeJs
js获取元素的标签名实现方法
2016/10/08 Javascript
jQuery选择器实例应用
2017/01/05 Javascript
jQuery中layer分页器的使用
2017/03/13 Javascript
Vue表单验证插件Vue Validator使用方法详解
2017/04/07 Javascript
详解用vue.js和laravel实现微信支付
2017/06/23 Javascript
通过源码分析Vue的双向数据绑定详解
2017/09/24 Javascript
在knockoutjs 上自己实现的flux(实例讲解)
2017/12/18 Javascript
vue自定v-model实现表单数据双向绑定问题
2018/09/03 Javascript
详解利用nodejs对本地json文件进行增删改查
2019/09/20 NodeJs
JS中数组实现代码(倒序遍历数组,数组连接字符串)
2019/12/29 Javascript
Vue+abp微信扫码登录的实现代码示例
2020/01/06 Javascript
requests和lxml实现爬虫的方法
2017/06/11 Python
基于Python中numpy数组的合并实例讲解
2018/04/04 Python
python 字典中文key处理,读取,比较方法
2018/07/06 Python
pycharm修改界面主题颜色的方法
2019/01/17 Python
python print出共轭复数的方法详解
2019/06/25 Python
django 中QuerySet特性功能详解
2019/07/25 Python
新手学python应该下哪个版本
2020/06/11 Python
python 实现"神经衰弱"翻牌游戏
2020/11/09 Python
详解Python之Scrapy爬虫教程NBA球员数据存放到Mysql数据库
2021/01/24 Python
YesStyle美国/全球:购买亚洲时装、美容化妆品和生活百货
2017/01/16 全球购物
Hoover胡佛官网:美国吸尘器和洗地机品牌
2019/01/09 全球购物
MYPROTEIN澳大利亚官方网站:欧洲运动营养品牌
2019/06/26 全球购物
本科毕业生的求职信范文
2013/11/20 职场文书
大学生的应聘自我评价
2013/12/13 职场文书
公司经理聘任书
2014/03/29 职场文书
统计学教授推荐信
2014/09/18 职场文书
植物园观后感
2015/06/11 职场文书
2016高三毕业赠言寄语
2015/12/04 职场文书