简介:

因为JS的不是面向对象语言,因此没有接口继承这一东西,但是JS有很多骚操作可以实现继承,继承无非就是子类拥有父类的属性和方法,下面就介绍6种变现实现JS继承的方法

1.最简单的继承实现(原型链)

思路: 一个构造函数的原型指向另一个构造函数的实例
实现

//父类
function SuperType(){this.property = true;
}
//父类的原型定义一个方法getSuperValue() 返回父类里面的property 属性
SuperType.prototype.getSuperValue = function(){return this.property;
};//子类
function SubType(){this.subproperty = false;
}
//子类的原型指向父类的实例
SubType.prototype = new SuperType();//子类的原型定义一个方法getSubValue ()返回子类的属性subproperty
SubType.prototype.getSubValue = function (){return this.subproperty;
};//实例化子类,并且调用父类的getSuperValue()
var instance = new SubType();
alert(instance.getSuperValue()); //true

缺点: 属性完全共享,方法完全共享
这种继承的方式有个缺点就是如果有一个子类修改了父类的方法或者属性,所以的子类都会被影响,我们希望的继承是子类拥有父类的属性和方法并且子类在重写父类的方法或者属性的时候是相互独立的,不会影响到其他子类和父类

function SuperType(){this.colors = ["red", "blue", "green"]; }
function SubType(){
}
//继承了 SuperType
SubType.prototype = new SuperType();var instance1 = new SubType();
instance1.colors.push("black");
//子类 instance1 往继承的父类属性colors添加一个属性导致子类instance2 也共享了
alert(instance1.colors); //"red,blue,green,black"
var instance2 = new SubType();
alert(instance2.colors); //"red,blue,green,black"

2. 借用构造函数

思路: 利用了call函数可以改变某一方法体的this指向和自执行
解决: 解决了上面原型链出现的全部子类共享父类属性和方法,一人改变全部改变的问题
实现

 function SuperType(){this.colors = ["red", "blue", "green"];this.say = function(params){console.log(params)}}function SubType(){// 把SuperType当做一个普通的方法执行在了SubType里面达到继承的目的SuperType.call(this);}var instance1 = new SubType();instance1.colors.push("black");alert(instance1.colors); //"red,blue,green,black"instance1.say('哈哈') ;//哈哈var instance2 = new SubType();alert(instance2.colors); //"red,blue,green" instance2.say('呵呵'); //呵呵

缺点: 虽然是解决了一个修改全部改变的问题,但是新的问题出来了,如果在SuperType的原型定义一个方法,其SubType的实例instance1和instance2都是访问不到
那这样还叫哪门子继承?SuperType完全就沦为了一个公共的方法和属性了,这样我们直接定义一个util不就行了么?搞这些干嘛

3.组合继承

思路: 将原型链和借用构造函数的技术组合到一块,
解决: 用原型链来继承父级原型的方法和属性,用借用构造来继承常规属性和方法
实现:

 //父类function SuperType(name) {this.name = name;this.colors = ["red", "blue", "green"];}//父类原型添加方法SuperType.prototype.sayName = function() {console.log(this.name);};//子类function SubType(name, age) {//借用构造函数方法达到继承父类属性的目的SuperType.call(this, name);this.age = age;}//子类原型指向父类SubType.prototype = new SuperType();//重新子类的构造器指回自己SubType.prototype.constructor = SubType;//子类原型添加方法SubType.prototype.sayAge = function() {console.log(this.age);};console.log('==============instance1===============')var instance1 = new SubType("Nicholas", 29);instance1.colors.push("black");console.log(instance1.colors); //"red,blue,green,black"instance1.sayName(); //"Nicholas";instance1.sayAge(); //29console.log('==============instance2===============')var instance2 = new SubType("Greg", 27);console.log(instance2.colors); //"red,blue,green"instance2.sayName(); //"Greg";instance2.sayAge(); //27

疑惑: 这里有个问题,为什么用了借用构造方法然后instance1.colors,push(‘black’)不会在所有的子类共享了呢?还是回归原型问题,当你访问一个构造函数的变量时,它会优秀访问他自身里面有没有这个属性,没有才会从原型上找,而这里就解释的通了,虽然SuperType里面有个colors属性,但是因为子类自身里面都有colors属性,两者重名所以永远都不会找到原型上,因为自身有这个属性,

优点: 组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优点,成为 JavaScript 中最常用的继
承模式。而且,instanceof 和 isPrototypeOf()也能够用于识别基于组合继承创建的对象。
缺点: 如果我们在父类SuperType添加一个console.log()打印一下会发现父类被实例化了两次,这就造成了浪费问题了,第一次实例在借用构造函数的时候,第二次实例在子类的原型指向父类实例的时候

4. 原型式继承

思路 :利用工厂模式和原型链来实现继承,直接返回一个new过后的构造函数
解决: 算是原型链的代码优化吧
实现:

function object(o){function F(){}F.prototype = o;return new F();} var person = {name: "Nicholas",friends: ["Shelby", "Court"]};var anotherPerson = object(person);anotherPerson.name = "Greg";anotherPerson.friends.push("Rob");console.log(anotherPerson.name);  //Gregconsole.log(anotherPerson.friends); //["Shelby", "Court", "Rob"]var yetAnotherPerson = object(person);yetAnotherPerson.name = "Linda";yetAnotherPerson.friends.push("Barbie");console.log(yetAnotherPerson.name); //Lindaconsole.log(yetAnotherPerson.friends); // ["Shelby", "Court", "Rob", "Barbie"]

缺点: 还是回到了原型链的那个问题,一个修改全部变化,这个唯一的优点就是写法逼格高,而且es5已经实现了这种继承方式的API: Object.create()

6.寄生式继承

思路: 在原型式继承的基础上再添加一个工厂模式,在这个工厂里面定义一些额外的属性和方法
解决: 算是原型式的拓展吧
实现:

 function object(o){function F(){}F.prototype = o;return new F();} //新添加的工厂模式function createAnother(original){var clone = object(original); //通过调用函数创建一个新对象clone.sayHi = function(){ //以某种方式来增强这个对象console.log('hello world')};return clone; //返回这个对象} var person = {name: "Nicholas",friends: ["Shelby", "Court", "Van"]};var anotherPerson = createAnother(person);anotherPerson.sayHi(); //"hi" anotherPerson.friends.push('123456')console.log(anotherPerson.friends) // ["Shelby", "Court", "Van", "123456"]var mily = createAnother(person);console.log(mily.friends) // ["Shelby", "Court", "Van", "123456"]

**缺点:**跟原型式继承一样,优点嘛,我也不知道他的使用场景是什么?解决什么问题

7.寄生组合式继承

思路: 组合继承里面有个很明显的缺点就是我们使用借用构造函数的时候已经把父类的属性和方法都继承过来了,缺点就是没有继承原型上的属性和方法,然后我们使用原型链的方式把原型上的属性和方法继承过来了,也正是如此,我们用了new实例导致父类实例化了两次,并且原型链里面还多了一份我们已经用 了借用构造函数继承得到的方法和属性,因此解决的方法就是不通过new实例父类,直接让子类的原型指向父类的原型就OK了
解决: 解决组合继承中父类被实例化两次造成性能浪费
实现:

 function object(o){function fun(){}fun.prototype = oreturn new fun()}//寄生组合式继承,只见子类的原型指向父类原型的一份数据拷贝//这样子类在修改原型上的属性时也不会出现一人修改全部改变,//简直完美!!!function inheritPrototype(subType, superType){var prototype = object(superType.prototype); //创建对象prototype.constructor = subType; //增强对象subType.prototype = prototype; //指定对象} function SuperType(name){this.name = name;this.colors = ["red", "blue", "green"];console.log('1') //只调用了一次}SuperType.prototype.sayName = function(){alert(this.name);};function SubType(name, age){SuperType.call(this, name);this.age = age;}inheritPrototype(SubType, SuperType);SubType.prototype.sayAge = function(){alert(this.age);}; var SubType1 = new SubType('张三',18)SubType1.colors.push('yellow')console.log(SubType1.colors)//["red", "blue", "green","yellow"]var SubType2 = new SubType('李四',20)console.log(SubType2.colors)//["red", "blue", "green"]

总结: 寄生组合式式继承是最终的版本,比较完美的继承方式,就是代码有点多

阅读JS小红书之继承的六种实现方法相关推荐

  1. 小红书如何种草,有哪些方法和注意事项

    大家好,我是驻海小僧,今天看到这篇文章写的很认真,所以搬过来和大家分享,原作者不详, 了解更多咨询关注公众号 驻海科技 图文类种草是小红书最常见最基础的方式. 举我们曾经做过的一个案例,金稻是一家做美 ...

  2. 小红书怎么涨粉最快?小红书涨粉最快的方法分享

    当下是属于流量时代,而流量是谁贡献的?说到底还是那些粉丝贡献的.换言之,当下是出于一个粉丝经济的时代.既然如此,粉丝数据就变得极为的重要.今天就来分享一下小红书怎么涨粉最快,新手前期如何快速积累自己的 ...

  3. 小红书可以赚钱吗?通过小红书赚钱的几种方式!

    小红书是一个非常受欢迎的社交电商平台,许多人都在上面分享自己的购物体验和生活方式.如果你想通过小红书赚钱,以下是一些方法: 写优质的笔记 小红书上的笔记可以分为各种类别,例如美妆.时尚.旅行等.如果你 ...

  4. 2021年小红书品牌经典爆文拆解

    在小红书品牌种草中,爆文意味着高曝光且能获得持续不断的长尾流量,那么,什么样的内容更有机会成为爆文?通过拆解2021年小红书热门行业下品牌爆文的内容特点,我们为大家总结了小红书爆文打造的趋势和逻辑. ...

  5. 小红书笔记怎么推广?笔记关键词有什么需要注意?

    根据不同的产品,还有品牌的特性和市场情况,小红书有很多对应的推广方法,下面就给大家带来小红书笔记怎么推广?小红书都有哪些推广方式? 一. 小红书笔记怎么推广 1.关键词排名 小红书的系统机制会将笔记贴 ...

  6. 千访 | “霸总”人设揽粉近十万!小红书企业号还能这么玩?

    采访手记:你想象中的小红书企业号是什么样子?是品宣的渠道之一,还是拉近与用户距离的传播媒介? 在小红书做企业号,一直是很多品牌头疼的问题,但最近在短短两个多月时间内,@洁柔纸巾 的官方账号却凭借&qu ...

  7. 小红书如何推广 方法总结

    大家好,我是权知星球,今天来跟大家分享一下小红书如何推广,方法总结. 一.小红书介绍 小红书成立于2013年6月6日,最初的核心业务是社区内容分享.最初分享的主要是美妆和个人护理方面的内容.之后,平台 ...

  8. 小红书如何引流到淘宝店铺,提升产品销量?

    我是由去年开始做小红书引流,一直做到现在,在去年的时候小红书还处于野蛮生长的阶段,在小红书平台获取流量是非常简单的,只要找到爆文笔记模仿就可以出爆款. 但随着小红书规则的完善,单纯的模仿已很难再爆款, ...

  9. 小红书限流原因是什么?怎么不被限流?

    如果经常浏览小红书的用户就会知道,一堆几万播放量的笔记中,突然播放只有几千了,很可能是被限流了,那么就给大家带来小红书限流原因是什么?怎么不被限流? 一.小红书限流原因是什么? 1.一个设备多次登入 ...

最新文章

  1. 一行代码:你的纯文本秒变Markdown
  2. IBatis常见错误集锦
  3. leetcode--872. 叶子相似的树
  4. sqlserver模糊查询不用like_vlookup配合通配符,模糊查询也能很精确,再也不用筛选了...
  5. .net6给winform带来的新功能
  6. 【Java】JDBC连接MySQL驱动
  7. 实践案例丨教你一键构建部署发布前端和Node.js服务
  8. android项目中有哪几种依赖关系,Android Studio项目中三种依赖的添加方式
  9. 【AT91SAM9261EK】u-boot 2022 tftpboot 烧写根文件系统
  10. ps快速制作全屏水印
  11. t3安装找不到主机服务器,T3标准版不能连接服务器的处理方法
  12. 习惯养成android软件,六款有助于养成良好习惯的APP(安卓)
  13. 蛇形走线用在哪里,一文告诉你
  14. 九章量电子计算机诞生于,计算机应用基础统考题
  15. html代码房地产,HTML白色宽屏形式房地产动态网页模板代码
  16. Ruby on Rails的核心特性是什么?
  17. intel芯片内核linux,Linux:再见了Intel 386处理器
  18. ps国画效果案例制作教程和思路介绍
  19. ICV:2022年中国车载摄像头市场规模有望突破50亿美元大关
  20. H5游戏平台创业怎么样?能赚钱吗?

热门文章

  1. m1芯片的macbook使用问题总结
  2. pycharm初体验
  3. 无约束多维极值求解思路
  4. 自学java,学多久可以找到工作?
  5. 前端逼死强迫症之DOM
  6. Kibana【从无到有从有到无】【搜索引擎】【K4】可视化
  7. 计算机专业考博入学考试科目,北京航空航天大学计算机应用技术考博考试科目.doc...
  8. Win10 Hyper-V 固定虚拟机IP地址的方法
  9. 应用上下文请求上下文
  10. 激荡25年的中国互联网发展史(上篇):“互联网” 的群星闪耀时