js的类和继承

文章详细介绍了JavaScript中的类的概念,如何定义和使用类,以及new关键字的工作原理。接着讨论了继承的目的,包括ES5中的原型链继承、构造函数继承和组合继承,分析了各自的优缺点。最后,文章提到了ES6的class和extends关键字带来的改进,以及super函数的作用。
摘要由CSDN通过智能技术生成

一,js中的类

1,js类的概念

每个对象都是属性的集合,但是他们都是独立的。想让一部分对象共有一些属性,就可以使用类去定义。

js中的类是基于原型继承机制的

2,类的使用

定义类:function Person() { ... }

封装普通属性:this.name = xxx;        this.age = xxx;

封装原型属性:Person.prototype.eat = xxx;

实例化:var p = new Person();

3,new关键字原理

在调用new关键字实例化一个对象时,实际上进行了以下步骤:

(1)var p = {};        // 创建一个空对象

(2)p.__proto__ = Person.prototype;        // 将对象的隐式原型__proto__指向构造函数的显示原型prototype

(3)Person.call(obj) ;        // 将this指向改变,指向实例对象

二,继承

1,js继承的目的

让子类的实例也拥有父类的私有属性和公共方法

2,ES5的继承方法

2.1 使用原型链继承

方式:即利用原型链的机制,让子类的原型prototype等于父类的实例即可。

示例:

// 父类
function Parent() {
    this.x = '123'; // 父类私有属性、方法
}
Parent.prototype.eat = function(a, b) { // 父类公有属性、方法
    console.log(a + b);
}
// 子类
function Child() {
    this.y = '456';    // 子类私有属性、方法
}
Child.prototype.fly = 'flyer';    // 子类公有属性、方法

// 继承
Child.prototype = new Parent;

// 使用:实例化一个子类对象
var c1 = new Child;
console.log(c1);

优点:实现简单;可以继承父类的私有和公有属性。

缺点:不能实现多继承;原型对象的属性,都被所有的子类实例共享。其中一个子类修改属性,其他的子类属性也跟着改变

2.2 使用构造函数通过call或apply继承

方式:即在子类的构造函数中,通过call或apply强制将父类的this指向修改为子类,这样子类便被强制继承了父类的私有属性

示例:

// 父类
function Parent() {
    this.x = '123';
}
// 子类
function Child() {
    // 改变this指向为Child,将父类当做普通函数执行(没有父类实例,他原型上的属性就和父类没关系了)
    Parent.call(this); 
}
// 使用:实例化一个子类对象
var c1 = new Child;
console.log(c1);

优点:可以实现多继承,即call多个父类;解决了子类实例共享父类引用属性的问题

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

2.3 组合继承

方式:即综合原型继承和构造函数使用call继承的方式

理解:因为构造函数+call继承方式 解决了原型链继承方式 不能多继承和共享属性修改所有实例也跟着变化的缺点,但因为构造函数+call继承方式只能继承父类的私有属性,无法继承父类的公有属性,因此组合继承是为了解决这个方式实现的。

示例:

// 父类
function Parent() {
    this.x = '123';    // 父类私有属性、方法
}
Parent.prototype.eat = function(a, b){ // 父类公有属性、方法
    console.log(a + b);
}

// 子类
function Child() {
    Parent.call(this);    // 父类改变this指向为子类
    this.y = '456';       // 子类私有的属性
}

// 组合原型方式继承
Child.prototype = Object.create(Parent.prototype);   // 子类的原型指向父类的实例(通过Object.create方法)
Child.prototype.constructor = Child;    // 手动增加构造函数


// 子类的公有属性、方法
Child.prototype.fly = 'flyer';

// 使用
var c1 = new Child;
console.log(c1)

缺点:

(1)组合创建的子类原型没有构造函数,需要手动创建。

(2)让子类的原型指向父类的实例需要操作子类Child.prototype.__proto__ = Parent.prototype;但是IE浏览器不允许操作__proto__隐式原型,因此需要使用Object.create()方法。

附:Object.create(proto, [property]) -- 以指定的原型proto创建对象(参数可以是null,但不能是undefined),property参数可选,新对象的属性设置

3,ES6的继承方法

方式:ES6增加关键字class、constructor、super、extends等关键字,实现继承。原理类似于ES5的组合继承。

方式:

// 父类
class Parent{
    constructor() {
        this.x = '123'; // 私有
    }

    eat(a, b) {    // 公有
        console.log(a + b);
    }
}
// 子类,继承父类
class Child extends Parent{
    constructor() {
        super();    // 执行父类的构造函数
        this.y = '456';    // 子类私有
    }
    
    fly() {    // 子类公有
        console.log('fluer');
    }
}

// 使用
var c1 = new Child;
console.log(c1);

特点:super()函数相当于ES5中的call方式,执行了父类的构造函数,且可以传参。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

妍思码匠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值