浅谈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 相关文章推荐
List the Stored Procedures in a SQL Server database
Jun 20 Javascript
使用新的消息弹出框blackbirdjs
Oct 16 Javascript
使用jQuery实现dropdownlist的联动效果(sharepoint 2007)
Mar 30 Javascript
鼠标经过显示二级菜单js特效
Aug 13 Javascript
纯js分页代码(简洁实用)
Nov 05 Javascript
javascript常见数据验证插件大全
Aug 03 Javascript
JS图片等比例缩放方法完整示例
Aug 03 Javascript
JS中微信小程序自定义底部弹出框
Dec 22 Javascript
javascript使用递归算法求两个数字组合功能示例
Jan 03 Javascript
原生js实现旋转木马轮播图效果
Feb 27 Javascript
Vue中的transition封装组件的实现方法
Aug 13 Javascript
分享8个JavaScript库可更好地处理本地存储
Oct 12 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 stristr() 函数(不区分大小写的字符串查找)
2010/06/03 PHP
php获取开始与结束日期之间所有日期的方法
2016/11/29 PHP
JavaScript 基础知识 被自己遗忘的
2009/10/15 Javascript
Ext 今日学习总结
2010/09/19 Javascript
jquery jqPlot API 中文使用教程(非常强大的图表工具)
2011/08/15 Javascript
分享一个我自己写的ToolTip提示插件(附源码)
2013/01/20 Javascript
jQuery 过滤方法filter()选择具有特殊属性的元素
2014/06/15 Javascript
js+css实现的圆角边框TAB选项卡滑动门代码分享(2款)
2015/08/26 Javascript
跟我学习javascript的全局变量
2015/11/16 Javascript
JavaScript实现身份证验证代码
2016/02/17 Javascript
BootStrap智能表单实战系列(九)表单图片上传的支持
2016/06/13 Javascript
数组Array的排序sort方法
2017/02/17 Javascript
Vue应用部署到服务器的正确方式
2017/07/15 Javascript
一个因@click.stop引发的bug的解决
2019/01/08 Javascript
深入探索VueJS Scoped CSS 实现原理
2019/09/23 Javascript
Vue项目中使用flow做类型检测的方法
2020/03/18 Javascript
浅谈Vue3.0新版API之composition-api入坑指南
2020/04/30 Javascript
详解ES6数组方法find()、findIndex()的总结
2020/05/12 Javascript
微信小程序中data-key属性之数据传输(经验总结)
2020/08/22 Javascript
[38:31]完美世界DOTA2联赛PWL S3 Magma vs GXR 第一场 12.13
2020/12/17 DOTA
深入理解Javascript中的this关键字
2015/03/27 Python
Python Django 实现简单注册功能过程详解
2019/07/29 Python
python脚本执行CMD命令并返回结果的例子
2019/08/14 Python
python中函数返回多个结果的实例方法
2020/12/16 Python
flask框架中的cookie和session使用
2021/01/31 Python
关于HTML5的22个初级技巧(图文教程)
2012/06/21 HTML / CSS
HTML5中的Scoped属性使用实例
2014/04/23 HTML / CSS
前端实现弹幕效果的方法总结(包含css3和canvas的实现方式)
2018/07/12 HTML / CSS
纽约市的奢华内衣目的地:Anya Lust
2019/08/02 全球购物
Hello Molly美国:女性时尚在线
2019/08/26 全球购物
开业庆典策划方案
2014/02/18 职场文书
“四风”查摆问题自我剖析材料
2014/09/27 职场文书
开学第一周值周总结
2015/07/16 职场文书
Python实现socket库网络通信套接字
2021/06/04 Python
Tomcat 与 maven 的安装与使用教程
2022/06/16 Servers
Win11无法安装更新补丁KB3045316怎么办 附KB3045316补丁修复教程
2022/08/14 数码科技