JavaScript中的几种继承方法示例


Posted in Javascript onDecember 06, 2020

1.原型链继承

原理: 子类原型指向父类实例对象实现原型共享,即Son.prototype = new Father()。

这里先简单介绍下原型

js中每个对象都有一个__proto__属性,这个属性指向的就是该对象的原型。js中每个函数都有一个prototype属性,这个属性指向该函数作为构造函数调用时创建的实例的原型。原型对象上有一个constructor属性,指向创建该对象的构造函数,该属性不可枚举。

var obj = {};
obj.__proto__ === Object.prototype; //true
console.log(Object.prototype.constructor) // ƒ Object

当我们访问一个对象的属性或者方法时,如果找不到,则会通过原型向上寻找,若原型上也未找到,则会去原型的原型上面去找。比如我要调用obj.toString方法时,在自身并未找到toString方法,则会去原型上去寻找,即在Object.prototype上去寻找,找到后运行该方法。

var obj = {};
obj.toString();
obj.__proto__.toString(); //obj.__proto__和Object.prototype指向的是一个对象,自然就能访问Object.prototype上的toString方法啦

注意:原型链的终点是null,使用bind方法返回的函数没有prototype属性。

var obj = {};
function fn(){};
fn.bind(obj).prototype; // undefined
Object.prototype.__proto__; // null

原型链接继承

function Father(age){
 this.age = age;
 this.color = ['red','pink']
}
Father.prototype.sayHello = function(){
 console.log('hello')
} 
function Son(sex){
 this.sex = sex
}
console.log(Son.prototype.constructor) // ƒ Son
Son.prototype = new Father(15) // 原型链继承关键
var son = new Son('男')
son.color.push('black')
var son2 = new Son('女')
son.sayHello() // hello
son.sayHello === son2.sayHello //true
console.log(son2.color) // ['red','pink','black']
console.log(Son.prototype.constructor) // ƒ Father

可以看到通过原型链实现继承,原型上引用类型的值会被所有实例共享。子类的constructor指向会发生改变,而且在创建子类实例时不可以向父类构造函数传递参数。可以手动把子类constructor属性指回其构造函数。

//写法一
Son.prototype.constructor = Son // 这种写法有点缺点,它会让constructor属性变的可以枚举。

//写法二
Object.defineProperty(Son.prototype,'constructor',{
 enumerable:false, // 设置不可枚举
 value:Son
})

2.构造函数继承

原理:在子类构造函数中通过apply或者call调用父类构造函数来继承属性或方法。

function Father(name){
 this.color = ['red']
 this.sayHello = function(){
  console.log('hello')
 }
}
Father.prototype.sayName = function(){
 console.log('zs')
}
function Son(num,name){
 Father.call(this,name) //实现继承的关键代码
 this.num = num
}
var son = new Son(10,'zs')
var son2 = new Son(15,'ls')
son.color.push('pink')
console.log(son2.color) // ['red']
son.sayName() //报错 son.sayName is not a function
console.log(son.sayHello === son2.sayHello) //false

可以看出通过构造函数实现继承,解决了原型链继承不能向父类传参以及引用类型值共享的问题。但这种继承方法却不能访问父类构造函数原型上的方法和属性,而且定义在父类构造函数中的方法也不能复用。

3.组合式继承

组合继承,有时候也叫伪经典继承,它是将原型链继承和构造函数继承结合到一起的一种继承模式。实现思路是通过原型链实现对原型属性和方法的继承,通过借用构造函数实现对实例属性的继承。

function Father(name){
 this.color = ['red']
}
Father.prototype.sayName = function(){
 console.log('zs')
}
function Son(num,name){
 Father.call(this,name) //继承实例属性
 this.num = num
}
Son.prototype = new Father() //继承原型上属性
Son.prototype.constructor = Son
var son = new Son(10,'zs')
var son2 = new Son(15,'ls')
son.color.push('pink')
console.log(son.color,son2.color) //['red','pink'] ['red']
son.sayName() // zs

组合式继承避免了原型链继承和构造函数继承的缺点,融合了它们的优点,成为JavaScript中常用的一种继承模式。

4.寄生式继承

寄生式继承与工厂模式类似,一般用来继承对象。即创建一个封装继承的函数,在函数内部复制一份该对象,对复制的对象进行处理,返回复制的对象。

function createAnother(obj){
  var clone = Object.create(obj)
  clone.name = 'zs'
  clone.sayHello = function(){
   console.log('hello')
  }
  return clone
}
var obj = {age:15}
var newObj = createAnother(obj) // 15
console.log(newObj.name) // zs
newObj.sayHello() // hello

5.寄生组合式继承

前面说到过组合式继承是Javascript中最常用的继承模式,不过这种模式也有自己的不足,它会调用两次父类构造函数。第一次是在将子类原型指向父类实例的时候,第二次是在子类构造函数中调用的。

function Father(name){
  this.name = name
 }
 function Son(num,name){
  Father.call(this,name) // 第二次调用
 }
 Son.prototype = new Father('ls') // 第一次调用
 var son = new Son(10,'zs')
 console.log(son)

在第一次调用的时候,Son.prototype会继承name这个属性,第二次调用时,实例对象会继承name。当我们获取实例对象的name属性时因为实例对象上有该属性,所以是不会去原型上去寻找的,相当于实例对象上的name属性把原型上的name属性给屏蔽掉了,所以原型上的这个属性是多余的。

JavaScript中的几种继承方法示例

为了解决这个问题,就有了寄生组合式继承。主要思路就是创建一个函数完成原型链继承和constructor的指向问题,然后通过构造函数继承属性。

// 复制一个父类的原型指向,将子类的原型指向复制的父类原型,达到不用调用父类构造函数就能继承其原型上的方法的效果。
 function inherit(Sup,Sub){
  var prototype = Object.create(Sup.prototype)
  Sub.prototype = prototype
  prototype.constructor = Sub
 }
 function Father(name){
  this.name = name
 }
 function Son(name){
 Father.call(this,name)
 }
 inherit(Father,Son)
 var son = new Son('zs')
 console.log(son)

JavaScript中的几种继承方法示例

以上就是JavaScript中常用的几种继承方式啦。

到此这篇关于JavaScript中的几种继承方法的文章就介绍到这了,更多相关JavaScript继承方法内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
一个JS的日期格式化算法示例
Jul 31 Javascript
JS将制定内容复制到剪切板示例代码
Feb 11 Javascript
javascript版的in_array函数(判断数组中是否存在特定值)
May 09 Javascript
js获取页面description的方法
May 21 Javascript
Javascript防止图片拉伸的自适应处理方法
Dec 26 Javascript
webpack打包js的方法
Mar 12 Javascript
Vue进度条progressbar组件功能
Apr 17 Javascript
小程序实现展开/收起的效果示例
Sep 22 Javascript
在antd4.0中Form使用initialValue操作
Nov 02 Javascript
解决vux 中popup 组件Mask 遮罩在最上层的问题
Nov 03 Javascript
用webAPI实现图片放大镜效果
Nov 23 Javascript
js 数据类型判断的方法
Dec 03 Javascript
js调用网络摄像头的方法
Dec 05 #Javascript
浅谈Vue使用Elementui修改默认的最快方法
Dec 05 #Vue.js
vue+element_ui上传文件,并传递额外参数操作
Dec 05 #Vue.js
JavaScript实现浏览器网页自动滚动并点击的示例代码
Dec 05 #Javascript
解决vue下载后台传过来的乱码流的问题
Dec 05 #Vue.js
js获取图片的base64编码并压缩
Dec 05 #Javascript
js重写alert事件(避免alert弹框标题出现网址)
Dec 04 #Javascript
You might like
解析thinkphp基本配置 convention.php
2013/06/18 PHP
php第一次无法获取cookie问题处理
2014/12/15 PHP
yii2实现Ueditor百度编辑器的示例代码
2018/11/02 PHP
jQuery 学习 几种常用方法
2009/06/11 Javascript
jquery isEmptyObject判断是否为空对象的函数
2011/02/14 Javascript
javascript针对DOM的应用分析(四)
2012/04/15 Javascript
情人节单身的我是如何在敲完代码之后收到12束玫瑰的(javascript)
2015/08/21 Javascript
15个常用的jquery代码片段
2015/12/19 Javascript
如何在JS中实现相互转换XML和JSON
2016/07/19 Javascript
详细总结Javascript中的焦点管理
2016/09/17 Javascript
微信小程序去哪里找 小程序到底如何使用(附小程序名单)
2017/01/09 Javascript
js实现带进度条提示的多视频上传功能
2020/12/13 Javascript
浅析webpack 如何优雅的使用tree-shaking(摇树优化)
2017/08/16 Javascript
Vuex modules模式下mapState/mapMutations的操作实例
2019/10/17 Javascript
[01:04:35]2018DOTA2亚洲邀请赛 4.3 突围赛 Secret vs VG 第一场
2018/04/04 DOTA
Hadoop中的Python框架的使用指南
2015/04/22 Python
python八皇后问题的解决方法
2018/09/27 Python
python中pika模块问题的深入探究
2018/10/13 Python
python实现翻译word表格小程序
2020/02/27 Python
python使用梯度下降算法实现一个多线性回归
2020/03/24 Python
html5 canvas fillRect坐标和大小的问题解决方法
2014/03/26 HTML / CSS
英国最受欢迎的价格比较网站之一:MoneySuperMarket
2018/12/19 全球购物
信息管理员岗位职责
2013/12/01 职场文书
奶茶店创业计划书范文
2014/01/17 职场文书
前处理组长岗位职责
2014/03/01 职场文书
清明节网上祭英烈活动总结
2014/04/30 职场文书
我爱我的祖国演讲稿
2014/05/04 职场文书
全运会口号
2014/06/20 职场文书
小学生读书活动总结
2014/06/30 职场文书
平面设计专业求职信
2014/08/09 职场文书
农林经济管理专业自荐信
2014/09/01 职场文书
无房产证房屋转让协议书合同样本
2014/10/18 职场文书
优秀教师事迹材料
2014/12/15 职场文书
高中教师个人工作总结
2015/02/10 职场文书
python保存图片的四个常用方法
2022/02/28 Python
关于Nginx中虚拟主机的一些冷门知识小结
2022/03/03 Servers