浅谈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 相关文章推荐
js 提交和设置表单的值
Dec 19 Javascript
javascript全局变量封装模块实现代码
Nov 28 Javascript
一个JavaScript用逗号分割字符串实例
Sep 22 Javascript
Js实现自定义右键行为
Mar 26 Javascript
jQuery form插件之ajaxForm()和ajaxSubmit()的可选参数项对象
Jan 23 Javascript
JavaScript简单获取页面图片原始尺寸的方法
Jun 21 Javascript
React Native中TabBarIOS的简单使用方法示例
Oct 13 Javascript
vue父组件向子组件(props)传递数据的方法
Jan 02 Javascript
npm 下载指定版本的组件方法
May 17 Javascript
详解vscode中vue代码颜色插件
Oct 11 Javascript
Vue之beforeEach非登录不能访问的实现(代码亲测)
Jul 18 Javascript
bootstrap-treeview实现多级树形菜单 后台JSON格式如何组织?
Jul 26 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数组是否为空的代码
2011/09/08 PHP
深入探讨:Nginx 502 Bad Gateway错误的解决方法
2013/06/03 PHP
详细解读PHP中接口的应用
2015/08/12 PHP
php实现网站文件批量压缩下载功能
2015/10/28 PHP
学习php设计模式 php实现工厂模式(factory)
2015/12/07 PHP
thinkPHP框架整合tcpdf插件操作示例
2018/08/07 PHP
laravel withCount 统计关联数量的方法
2019/10/10 PHP
Laravel框架Eloquent ORM简介、模型建立及查询数据操作详解
2019/12/04 PHP
取得传值的函数
2006/10/27 Javascript
JS 控制CSS样式表
2009/08/20 Javascript
jquery.cvtooltip.js 基于jquery的气泡提示插件
2010/11/19 Javascript
jquery 与NVelocity 产生冲突的解决方法
2011/06/13 Javascript
EXTjs4.0的store的findRecord的BUG演示代码
2013/06/08 Javascript
AngularJs Javascript MVC 框架
2016/06/20 Javascript
利用angular.copy取消变量的双向绑定与解析
2016/11/25 Javascript
JavaScript中transform实现数字翻页效果
2017/03/08 Javascript
javascript 中的继承实例详解
2017/05/05 Javascript
妙用Angularjs实现表格按指定列排序
2017/06/23 Javascript
JSON的parse()方法介绍
2019/01/31 Javascript
解决vue 使用setTimeout,离开当前路由setTimeout未销毁的问题
2020/07/21 Javascript
[01:31:02]TNC vs VG 2019国际邀请赛淘汰赛 胜者组赛BO3 第一场
2019/08/22 DOTA
python快速排序代码实例
2013/11/21 Python
常用python编程模板汇总
2016/02/12 Python
python实现用户登录系统
2016/05/21 Python
Flask 让jsonify返回的json串支持中文显示的方法
2018/03/26 Python
python中使用iterrows()对dataframe进行遍历的实例
2018/06/09 Python
Python实现12306火车票抢票系统
2019/07/04 Python
Python中拆分字符串的操作方法
2019/07/23 Python
python 常见的反爬虫策略
2020/09/27 Python
全球最大的瓷器、水晶和银器零售商:Replacements
2020/06/15 全球购物
军训的自我鉴定
2013/12/10 职场文书
个人求职信范例
2014/01/29 职场文书
弘扬焦裕禄精神践行三严三实心得体会
2014/10/13 职场文书
大学生自我评价范文
2015/03/03 职场文书
故意伤害罪辩护词
2015/05/21 职场文书
JS Object构造函数之Object.freeze
2021/04/28 Javascript