浅谈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 Array数组对象的扩展函数代码
May 22 Javascript
js下判断 iframe 是否加载完成的完美方法
Oct 26 Javascript
JavaScript判断文件上传类型的方法
Sep 02 Javascript
Javascript的表单验证长度
Mar 16 Javascript
JavaScript来实现打开链接页面的简单实例
Jun 02 Javascript
JS输出空格的简单实现方法
Sep 08 Javascript
jQuery实现右键菜单、遮罩等效果代码
Sep 27 Javascript
基于Vue2.0的分页组件
Mar 16 Javascript
JS关于刷新页面的相关总结
May 09 Javascript
解决vue中虚拟dom,无法实时更新的问题
Sep 15 Javascript
Node.js API详解之 string_decoder用法实例分析
Apr 29 Javascript
js实现轮播图效果 纯js实现图片自动切换
Aug 09 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与PHPExcel冲突解决方法
2011/08/08 PHP
浏览器关闭后,能继续执行的php函数(ignore_user_abort)
2012/08/01 PHP
PHP Directory 函数的详解
2013/03/07 PHP
php5.4以下版本json不支持不转义内容中文的解决方法
2015/01/13 PHP
PHP实现数据分页显示的简单实例
2016/05/26 PHP
Laravel学习教程之从入口到输出过程详解
2017/08/27 PHP
php操作redis数据库常见方法实例总结
2020/02/20 PHP
JavaScript 变量作用域分析
2011/07/04 Javascript
Jquery实现视频播放页面的关灯开灯效果
2013/05/27 Javascript
JS小功能(操作Table--动态添加删除表格及数据)实现代码
2013/11/28 Javascript
jQuery避免$符和其他JS库冲突的方法对比
2014/02/20 Javascript
浅析JavaScript中命名空间namespace模式
2016/06/22 Javascript
关于javascript的一些知识以及循环详解
2016/09/12 Javascript
基于vue实现swipe轮播组件实例代码
2017/05/24 Javascript
js时间戳与日期格式之间转换详解
2017/12/11 Javascript
Angular使用Restful的增删改
2018/12/28 Javascript
JavaScript解析JSON数据示例
2019/07/16 Javascript
微信小程序后台持续定位功能使用详解
2019/08/23 Javascript
微信小程序 SOTER 生物认证DEMO 指纹识别功能
2019/12/13 Javascript
Vue Router的手写实现方法实现
2020/03/02 Javascript
javascript 使用sleep函数的常见方法详解
2020/04/26 Javascript
vuecli3.x中轻松4步带你使用tinymce的步骤
2020/06/25 Javascript
[01:04:05]Mineski vs TNC 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
Python判断字符串与大小写转换
2015/06/08 Python
使用python实现ANN
2017/12/20 Python
python+pandas+时间、日期以及时间序列处理方法
2018/07/10 Python
python 处理telnet返回的More,以及get想要的那个参数方法
2019/02/14 Python
python实现批量注册网站用户的示例
2019/02/22 Python
Python中的Socket 与 ScoketServer 通信及遇到问题解决方法
2019/04/01 Python
python 使用shutil复制图片的例子
2019/12/13 Python
django 解决自定义序列化返回处理数据为null的问题
2020/05/20 Python
CSS3教程(5):网页背景图片
2009/04/02 HTML / CSS
HTML5本地存储和本地数据库实例详解
2017/09/05 HTML / CSS
幼师自我鉴定
2014/02/01 职场文书
心理咨询承诺书
2014/05/20 职场文书
小学生一分钟演讲稿
2014/08/26 职场文书