JS继承的几种方式及优缺点
一.原型链继承:
原理:将父类的实例作为子类的原型
function Father(){this.age=10this.phone={first:"华为",second:"小米"}}Father.prototype.getage=function(){return this.age}function Son(name,money){this.name=namethis.money=money}Son.prototype=new Father() //子类型的原型为父类型的一个实例对象Son.prototype.constructor=Son //让子类型的原型的constructor指向子类型Son.prototype.getmoney=function(){return this.money}var son=new Son("小米",1000)//var son2=new Son()console.log(son.age)//10console.log(son.getage())//10console.log(son.name)//小米console.log(son.getmoney())//1000console.log(son instanceof Son)//trueconsole.log(son instanceof Father)//trueson.phone.first="魅族"//更改一个子类的引用属性,其他子类也会受影响console.log(son2.phone.first)//魅族
优点:1.通过子类实例可以直接访问父类原型链上和实例上的成员
2. 相对简单
缺点:1.创建子类实例时,无法向父类构造函数传参
2.父类的所有引用属性
会被所有子类共享,更改一个子类的引用属性,其他子类也会受影响
二.构造函数继承:
原理:在子类构造函数中调用父类构造函数,可以在子类构造函数中使用call()
和apply()
方 法改变this指向
function Father(name,age){this.name=namethis.age={age:age}}Father.prototype.getname=function(){return this.name}function Son(name,age,money){Father.call(this,name,age)//修改Father的thisthis.money=money}Son.prototype.getmoney=function(){return this.money}var son=new Son("小明",12,1000)var son2=new Son("小李",11,999)console.log(son.name)//小明console.log(son.getname())//报错 无法继承父类原型上的属性与方法console.log(son.money)//1000console.log(son.getmoney())//1000console.log(son instanceof Father)//falseconsole.log(son instanceof Son)//trueconsole.log(son.age.age)//12console.log(son2.age.age)//11 父类的引用属性不会被共享
优点:1.可以在子类实例中直接向父类构造函数传参
2.父类的引用属性不会被子类共享
缺点:1.无法继承父类原型上的属性与方法
三.组合继承:
原理:组合上述两种方法就是组合继承。用原型链实现对原型属性和方法的继承,用借用构造函数技术来实现实例属性的继承。
function Father(name,age){this.name=namethis.age={age:age}}Father.prototype.getname=function(){return this.name}function Son(name,age,money){Father.call(this,name,age)//能够看到父类型属性this.money=money}Son.prototype=new Father()//能看到父元素方法Son.prototype.constructor=Son//让子类型的原型的constructor指向子类型Son.prototype.getmoney=function(){return this.money}var son=new Son("小明",12,1000)var son2=new Son("小李",18,1999)console.log(son.name)//小明console.log(son.getname())//小明console.log(son.money)//1000console.log(son.getmoney())//1000console.log(son instanceof Father)//trueconsole.log(son instanceof Son)//trueconsole.log(son.age.age)//12console.log(son2.age.age)//18 父类构造函数中的引用属性不会被共享
优点: 1.可以在子类实例中直接向父类构造函数传参
2. 通过子类实例可以直接访问父类原型链和实例的成员
3.父类构造函数中的引用属性不会被子类共享
缺点:调用了两次supertype构造函数,一次在赋值Son的原型时,一次在实例化子类时call 调用,这次调用会屏蔽原型中的两个同名属性。
四:原型式继承:
原理:利用一个空对象作为中介,将某个对象直接赋值给空对象构造函数的原型。
function object(obj){function F(){}F.prototype=obj//对传入其中的对象执行了一次浅复制,将构造函数F的原型直接指向传入的对象。return new F()}var person={name:"小李",friends:["小米","小兰"],sayname:function(){console.log(this.name)}}var person1=object(person)person1.name="小王"person1.friends.push("小黑")console.log(person1.friends)//['小米', '小兰', '小黑']person1.sayname()//小王var person2=object(person)person2.name="小鱼"person2.friends.unshift("小葵")console.log(person2.friends)// ['小葵', '小米', '小兰', '小黑']person2.sayname()//小鱼console.log(person.friends)//['小葵', '小米', '小兰', '小黑']
缺点: 1.子类实例不能向父类传参
2.父类的所有引用属性
会被所有子类共享
五:寄生式继承
原理: 在原型式继承的基础上,增强对象,返回构造函数
function object(obj){function F(){}F.prototype=objreturn new F()}function createAnother(obj){var clone=object(obj)clone.getname=function(){ //增强对象console.log(this.name)}return clone}var person={name:"小李",friends:["小米","小兰"],}var person1=createAnother(person)person1.friends.push("小黑")person1.name="小红"console.log(person1.friends)// ['小米', '小兰', '小黑']person1.getname()//小红var person2=createAnother(person)console.log(person2.friends)//['小米', '小兰', '小黑']person2.getname()//小李
缺点: 1.子类实例不能向父类传参
2.父类的所有引用属性
会被所有子类共享
(同原型式继承)
六:寄生式组合继承:
原理:结合借用构造函数传递参数和寄生模式实现继承
function object(obj){function F(){}F.prototype=objreturn new F()}function GetPrototype(Father,Son){var prototype=object(Father.prototype) // 创建对象,创建父类原型的一个副本prototype.constructor=Son // 增强对象,弥补因重写原型而失去的默认的constructor 属性Son.prototype=prototype // 指定对象,将新创建的对象赋值给子类的原型}function Father(name){this.name=namethis.color=["blue","pink","black"]}Father.prototype.getname=function(){return this.name}function Son(name,age){Father.call(this,name)this.age=age}GetPrototype(Father,Son) 这一句,替代了组合继承中的Son.prototype = new Father() Son.prototype.getage=function(){return this.age}var son1=new Son("小米",18)var son2=new Son()son1.color.push("green")console.log(son1.getname()) //小米console.log(son1.name) //小米console.log(son1.color) //['blue', 'pink', 'black', 'green']console.log(son2.color) // ['blue', 'pink', 'black']console.log(son1 instanceof Father)//true
优点:1. 只调用一次父类构造函数
2. 子类可以向父类传参
3. 父类方法可以复用
4. 父类的引用属性不会被共享
这是最成熟的方法
七:拷贝继承:
原理:通过遍历复制前一个对象的属性和方法达到拷贝的效果
function Father(){this.name="小明",this.phone={first:"小米",second:"华为"}}Father.prototype.getname=function(){return this.name}function Son(name){var father=new Father()for(var i in father){Son.prototype[i]=father[i]}}var son=new Son()var son2=new Son()son.phone.first="小李"console.log(son.name)//小明console.log(son.getname())//小明console.log(son2.phone.first)//小李console.log(son instanceof Father)//false
缺点:1.效率极低,内存占用高(因为要拷贝父类的属性)
2.无法获取父类不可枚举的方法(for in不能访问到的)
3.父类的所有引用属性
会被所有子类共享
八:ES6 class继承
class Father {constructor(name,age){this.name=namethis.age=age}call(){return "打电话"}}//子类继承父类——语法:class 子类 extends 父类class Son extends Father{constructor(name,age,height){//super在子类的构造方法中调用父类的构造方法super(name,age) //this操作必须放在super后面this.height=height}play(){console.log("玩游戏")}}var son= new Son("小王",16,180)console.log(son.name)//小王console.log(son.call())//打电话console.log(son.height)//180
优点:原理还是参照寄生组合继承,基本原理是一样,语法糖,写起来方便,比较完美
JS继承的几种方式及优缺点相关推荐
- js 继承的几种方式
JS继承的实现方式: 既然要实现继承,那么首先我们得有一个父类,代码如下: function Animal(name) {// 属性this.name = name || '小白';// 实例方法th ...
- js对象:实现继承的几种方式及优缺点
目录 一.原型链继承 二.构造函数继承 三.组合继承(构造函数式继承+原型链继承) 四.拷贝继承(原型式继承) 五.寄生式继承 六.寄生组合式继承 七.使用ES6中class关键字 一.原型链继承 子 ...
- 学习js继承的6种方式
关于原型,原型链,构造函数和实例关系,可以参考上一篇文章 地址:juejin.im/post/5cbfb3- js 实现继承的方式一:原型链继承 function Father(){this.name ...
- JS 总结之原型继承的几种方式
在之前的总结中,我们详细分析了原型<JS 总结之原型>,原型很大作用用于模拟继承,这一次,我们来聊原型继承的几种方式. function Person (age) {this.age = ...
- 可以实现继承的几种方式
继承的几种方式 说起继承,又是一个老生常谈的问题了.今天来讲讲继承的几种方法以及他们的优缺点吧. 源码地址:点击这里 一.原型链继承 原型链继承:通过原型将一个引用类型继承另一个引用类型的属性和方法. ...
- 继承有几种方式,分别是什么,想要实现继承可以使用哪些方法
这里是修真院前端小课堂,每篇分享文从 [背景介绍][知识剖析][常见问题][解决方案][编码实战][扩展思考][更多讨论][参考文献] 八个方面深度解析前端知识/技能,本篇分享的是: [继承有几种方式 ...
- Django中Model继承的三种方式
Django中Model继承的三种方式 Django中Model的继承有三种: 1.抽象继承 2.多表继承 3.proxy model(代理model) 1.抽象继承 第一种抽象继承,创建一个通用父类 ...
- JavaScript系列-02 HTML嵌入js代码的第二种方式
javaScript系列 HTML中嵌入js代码的第二种方式 脚本块的方式 文章目录 javaScript系列 前言 一.了解脚本块的方式 1.1运行规则 二.执行原理 1.编写代码 2.效果 总结 ...
- spring依赖注入的三种方式以及优缺点
spring依赖注入的三种方式以及优缺点 一.依赖注入的三种方式 1.通过构造器注入.(spring4.3之后,推荐使用) 2.通过setter注入.(spring4.3之前,推荐使用) 3通过fil ...
- 在HTML 中嵌入 JS 代码的三种方式
一,在HTML中嵌入JS代码的第一种方式:行间事件 行间事件是指将JavaScript函数写到HTML元素中的执行事件. 1.JavaScript 是一种事件驱动型的编程语言,通常都是在发生某个事件的 ...
最新文章
- 浏览器--如何让登陆页面的表单不默认显示账号和密码
- 招聘|腾讯地图平台部招点云算法工程师
- Faster_RCNN 4.训练模型
- 第三章、Data语意学
- Android自定义XML属性以及遇到的命名空间的问题
- C#中深拷贝对象的简单方法
- 方法参数是结构体指针,报错信息是空指针怎么办
- python 高级面试题_Python高阶面试题
- Java 内存模型 JMM 详解
- 如何写一个pyton模块
- 2017.7.26 奇怪的道路 失败总结
- 创业负债累累 | 失败了的我还如何翻盘?是天台见! 我的故事还只是从这件事开始...
- python编程入门经典-总算理解python编程入门经典教程
- Winfrom窗体无法关闭问题--检查是否存在重写
- Codeforces 837D 动态规划
- 龙果支付 mysql_龙果开源支付系统搭建与部署
- 【笔试题目整理】 网易2018校园招聘数据分析工程师笔试卷
- 安卓逆向——AS开发Xposed插件demo案例
- PHP 编辑器 kindEditor 上传图片失败 解决方案
- 四轮驱动(SSMR)移动机器人手柄控制
热门文章
- Chromium OS源码
- html yy直播,网页YY直播间进入方法 网页YY迷你版怎么用
- 潘多拉网吧防火墙 1.0 双线破解
- 最新最全的微信小程序入门学习教程,微信小程序零基础入门到精通
- 计算机会考excel操作,信息技术会考EXCEL操作题.doc
- mp c2011sp文件服务器,理光Ricoh MP C2011SP驱动
- 多点温度检测上位机显示_基于51单片机的多点温度检测系统设计
- 自从有了OJ水题嗅探神器,麻麻再也不担心我刷不到题了。。
- Android信鸽推送全解
- selenium(三)之webDriver与浏览器版本问题