浅谈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 相关文章推荐
javascript中的一些注意事项 更新中
Dec 06 Javascript
js动态调用css属性的小规律及实例说明
Dec 28 Javascript
jQuery判断元素上是否绑定了指定事件的方法
Mar 17 Javascript
javascript闭包的理解
Apr 01 Javascript
搞定immutable.js详细说明
May 02 Javascript
遍历js中对象的属性和值的实例
Nov 21 Javascript
如何正确理解javascript的模块化
Mar 02 Javascript
详解JS函数stack size计算方法
Jun 18 Javascript
axios全局注册,设置token,以及全局设置url请求网段的方法
Sep 25 Javascript
基于js Canvas实现二次贝塞尔曲线
Dec 25 Javascript
详解webpack编译速度提升之DllPlugin
Feb 05 Javascript
详解Vue项目中实现锚点定位
Apr 24 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
PHP常用的文件操作函数经典收藏
2013/04/02 PHP
jQuery中setTimeout的几种使用方法小结
2013/04/07 Javascript
JS定时刷新页面及跳转页面的方法
2013/07/04 Javascript
JS小游戏之仙剑翻牌源码详解
2014/09/25 Javascript
JavaScript判断数组是否包含指定元素的方法
2015/07/01 Javascript
JS实现从顶部下拉显示的带动画QQ客服特效代码
2015/10/24 Javascript
Bootstrap每天必学之轮播(Carousel)插件
2016/04/25 Javascript
使用纯JS代码判断字符串中有多少汉字的实现方法(超简单实用)
2016/11/12 Javascript
JavaScript文件的同步和异步加载的实现代码
2017/08/19 Javascript
解决element UI 自定义传参的问题
2018/08/22 Javascript
JS数组求和的常用方法总结【5种方法】
2019/01/14 Javascript
JS实现指定区域的全屏显示功能示例
2019/04/25 Javascript
vue计算属性+vue中class与style绑定(推荐)
2020/03/30 Javascript
Threejs实现滴滴官网首页地球动画功能
2020/07/13 Javascript
c++生成dll使用python调用dll的方法
2014/01/20 Python
解读Django框架中的低层次缓存API
2015/07/24 Python
Python找出微信上删除你好友的人脚本写法
2018/11/01 Python
django celery redis使用具体实践
2019/04/08 Python
使用django的objects.filter()方法匹配多个关键字的方法
2019/07/18 Python
Windows+Anaconda3+PyTorch+PyCharm的安装教程图文详解
2020/04/03 Python
python实现秒杀商品的微信自动提醒功能(代码详解)
2020/04/27 Python
python安装和pycharm环境搭建设置方法
2020/05/27 Python
农救科工作职责
2013/11/27 职场文书
部队万能检讨书
2014/02/20 职场文书
21岁生日感言
2014/02/27 职场文书
幼儿教师培训感言
2014/03/08 职场文书
房地产公司见习自我鉴定
2014/04/28 职场文书
祖国在我心中演讲稿300字
2014/05/04 职场文书
新品发布会策划方案
2014/06/08 职场文书
2014年高数考试作弊检讨书
2014/12/14 职场文书
2014年优秀班主任工作总结
2014/12/16 职场文书
《叶问2》观后感
2015/06/15 职场文书
暑假打工感想
2015/08/07 职场文书
2016高考冲刺决心书
2015/09/23 职场文书
关于战胜挫折的名言警句大全!
2019/07/05 职场文书
防止web项目中的SQL注入
2021/12/06 MySQL