摘要:导读中主要有三种实现继承的方式,分别是构造函数继承原型继承组合继承其中前两种方式都有其缺陷。方法使用原型继承避免了构造函数继承中方法重复拷贝浪费内存的缺陷。
导读
JavaScript中主要有三种实现继承的方式,分别是
构造函数继承
原型继承
组合继承
其中前两种方式都有其缺陷。第三种方式组合继承则将前两种方式结合起来,取长补短,是JS继承最常用的最佳实践。本文结合代码和注释逐一阐述三种继承方式。
构造函数继承构造函数继承的关键: 在Child构造函数中执行Parent.call(this)。
function Parent(name) { this.name = name; this.hobby = []; this.speak = function() { console.log("Parent speak"); } // 缺点1:new多个Child时,Parent构造函数中的方法会在每个Child中拷贝一份,浪费内存 } Parent.prototype.say = function() { console.log("Parent say"); } // 缺点2:Parent原型对象上的方法不会被Child继承 function Child(name, type) { Parent.call(this, name); // 构造函数继承的关键 this.type = type; }原型继承
原型继承的关键: 设置Child原型指向ParentChild.prototype = new Parent()。
function Parent(name) { this.name = name; this.hobby = []; // 缺点:Parent的引用属性会被所有Child实例共享,互相干扰 } Parent.prototype.say = function() { console.log("Parent say"); } function Child(type) { this.type = type; } Child.prototype = new Parent(); // 原型继承的关键组合继承(最佳实践)
组合继承的关键:
属性使用构造函数继承 —— 避免了原型继承中Parent引用属性被所有Child实例共享的缺陷。
方法使用原型继承 —— 避免了构造函数继承中方法重复拷贝、浪费内存的缺陷。
function Parent(name) { this.name = name; this.hobby = []; // 属性放在构造函数中 } Parent.prototype.say = function() { // 方法放在原型中 console.log("Parent say"); } function Child(name, type) { Parent.call(this, name); // Child继承Parent属性(构造函数继承) this.type = type; // Child扩展属性 } Child.prototype = Object.create(Parent.prototype); // Child继承Parent方法(原型继承) Child.prototype.speak = function() { // Child扩展方法 console.log("Child speak"); } Child.prototype.constructor = Child; // 修复Child的constructor指向,否则Child的constructor会指向Parent
补充:
对于组合继承代码中的Child.prototype = Object.create(Parent.prototype),还有两种常见的类似写法是Child.prototype = Parent.prototype和Child.prototype = new Parent(),但这两种写法都是有缺陷的,需要避免:
Child.prototype = Parent.prototype,修改Child.prototype就等于修改Parent.prototype,会干扰所有Parent实例。
Child.prototype = new Parent(),Parent构造函数重复调用了两次(另一处调用是Child构造函数中的Parent.call(this)),浪费效率,且如果Parent构造函数有副作用,重复调用可能造成不良后果。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/98009.html
摘要:前言重新梳理一下发现以前说的有问题顺便比较两两写法之间的差异性使用对象字面量表示法函数字面量运行时间嵌套函数字面量调用方法函数字面量运行时间函数字面量运行时间使用操作符后跟构造函数详情可参考关于中的运算符构造函数与原型链一些理解构造函数原型 前言 PS:2018/04/14: 重新梳理一下发现以前说的有问题,顺便比较两两写法之间的差异性. 1、使用对象字面量表示法 console.ti...
摘要:下面我们通过代码来看一下实现和区别三种实现继承,重写方法实现接口,实现方法实现接口,实现方法,带有返回值和异常如何使用第一种实现方式第二种实现方式第三种实现从代码可以看出以上提到的区别,,。第二种方式并没有体现共用同一个。 Java实现线程的三种方式和区别 Java实现线程的三种方式: 继承Thread 实现Runnable接口 实现Callable接口 区别: 第一种方式继承T...
摘要:对象的构造函数用于创建特定类型的对象既要准备使用对象,也要接收参数,构造函数在创建对象时可以用来设置成员属性和方法的值。 在经典的面向对象编程语言中,constructor是一个特殊的方法,被用来初始化一个新建的对象,一旦该对象被分配内存话。 在JavaScript中几乎所有的东西都是一个对象,然而常常引起我们兴趣的是对象的constructor。 对象的构造函数用于创建特定类型的对象...
摘要:面试题增强一个对象的方法的三种方式继承使用这种方式必须满足的条件是被增强的方法的所在类能被继承,并且这个对象已经明确知道。所以创建一个类继承重写了父类的方法增强了,变成飞了。。。 面试题:增强一个对象的方法的三种方式 1. 继承 使用这种方式必须满足的条件是:被增强的方法的所在类能被继承,并且这个对象已经明确知道。 举例: 有一个接口Person,里面有一个方法run() pack...
摘要:与执行环境相关的变量对象中有执行环境定义的所有变量和函数作用域链代码在一个环境中执行,便会创建变量对象的一个作用域链。 执行环境 执行环境是什么? javascript的解释器每次开始执行一个函数时,都会为每个函数创建一个执行环境(execution context)。 执行环境定义了变量或者函数有权访问的其他数据,决定了他们各自的行为。 与执行环境相关的变量对象(...
阅读 2353·2021-10-09 09:44
阅读 2050·2021-10-08 10:05
阅读 3391·2021-07-26 23:38
阅读 2915·2019-08-28 18:16
阅读 754·2019-08-26 11:55
阅读 1774·2019-08-23 18:29
阅读 1985·2019-08-23 18:05
阅读 1323·2019-08-23 17:02