博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JS的继承
阅读量:5876 次
发布时间:2019-06-19

本文共 4041 字,大约阅读时间需要 13 分钟。

一、ES5实现继承

1、原型链

在JavaScript中,通过new操作符创建一个实例对象,这个实例对象就会拥有一个【__proto__】属性,这个属性指向构造函数的prototype对象;构造函数的prototype对象也拥有一个【__proto__】属性,这个属性指向Object的prototype对象;Object.prototype的【__proto__】指向顶级对象null;按照这种一层一层向上查找的方式,就形成了一个原型链,这也是前端实现继承的最核心的点,有了原型链之后,实例对象就可以访问到它的祖先元素的属性和方法了。复制代码

2、继承

2-1、原型链继承
【代码实现】
function Parent (name) {    this.name = name;    this.friends = ['zhangsan', 'lisi'];}Parent.prototype.getName = function () {    console.log(name);}function Child (age) {    this.age = age;    }Child.prototype = new Parent();Child.prototype.getAge = function () {    console.log(this.age);}var child = new Child(22);child.friends.push('wangwu');var child1 = new Child(23);console.log(child.friends);// [ 'zhangsan', 'lisi', 'wangwu' ]console.log(child1.friends);// [ 'zhangsan', 'lisi', 'wangwu' ]复制代码
【问题!!!】
1>、使用原型链实现继承时,不能使用字面量的方式为子类添加方法,会断开原型链,导致子类无法访问父类。2>、使用原型链继承,父类的属性和方法与子类共享,如果父类的属性是引用类型,那么子类在修改该属性时,也会修改父类的该属性。3>、在创建子类的实例时,无法向父类传递参数。复制代码
2-2、借用构造函数继承
使用构造函数继承,子类可以向父类传递参数复制代码
【代码实现】
function Parent (name) {    this.name = name;    this.friends = ['zhangsan', 'lisi'];}Parent.prototype.getName = function () {    console.log(name);}function Child (age) {    Parent.call(this);    this.age = age;    }Child.prototype.getAge = function () {    console.log(this.age);}var child = new Child(22);child.friends.push('wangwu');var child1 = new Child(23);console.log(child.friends);// ['zhangsan', 'lisi', 'wangwu']console.log(child1.friends);// ['zhangsan', 'lisi']child.getName();// error复制代码
【问题!!!】
使用构造函数的方式实现继承时,子类只能访问直接定义在父类上的属性和方法,而定义在父类的prototype对象上的方法和属性子类是访问不到的。无法实现函数的复用。复制代码
2-3、组合继承
组合继承,也叫伪经典继承;他是构造函数和原型链的结合。原理就是:使用原型链实现对属性和方法的继承。复制代码
【代码实现】
function Parent (name) {    this.name = name;    this.friends = ['zhangsan', 'lisi'];}Parent.prototype.getName = function () {    console.log(this.name);}function Child (name, age) {    Parent.call(this, name);    this.age = age;    }Child.prototype = new Parent();Child.prototype.getAge = function () {    console.log(this.age);}var child = new Child('xiao', 22);child.friends.push('wangwu');var child1 = new Child('meng', 23);console.log(child.__proto__);console.log(child.friends);console.log(child1.friends);child.getName();// xiao复制代码
【结论】
每个实例对象都有自己的属性和方法,子类可以访问父类的原型链上的方法和属性。复制代码
2-4、原型式继承
使用一个中间对象作为基础,继承父类的原型复制代码
【代码实现】
function Parent (name) {    this.name = name;    this.friends = ['zhangsan', 'lisi'];}Parent.prototype.getName = function () {    console.log(this.name);}function Child (name, age) {    Parent.call(this, name);    this.age = age;    }Child.prototype = Object.create(Parent.prototype);Child.prototype.getAge = function () {    console.log(this.age);}var child = new Child('xiao', 22);child.friends.push('wangwu');var child1 = new Child('meng', 23);console.log(child.__proto__);console.log(child.friends);console.log(child1.friends);child.getName();// xiao复制代码

二、ES6继承

【简述】
在ES6中,继承通过extends关键字实现。通过extends关键字实现继承时,只是实现了父类的复制。复制代码

【注意事项】

- 使用extends之后,如果不使用super方法,子类的实例对象调用父类的方法时,父类的this指向已经发生了变化,指向了子类。- 子类必须在constructor方法中,调用super方法,否则新建实例会报错。 【子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的属性和方法,然后再添加子类自己的属性和方法】复制代码
class Person {    //调用类的构造方法    constructor(name, age) {        this.name = name        this.age = age    }    //定义一般的方法    showName() {        console.log("调用父类的方法")        console.log(this.name, this.age);    }}let p1 = new  Person('kobe', 39)console.log(p1)//定义一个子类class Student extends Person {    constructor(name, age, salary) {        super(name, age)//通过super调用父类的构造方法        this.salary = salary    }    showName() {//在子类自身定义方法        console.log("调用子类的方法")        console.log(this.name, this.age, this.salary);    }}let s1 = new Student('wade', 38, 1000000000)console.log(s1)s1.showName()复制代码

【ES5继承和ES6继承的区别】

- ES5的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this对象上。- ES6的继承,实质是先将父类实例对象的属性和方法添加到this对象上【所以必须先调用super方法】,然后再用子类的构造函数修改this。- 如果子类没有定义constructor方法,这个方法会被默认添加,即:不管有没有显示定义,任何一个子类都有constructor方法。【注意】:在子类的构造函数中,只有调用super之后,才可以使用this关键字,否则会报错。这是因为子类实例的构建基于父类实例,只有super方法才能调用父类实例。复制代码

转载于:https://juejin.im/post/5c67cac86fb9a049d61e12a9

你可能感兴趣的文章
在WPF中如何使用RelativeSource绑定
查看>>
Map的深浅拷贝的探究
查看>>
XSLT语法 在.net中使用XSLT转换xml文档示例
查看>>
如何将lotus 通讯簿导入到outlook 2003中
查看>>
WinForm 应用程序中开启新的进程及控制
查看>>
前端工程师的职业发展路线在哪?
查看>>
IOS 内存警告 Memory warning level
查看>>
[转]PAC Manager: Ubuntu 上强大的 SSH 帐号管理工具,可取代 SecureCRT_Miracle_百度空间...
查看>>
顺序容器 (2)string类型操作
查看>>
转载:我最近的研究成果(IGeometry.Project and IGeometry.SpatialReference)
查看>>
提示框
查看>>
HDOJ1233 畅通工程之一(最小生成树-Kruscal)
查看>>
14Spring_AOP编程(AspectJ)_环绕通知
查看>>
PHP之打开文件
查看>>
iOS - OC SQLite 数据库存储
查看>>
PHP-mysqllib和mysqlnd
查看>>
Redis常用命令
查看>>
NeHe OpenGL教程 第三十五课:播放AVI
查看>>
Linux下ping命令、traceroute命令、tracert命令的使用
查看>>
js replace,正则截取字符串内容
查看>>