一、对象冒充

其原理如下:构造函数使用 this 关键字给所有属性和方法赋值(即采用类声明的构造函数方式)。因为构造函数只是一个函数,所以可使 Parent 构造函数 成为 Children 的方法,然后调用它。Children 就会收到 Parent 的构造函数中定义的属性和方法。例如,用下面的方式定义 Parent 和 Children:


]// 父类构造函数
var Parent = function(name){this.name = name;this.sayHi = function(){console.log("Hi! " + this.name + ".");}//前端全栈学习交流圈:866109386
};//面向1-3年前端人员
//帮助突破技术瓶颈,提升思维能力
// 子类构造函数
var Children = function(name){this.method = Parent;this.method(name); // 实现继承的关键delete this.method;this.getName = function(){console.log(this.name);}
};var p = new Parent("john");
var c = new Children("joe");p.sayHi(); // 输出: Hi! john.
c.sayHi(); // 输出: Hi! joe.
c.getName(); // 输出: jo

原理:就是把 Parent 构造函数放到 Children 构造函数里面执行一次。那为什么不直接执行,非要转个弯把 Parent 赋值给 Children 的 method 属性再执行呢? 这跟 this 的指向有关,在函数内 this 是指向 window 的。当将 Parent 赋值给 Children 的 method 时, this 就指向了 Children 类的实例。

二、原型链继承

众所周知,JavaScript 是一门基于原型的语言,在 JavaScript 中 prototype 对象的任何属性和方法都被传递给那个类的所有实例。原型链利用这种功能来实现继承机制:


// 父类构造函数
var Parent = function(){this.name = "john";this.sayHi = function(){console.log("Hi! " + this.name + ".");}
};// 子类构造函数
var Children = function(){};Children.prototype = new Parent(); // 实现继承的关键var p = new Parent();
var c = new Children();p.sayHi(); // 输出: Hi! john.
c.sayHi(); // 输出: Hi! john.

注意:调用 Parent 的构造函数,没有给它传递参数。这在原型链中是标准做法。要确保构造函数没有任何参数。

三、使用 call 或 applay 方法

这个方法是与对象冒充方法最相似的方法,因为它也是通过改变了 this 的指向而实现继承:


// 父类构造函数
var Parent = function(name){this.name = name;this.sayHi = function(){console.log("Hi! " + this.name + ".");}
};// 子类构造函数
var Children = function(name){Parent.call(this, name); // 实现继承的关键this.getName = function(){console.log(this.name);}
};var p = new Parent("john");
var c = new Children("joe");p.sayHi(); // 输出: Hi! john.
c.sayHi(); // 输出: Hi! john.
c.getName(); // 输出: joe

apply 方法本人就不举列了,它和 call 方法的区别在于它的第二个参数必须是数组。

四、混合方式

对象冒充的主要问题是必须使用构造函数方式,这不是最好的选择。不过如果使用原型链,就无法使用带参数的构造函数了。如何选择呢?答案很简单,两者都用。 在 JavaScript 中创建类的最好方式是用构造函数定义属性,用原型定义方法。这种方式同样适用于继承机制:


// 父类构造函数
var Parent = function(name){this.name = name;
};Parent.prototype.sayHi = function(){console.log("Hi! " + this.name + ".");
};// 子类构造函数
var Children = function(name, age){Parent.call(this, name); // 实现继承的关键this.age = age;
};Children.prototype = new Parent(); // 实现继承的关键Children.prototype.getAge = function(){console.log(this.age);
};//前端全栈开发交流圈:866109386
//帮助1-3年前端人员突破技术瓶颈,提升思维
var p = new Parent("john");
var c = new Children("joe",30);p.sayHi(); // 输出: Hi! john.
c.sayHi(); // 输出: Hi! joe.
c.getAge(); // 输出: 30

五、使用Object.create 方法

Object.create 方法会使用指定的原型对象及其属性去创建一个新的对象:


// 父类构造函数
var Parent = function(name){this.name = name;
};Parent.prototype.sayHi = function(){console.log("Hi! " + this.name + ".");
};// 子类构造函数
var Children = function(name, age){Parent.call(this, name); // 实现继承的关键this.age = age;
};Children.prototype = Object.create(Parent.prototype); // 实现继承的关键
Children.prototype.constructor = children; // @Children.prototype.getAge = function(){console.log(this.age);
};var p = new Parent("john");
var c = new Children("joe",30);p.sayHi(); // 输出: Hi! john.
c.sayHi(); // 输出: Hi! joe.
c.getAge(); // 输出: 30

@ 当执行 Children.prototype = Object.create(Parent.prototype) 这个语句后,Children 的 constructor 就被改变为 Parent ,因此需要将 Children.prototype.constructor 重 新指定为 Children 自身。

六、extends 关键字实现继承

这个是 ES6 的语法糖,下面看下es6实现继承的方法:


class Parent {constructor(name, age) {this.name = name;this.age = age;}
}class Children extends Parent {constructor(name, age, job) {this.job = job; // 这里会报错super(name, age);this.job = job; // 正确}
}

上面代码中,子类的constructor方法没有调用super之前,就使用this关键字,结果报错,而放在super方法之后就是正确的。子类Children的构造函数之中的super(),代表调用父类Parent的构造函数。这是必须的,否则 JavaScript 引擎会报错。

注意,super虽然代表了父类Parent的构造函数,但是返回的是子类Children的实例,即super内部的this指的是Children,因此super()在这里相当于Parent.prototype.constructor.call(this)。

原文链接:https://my.oschina.net/u/3970421/blog/2872629

转载于:https://www.cnblogs.com/lovellll/p/10245931.html

JavaScript对象继承方式相关推荐

  1. JavaScript六种继承方式的递进推演

    1. 原型链继承 function Parent1() {this.name = "Parent1"this.son = [1] } // 需要继承的子类 function Chi ...

  2. Javascript 对象继承 原型链继承 对象冒充 call 混合方式

    一.原型链继承 function ClassA() {} ClassA.prototype.color = "blue"; ClassA.prototype.sayColor = ...

  3. jQuery-源码阅读,JavaScript原生继承方式与jQuery中的继承

    JavaScript中继承方法有以下几种: 1.原型链继承: function Book (name,author){this.name=name;this.author=author;}Book.p ...

  4. 实现javascript对象继承的完美方式 圣杯模型

    直接上代码:不多说,hhh: 封装成函数,实现功能的实例化 我们要养成抽象实例的能力; 继承–>extend();inherit(); 继承的方法更加适合工业化 这种方法叫做共享原型 Fathe ...

  5. javascript --- 对象的方式体验链式调用

    将功能相近的方法写入同一个对象中,是一个很好的编程习惯,便于后期的维护和前期的开发. foo1 var fooObj = {foo1: function() {console.log('foo1'); ...

  6. JavaScript 对象继承

    原型继承: 这种原型继承的特点:既继承了父类的模板,又继承了父类的原型对象.优点是继承了父类的模板,     又继承了父类的原型对象,缺点就是父类实例传参,不是子类实例化传参,不符合常规语言的写法. ...

  7. Javascript中的几种继承方式比较

    原文地址 开篇 从'严格'意义上说,javascript并不是一门真正的面向对象语言.这种说法原因一般都是觉得javascript作为一门弱类型语言与类似java或c#之类的强型语言的继承方式有很大的 ...

  8. 探究JS常见的6种继承方式

    先看以下百科对(面向对象的继承)的解释! 通过以上精炼实用的解释,我们可以了解到继承的基本作用和功能!即可以使得子类具有父类的属性和方法或者重新定义.追加属性和方法等. 广告:帮忙点击>> ...

  9. JavaScript对象理解

    1.对象 javascript对象:有助于组织信息 对象仅仅是一种特殊的数据类型?⒂涤幸幌盗械氖粜院头椒ā?lt;br /> 访问对象的属性:对象名.属性名 对象的方法调用:对象名.方法名() ...

最新文章

  1. Clojure程序设计
  2. 系统维护For流星无语
  3. Python list列表的使用(增删改查)
  4. 今日c++练手之寻找n个连续的合数
  5. Django 模型 —— 模型介绍
  6. 分布式系统概念 | 分布式ID:数据库、号段模式、雪花算法(Snowflake)、Redis实现方案
  7. fopen,fopen_s,fclose, _fcloseall函数用法
  8. 文件查找-locate find 学习笔记
  9. ID,ClientID,UniqueID的区别
  10. OpenCV实战【2】HOG+SVM实现行人检测
  11. Mac下png转icns图标脚本
  12. python备份目录下文件夹_Python备份目录及目录下的全部内容的实现方法
  13. 力扣-530. 二叉搜索树的最小绝对差
  14. sap ui5 中使用echarts
  15. SAP FAGLGVTR 总账科目年末结转
  16. 坚果云和亿方云哪个更适合学校?
  17. cadence 通孔焊盘_【精品】PCB设计软件allegro不规则带通孔焊盘的制作
  18. Nature综述:鸟枪法宏基因组-从取样到数据分析——2万字带你系统入门宏基因组实验和分析
  19. spring中自定义注解(annotation)与AOP中获取注解___使用aspectj的@Around注解实现用户操作和操作结果日志
  20. AI遮天传 DL-CNN

热门文章

  1. 每日一博 - ThreadLocal VS InheritableThreadLocal VS TransmittableThreadLocal
  2. MySQL - 践行索引优化
  3. linux服务器磁盘格式,linux下查看磁盘分区的文件系统格式
  4. php和派森,安装多版本Python,一个神器足矣
  5. 学习Kotlin(四)对象与泛型
  6. oracle var/tmp,关于/var/tmp/.oracle 目录(ZT)
  7. php 正则获取数字,php结合正则获取字符串中数字的几种方法
  8. 艺术签名python_个性签名设计五十行Python轻松实现
  9. Linux统计某个文件夹下的文件个数、目录个数
  10. @select注解模糊查询_mybatis @SelectProvider 注解, 打赌你没有用过