js继承:一网打尽js继承 刺骨的言语ヽ痛彻心扉 2022-03-12 07:24 240阅读 0赞 转载:原地址:[https://mp.weixin.qq.com/s/NkxW367Znl5Hb47\_vv8Eeg][https_mp.weixin.qq.com_s_NkxW367Znl5Hb47_vv8Eeg] 继承方式知多少 过完年,马上又到了金三银四的季节,这段时间无论是身经百战的老鸟,还是在程序界中杀个七进七出的高手,抑或是菜鸟都在这段时间内,疯狂的恶补自己的知识面,以便于在跳槽的时候拿到一个称心如意的offer —— 而js继承不必说必然是一个非常高频的基础面试题 说它基础是因为绝大部分都能说出几点来,接下来我就带大家全面的回顾一下这个知识点 JS是一种弱类型的面向对象语言(抽象,封装,继承,多态),所以在实现继承上还是一如既往的灵活 ![在这里插入图片描述][20190305151819231.png] 1//父类 2 function Person(name) \{ 3 [this.name][] = name || ‘无名’ 4 this.sayHello = function () \{ 5 console.log('hello everyBody i am ’ + [this.name][]) 6 \} 7 \} 8 Person.prototype.doWork = function (work) \{ 9 console.log([this.name][] \+ ‘的工作是–’ + work) 10 \} ES5继承 第一种 —— 原型继承 原型继承基本上是人人都会的功能无非就是 将父类的实例当作子类的原型, 其中牵扯到的知识点有两个 this的指向 原型的链条继承 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0NTA4NTMw_size_16_color_FFFFFF_t_70] 1 //子类 2 function Teacher() \{\} 3 Teacher.prototype = new Person(‘张三’) 4 5 var ls = new Teacher() 6 console.log([ls.name][]) // 张三 7 ls.sayHello() //hello everyBody i am 张三 8 ls.doWork(‘教师’) //张三的工作是–教师 9 10 var zs = new Teacher() 11 console.log([zs.name][]) // 张三 12 zs.sayHello() //hello everyBody i am 张三 13 zs.doWork(‘教师’) //张三的工作是–教师 14 优点: 简单,只要是父类原型上的方法和属性都可以访问使用 缺点: 优点即缺点,多个子类实例共享父类的属性 实例不能传参 即 var lisi = new Teacher(‘李四’),参数李四不会传到父类,输出依然是张三 不能实现多继承(多继承是指继承多个父类) 第二种 —— 通过构造函数继承 通过call来调用父类构造函数,所以每一个子类都会有一个父类实例的副本 知识点 通过call实现对象冒充 ![在这里插入图片描述][20190305151906701.png] 1//子类 2 function Teacher(name) \{ 3 Person.call(this,name) 4 [this.name][] = name || ‘无名’ 5 \} 6 7 var zs = new Teacher(‘张三’) 8 console.log([zs.name][]) 9 zs.sayHello() 10 zs.doWork(‘教师’) //报错 优点 通过call实现后,子类的实例拷贝的是父类的副本,不存在属性共享的问题 可实现多继承,通过多个call调用 缺点 优点类似于拷贝赋值,所以实例化的对象只是子类的实例,而不是父类的实例 无法复用父类原型链上的方法 第三种 拷贝继承 这个有点类似于上面,就是把父类的实例化遍历,通过赋值的方式赋值给子类的原型 ![在这里插入图片描述][20190305151927789.png] 1 //子类 2 function Teacher(name) \{ 3 var example = new Person(); 4 for(var p in example)\{ 5 Teacher.prototype\[p\] = example\[p\]; 6 \} 7 [Teacher.prototype.name][] = name || ‘Tom’; 8 \} 优点 可实现多继承,即把多个父类的实例化通过遍历的方式赋值给子类 缺点 麻烦,因为要遍历父类原型占用内存高 第四种 —— 把父类的实例当作子类返回值 通过实例化父类,然后为这个实例添加新的属性 ![在这里插入图片描述][20190305151948339.png] 1//子类 2 function Teacher(name) \{ 3 let example = new Person() 4 [example.name][] = name || ‘无名’ 5 return example 6 \} 7 8 var zs = new Teacher(‘张三’) 9 console.log([zs.name][]) 10 zs.sayHello() 11 zs.doWork(‘教师’) 优点 因为有return返回的值所以不管是new Teacher()还是函数调用Teacher()返回的结果是一样的 缺点 因为返回的是父类的实例,所以实例化对象zs只是父类的实例,不是子类的实例 不能实现多继承 小结一下 上面的四种方法都各有自己的优缺点,但是总体来看要么是不全面要么是麻烦或者占内存,一般在开发中不建议这样使用,但是也根据你自己的实际情况,比如上面的某个方式很符合你的业务场景,而又不考虑扩展之类的其它东西,也是可以使用的 当然除了这些,js发展了这么多年肯定是有比上面四种更好的方法,我们接着介绍 第五种 —— 组合继承(构造 + 实例)继承 通过call拷贝来父类的属性给子类使用,并且通过原型链的方式实现原型链的继承 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0NTA4NTMw_size_16_color_FFFFFF_t_70 1] 1//子类 2 function Teacher(name) \{ 3 Person.call(this,name) 4 [this.name][] = name || ‘无名’ 5 \} 6 7 Teacher.prototype = Object.create(Person.prototype) 8 Teacher.prototype.constructor = Teacher 9 10 var zs = new Teacher(‘张三’) 11 console.log([zs.name][]) 12 zs.sayHello() 13 zs.doWork(‘教师’) 优点 解决了构造继承和原型继承的缺点 缺点 调用了两次父类的构造,生成了两份实例 第六种 寄生组合式继承 这种方式可以理解为第五种方法的优化 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0NTA4NTMw_size_16_color_FFFFFF_t_70 2] 1//子类 2function Teacher(name) \{ 3 Person.call(this,name) 4 [this.name][] = name || ‘无名’ 5 \} 6 (function()\{ 7 let Example = function()\{\}; 8 Example.prototype = Person.prototype; 9 Teacher.prototype = new Example(); 10 Teacher.prototype.constructor = Teacher 11 \})(); 12 13 14 var zs = new Teacher(‘张三’) 15 console.log([zs.name][]) 16 zs.sayHello() 17 zs.doWork(‘教师’) 优点 堪称完美 缺点 有点复杂 ES6 继承 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0NTA4NTMw_size_16_color_FFFFFF_t_70 3] 1 class Person\{ 2 constructor(name)\{ 3 [this.name][] = name 4 \} 5 sayName()\{ 6 console.log('my name is ’ + [this.name][]) 7 \} 8 \} 9 class Teacher extends Person\{ 10 constructor(name)\{ 11 super() 12 [this.name][] = name 13 \} 14 \} 15 console.log(new Teacher(‘zs’)) 16 new Teacher(‘zs’).sayName() 子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工,如果不调用super方法,子类就得不到this对象。因此,只有调用super之后,才可以使用this关键字 底层实现:一个继承语句同时存在两条继承链:一条实现属性继承,一条实现方法的继承 1class A extends B\{\} 2A.**proto** === B; //继承属性 3A.prototype.**proto** == B.prototype;//继承方法 从上面可以看到不管是ES5还是ES6继承的基本实现方式是一样的,我想这就是所谓的万变不离其宗吧 如果有错误的地方 欢迎指正批评 [https_mp.weixin.qq.com_s_NkxW367Znl5Hb47_vv8Eeg]: https://mp.weixin.qq.com/s/NkxW367Znl5Hb47_vv8Eeg [20190305151819231.png]: /images/20220312/6a565ef0aa0d45139dde87e978cb6110.png [this.name]: http://this.name [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0NTA4NTMw_size_16_color_FFFFFF_t_70]: /images/20220312/4d653485da6b48ceb83bbf5cccfb0c94.png [ls.name]: http://ls.name [zs.name]: http://zs.name [20190305151906701.png]: /images/20220312/f10254af491e456eb40798d7a9e27492.png [20190305151927789.png]: /images/20220312/a9d8efb6c8fc449ba983919cb7b9a6fb.png [Teacher.prototype.name]: http://Teacher.prototype.name [20190305151948339.png]: /images/20220312/336edd1ca7504105877ac66842dd4bdc.png [example.name]: http://example.name [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0NTA4NTMw_size_16_color_FFFFFF_t_70 1]: /images/20220312/3eba070f82864de29fca07ca0b72dbf5.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0NTA4NTMw_size_16_color_FFFFFF_t_70 2]: /images/20220312/40872f3c92464f80bc391fde5fbd951d.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0NTA4NTMw_size_16_color_FFFFFF_t_70 3]: /images/20220312/e6e54ebc8137445eae055e0dd159359c.png
相关 js 继承 注意点: > 1. 原型链上的属性会被多个对象共享 > 2. 为某一个类添加静态方法,直接`构造函数名称.函数名=function(){}`,调用时直接通过`构造... 柔光的暖阳◎/ 2024年04月18日 16:57/ 0 赞/ 62 阅读
相关 JS继承 1.原型链继承 2.借用构造函数继承(经典继承) 3.组合继承 4.原型式继承 5.寄生式继承 6.寄生组合式继承 既然要实现继承,那么首先我们得有一个父 ゞ 浴缸里的玫瑰/ 2022年12月05日 00:50/ 0 赞/ 172 阅读
相关 js 继承 $(document).ready(initPage); function initPage() { extend(C - 日理万妓/ 2022年07月21日 02:20/ 0 赞/ 194 阅读
相关 js--继承 每个类有3部分, 第一部分是构造函数内的,供实例化对象复制用的 第二部分是构造函数外的,直接通过点语法添加,这是供类使用的,实例化对象访问不到 第三部分是类的原型中 ╰半夏微凉°/ 2022年07月11日 01:47/ 0 赞/ 193 阅读
相关 js继承 1、prototype方式 var BaseClass = function () \{ this.name = "3zfp"; ゞ 浴缸里的玫瑰/ 2022年06月09日 04:08/ 0 赞/ 173 阅读
相关 js继承:一网打尽js继承 转载:原地址:[https://mp.weixin.qq.com/s/NkxW367Znl5Hb47\_vv8Eeg][https_mp.weixin.qq.com_s_Nkx 刺骨的言语ヽ痛彻心扉/ 2022年03月12日 07:24/ 0 赞/ 241 阅读
相关 js继承 var animal=function(name){ //构造函数 this.name=name; this.sayhe 拼搏现实的明天。/ 2021年12月22日 02:43/ 0 赞/ 264 阅读
相关 js-----继承 1:创建的三种方式 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ub 曾经终败给现在/ 2021年09月20日 06:56/ 0 赞/ 359 阅读
相关 js继承 为何要继承 希望子类对象拥有父类的属性和方法 构造函数的继承 call写在子类构造函数中,将父构造函数中this指向由window指向子对象,并且执行父构造函数中 傷城~/ 2021年09月03日 06:53/ 0 赞/ 403 阅读
还没有评论,来说两句吧...