JS继承

举报
小妖现世 发表于 2021/07/10 00:35:46 2021/07/10
【摘要】 原型继承function Parent() { this.x = 100;}Parent.prototype.getX = function getX() { return this.x;};function Child() { this.y = 200;}//=> 让子类的原型等于父类的实例Child.prototype = new Parent; //=>原型继承Child.protot...

原型继承

function Parent() {
	this.x = 100;
}
Parent.prototype.getX = function getX() {
	return this.x;
};

function Child() {
	this.y = 200;
}
//=> 让子类的原型等于父类的实例
Child.prototype = new Parent; //=>原型继承

Child.prototype.getY = function getY() {
	return this.y;
};

let a = new Child;
console.log(a); 

现在a能用的方法是:私有的 y 和公有的 getY方法,以及Object上的公有方法;

原理

  • 子类的实例,能够用子类私有的和原型上公有的
  • 父类的实例,可以使用 父类私有和原型上公有的

所以我们只要让子类的原型等于父类的实例即可

  • Child.prototype = new Parent

特点

  • 1、父类中私有和公有的属性方法,最后都变为子类实例公有的
  • 2、和其他语言不同的是
    • 原型继承并不会把父类的属性方法“拷贝”给子类,
    • 而是让子类实例基于__proto__原型链找到自己定义的属性和方法“指向/查找”方式的

优缺点

  • a.__proto__.xxx = xxx 修改子类原型(原有父类的一个实例)中的内容,内容被修改后,对子类的其他实例有影响,但是对父类的实例不会有影响

  • a.__proto__.__proto__.xxx = xxx直接修改的是父类原型,这样不仅会影响其它父类的实例,也影响其他子类的实例

  • JS中的重写影响很大

CALL继承

function Parent() {
	this.x = 100;
}
Parent.prototype.getX = function getX() {
	return this.x;
};

function Child() {
	Parent.call(this);
	this.y = 200;
}
Child.prototype.getY = function getY() {
	return this.y;
};

let b= new Child;
console.log(b); 

原理

  • 在子类构造函数中,把父类当作普通函数执行(没有父类实例,父类原型上的那些东西也就和他没有关系了)
    • 此时 parent(this) 这个 thiswindow
  • 通过 call 强制改变 this 的指向为 Child 中的 this
    • Parent.call(this)
    • 此时 this 是当前 Child 中的 this

相当于强制给实例设置了一个私有的属性,相当于让子类的实例继承了父类的私有的属性,并且也变为了子类私有的属性“拷贝式”

特点

  • 只能继承父类中私有的,公有的不行(并且是把父类私有的变成子类私有的)

我们满意的继承方式应该是:父类私有变为子类私有 父类公有变为子类公有

寄生组合式继承(CALL继承 + 另类原型继承)

function Parent() {
	this.x = 100;
}
Parent.prototype.getX = function getX() {
	return this.x;
};

function Child() {
	Parent.call(this);
	this.y = 200;
}

Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

Child.prototype.getY = function getY() {
	return this.y;
};

let c1 = new Child;
console.log(c1); 
  • 上面我们说了 call 继承有个好处:能把父类私有的变成子类私有的;所以 call 继承我们留下来

那现在我们只要想办法让父类中公有的也能变成子类中公有的即可;

原理

  • 原型继承是创建了父类的一个实例,从而达到子类继承父类的效果;它最终实现的核心点是:Child.prototype.__proto__ === Parent.prototype;
  • 如果说我们在原型继承时不想要父类私有的内容,我们只需要:Child.prototype.__proto__ = Parent.prototype; 

这样虽然能实现效果但是IE浏览器中不允许我们操作__proto__,那我们有什么可以替换它呢?

// Object.create();创建一个空对象,让其原型链指向obj
let obj = {
	xxx: 'xxx'
};
console.log(Object.create(obj));

所以可以写成:Child.prototype = Object.create(Parent.prototype);即可

缺点:

  • 由于新创建的原型没有constructor属性,所以我们自己手动加一个默认的;

ES6中的类和继承

  • class类
class Parent {
	constructor() {
		this.x = 100;
	}
	// Parent.prototype.getX=function...
	getX() {
		return this.x;
	}
}
  • 继承
// 继承: extends Parent(类似于寄生组合继承)
// 注意:继承后一定要在CONSTRUCTOR第一行加上SUPER
class Child extends Parent {
	constructor() {
		super(); //=>类似于我们之前的CALL继承  super(100,200):相当于把Parent中的constructor执行,传递了100和200
		this.y = 200;
	}
	getY() {
		return this.y;
	}
}
let c1 = new Child;
console.log(c1);
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。