摘要:这又是什么呢这个相对之前的比较复杂,但是高效的一点是只调用一次被继承者构造函数原理就是通过寄生方式创建一个被继承者的副本,副本和被继承者共用一个这样就解决了之前的问题返回的一个副本设置指向因为新副本的原型对象被重写副本作为的原型对象
前言
我们学JAVA的时候说到继承就是一个extends ClassName的事情,但是在JS的世界里继承和我们在JAVA所认识的继承实现方法又有一些不同,你们真的了解JS的继承吗?就当你们很了解了,毕竟是基础知识,我就简单说说
原型链继承简言之就是把被继承的对象赋值给继承者的原型对象
function Super() { this.name = "mirok"; } Super.prototype.showName = function () { console.log(this.name); } function Sub() { this.name = "july"; } Sub.prototype = new Super(); const obj = new Sub(); obj.showName(); //输出july
原型实现继承虽然可以,但是也有相应的弊端,例如new Super()构建多个实例,继承里面的方法被其中一个实例重写,就会影响其他实例,也就是说原型里的是所有实例所共享的,这是我们不愿看到的,因此就有以下的方法。
借用构造函数简言之就是在继承者的构造函数中去调用被继承者的构造函数(即使用apply()/call()实现)
function Super() { this.supername = "mirok"; } function Sub() { Super.call(this) this.name = "july"; } Sub.prototype = new Super(); const obj = new Sub(); obj.name; //july obj.supername; //mirok
这种方式实现的继承相对于之前的来说不仅解决了之前的问题还能向被继承者传参数,但是也有一定的弊端,即容易覆盖本身的属性,解决方法就是在调用被继承者的构造函数再对自己添加属性,也就是说上面的Super.call要在this.name定义属性之前。另一个弊端就是继承的是无法共享的
组合继承这个就是组合前面的原型链继承和借用构造函数继承两者之长,也就是说既能在继承后的实例都有一份属性又能共用
function Super() { this.name = "mirok"; } Super.prototype.showName = function () { console.log(this.name); } function Sub1() { Super.call(this); this.name = "july"; } function Sub2() { Super.call(this); this.name = "deny"; } Sub1.prototype = new Super(); Sub2.prototype = new Super(); const obj1 = new Sub1(); const obj2 = new Sub2(); obj1.showName(); // july obj2.showName(); // deny原型式继承
这个比较特殊一点,就是在一个函数里去做原型链继承的事情
function object(obj) { function fun() {}; fun.prototype = obj; return new fun(); }
ES5规范了这类写法,就是Object.create(),但是弊端和第一种类似,因为不是我们理想的继承这里就不详细介绍
寄生式继承这个也比较特殊,就是把继承的事情放在一个函数里去做,再把对象返回
function object(obj) { function fun() {}; fun.prototype = obj; return new fun(); } function factory() { const person = {name:"mirok", age: 22}; const obj = object(person); obj.show = function() {console.log(this.name)} return obj; } factory().show(); //"mirok"
至于弊端可见而知,不能实现共享
寄生组合式继承组合继承有个弊端就是会调用两次被继承者的构造函数,解决方法就是使用寄生组合式继承。这又是什么呢?这个相对之前的比较复杂,但是高效的一点是只调用一次被继承者构造函数,原理就是通过寄生方式创建一个被继承者的副本,副本和被继承者共用一个prototype,这样就解决了之前的问题
function object(obj) { function fun() {}; fun.prototype = obj; return new fun(); } function factory(Sub, Super) { var proto = object(Super.prototype); //返回Super的一个副本 proto.constructer = Sub; //设置constructor指向, 因为新副本的原型对象被重写 Sub.prototype = proto; //副本作为sub的原型对象 } function Super () { this.name = "july"; } Super.prototype.show = function () { console.log(this.name); } function Sub1 () { Super.call(this); this.name = "mirok" } function Sub2 () { Super.call(this); this.name = "deny" } factory(Sub1, Super); factory(Sub2, Super); var obj1 = new Sub1(); var obj2 = new Sub2(); obj1.show(); // mirok obj2.show(); // deny
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/96757.html
摘要:前言还记得当初用语言写各种数据结构的苦逼时代嘛,但是用来实现栈和队列是如此的简单啊,但是你们真的了解用模拟栈和队列,就当你们真的很了解了,毕竟是基础知识,我就写几个案例,不喜勿喷栈栈方法栈就是先进后出,就是如此便捷就可以简单实现栈队列队列是 前言: 还记得当初用C语言写各种数据结构的苦逼时代嘛,但是用JS来实现栈和队列是如此的简单啊,但是你们真的了解用js模拟栈和队列,就当你们真的很了...
摘要:我们知道创建了一个函数就带了一个属性,创建一个实例就带着一个指针,这个指针是实例和构造函数的原型对象间的联系,这个指针在脚本中是不可见的,也就是你不能访问的,但是在和中,提供了来支持访问,这么一说,相信大家应该能明白吧 前言 一般我们看到prototype就会下意识的说这不就是原型对象嘛?但是你们真的了解prototype嘛?就当你们很了解了,毕竟是基础知识,我就简单说说 正文 先说说...
摘要:使用原型链实现对原型属性和方法的继承,用借用构造函数模式实现对实例属性的继承。 我们之前介绍了javascript面向对象的封装的相关内容,还介绍了js的call方法,今天开始讨论js的继承这篇文章参考了《javascript高级程序设计》(第三版),但内容不局限于,网上很多关于js继承的相关内容都是来自于这本书,有兴趣的同学可以翻阅查看 原型链继承 我们先通过一个栗子,了解一下原型链...
摘要:前言函数传参我们天天都在用,但是你们真的了解嘛就当你们很了解了,毕竟是一些基础的东西,我就写几个例子,不喜勿喷。 前言 函数传参我们天天都在用,但是你们真的了解嘛?就当你们很了解了,毕竟是一些基础的东西,我就写几个例子,不喜勿喷。 例子 demo1: var obj = {name: mirok} function demo1(obj) { obj.name = july }...
摘要:面试官要不你来手写下单例模式呗候选者单例模式一般会有好几种写法候选者饿汉式简单懒汉式在方法声明时加锁双重检验加锁进阶懒汉式静态内部类优雅懒汉式枚举候选者所谓饿汉式指的就是还没被用到,就直接初始化了对象。面试官:我看你的简历写着熟悉常见的设计模式,要不你来简单聊聊你熟悉哪几个吧?候选者:常见的工厂模式、代理模式、模板方法模式、责任链模式、单例模式、包装设计模式、策略模式等都是有所了解的候选者:...
阅读 1789·2021-08-19 11:12
阅读 1373·2021-07-25 21:37
阅读 946·2019-08-30 14:07
阅读 1240·2019-08-30 13:12
阅读 622·2019-08-30 11:00
阅读 3501·2019-08-29 16:28
阅读 954·2019-08-29 15:33
阅读 2926·2019-08-26 13:40