web前端 之 面向对象

类与实例

类的声明

1、ES6之前的声明方式

function Student() {
	this.name = 'name';
}

2、ES6新定义的声明方法

class Student2 {
	//constructor就是类名
	constructor() {
		this.name = 'name'
	}
}

生成实例

实例化就是将定义的类赋具体值给变量的过程

const student1 = new Student();
const student2 = new Student2();

类与继承

如何实现继承

基本原理或者说是本质就是原型链

实现继承的几种方式以及不同点

1、通过构造函数实现继承

function Parent1(name){
	this.name = name;
}
function Child1(name,age){
	//使用call方法使得指向发生变化,相当于把Parent中所有方法属性都copy过来成为Child的属性和方法
	Parent1.call(this,name);
	//或者可以使用Parent1.apply(this,name)
	this.age = age;
}
const child = new Child1('mao',25);

原理:通过call/apply函数改变this的指向,使this的指向由Parent1改变为Child1,从而实现继承
缺点:父类构造函数原型链上的方法属性无法继承
举例说明:

//这个say方法是Child1无法继承到的
Parent1.prototype.say = function() {
	console.log(name + ' is' + age + ' years old')
}

2、通过原型链实现继承

function Parent2(name){
	this.name = name;
	this.play = [1,2,3]
}
function Child2(name,age){
	this.age =age;
}
//实现继承的关键步骤
Child2.prototype = new Parent2('mao');
const child2 = new Child2('mao',25);

原理:将父类实例化对象后赋值给子类的prototype属性
缺点:如果多个子类实例化之后,任一实例化后的对象改变了原型链上的值,那么其余实例化对象继承的该值也会发生变化。
举例如下:

const s1 = new Child2();
const s2 = new Child2();
s1.play.push(4);
//此时原型链上的play值已经变为[1,2,3,4]
console.log(s2.play);
//此时打印出的s2.play值为[1,2,3,4]	

3、混合式继承

组合方式,将上面两种方式直接结合起来

//缺点:父类Parent3被调用了两次,一次是call继承的时候,一次是原型链继承的时候
function Parent3(name) {
	this.name = name;
}
function Child3(name,age) {
	Parent3.call(this,name);
	this.age = age
}
//原型链方式继承父类
Child3.prototype = new Parent3(name);
const child3 = new Child3('mao',24);

接下来我们对上面的组合继承进行优化

组合继承优化1

//优点:父类Parent3调用一次即可
//缺点:子类和父类的构造函数指向同一个,子类的constructor指的是Parent
function Parent3(name) {
	this.name = name;
}
function Child3(name,age) {
	Parent3.call(this,name);
	this.age = age
}
//这种方式的弊端是子类和父类的构造函数指向同一个,子类的constructor指的是Parent
Child3.prototype = Parent3.prototype;
//下面这个不建议这么写,因为修改后子类和父类的constructor全部指向了子类,没法区分子类和父类
//Child3.prototype.constructor = Parent3;
const child3 = new Child3('mao',24);
//以下结果都返回为true,没法判断child3是子类还是父类的直接对象,这就印证了上面说的缺点
console.log(child3 instanceof Child3,child3 instanceof Parent3);
//这个输出的就是Parent3
console.log(child3.constructor)

来,接着对上面的继承进行优化

组合继承优化2(这个就是组合继承的完美写法了)

function Parent3(name) {
	this.name = name;
}
function Child3(name,age) {
	Parent3.call(this,name);
	this.age = age
}
//这里用Object.create先创建一个空对象,然后这个对象的原型链就是传入的参数
//这个空对象其实就作为一个中间值,将子类和父类区分开了
Child3.prototype = Object.create(Parent3.prototype);
//此时该空对象的constructor是空,我们需要对该值赋值,让他指向子类
Child3.prototype.constructor = Child3;
const child3 = new Child3('mao',24);
//以下结果两个返回都为true
console.log(child3 instanceof Child3,child3 instanceof Parent3);
//这个输出的就是Child3
console.log(child3.constructor)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值