JavaScript 继承小记

面向对象编程很重要的一个方面,就是对象的继承。A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法。这对于代码的复用是非常有用的。

大部分面向对象的编程语言,都是通过“类”(class)实现对象的继承。传统上,JavaScript 语言的继承不通过 class(ES6 引入了class 语法),而是通过“原型对象”(prototype)实现。那么在JS中常见的继承方式有几种呢?

首先我们先来通过 es5 里的方法做一个类,即构造方法,如下:

function Person() {
    // 定义参数
    this.name = "张三";
    this.age = 18;
    // 定义方法
    this.run = function () {
        console.log(this.name + "在运动");
    }
}

// 通过原型链扩展属性和方法
Person.prototype.sex = "男";
Person.prototype.work = function () {
    console.log(this.name + "在工作");
};
// 通过类添加属性和静态方法
Person.city = "北京";
Person.eat = function () {
    console.log(this.name + "在吃")
};

// 实例化 Person
var p = new Person();
p.run(); // 张三在运动
p.work(); // 张三在工作
// p.eat(); // 报错 p.eat is not a function
Person.eat(); // Person在吃  // this 指向发生改变,为全局,该 name 不是 Person 类中定义的 name

在上面的代码中,我们根据构造函数方法创建了一个 Person 类,并通过内部定义参数方法,原型链扩展属性和方法,通过类添加属性和方法。接下来我们就根据这个 Person 类来实现集中继承的方法。

1、对象冒充实现继承

function Person() {
    // 定义参数
    this.name = "张三";
    this.age = 18;
    // 定义方法
    this.run = function () {
        console.log(this.name + "在运动");
    }
}

// 通过原型链扩展属性和方法
Person.prototype.sex = "男";
Person.prototype.work = function () {
    console.log(this.name + "在工作");
};

function Student() {
    Person.call(this);
}
var s = new Student();
console.log(s.name); // 张三
s.run(); // 张三在运动
/**
 * 对象冒充继承不能实现
 * 父类原型链上的属性和方法
 */
console.log(s.sex); // undefined
s.work(); // 报错 s.work is not a function

在上面的代码中,我们可以通过对象冒充的方法进行继承,但是原型链上的属性和方法是不能被继承的。

2、原型链继承

function Person() {
    // 定义参数
    this.name = "张三";
    this.age = 18;
    // 定义方法
    this.run = function () {
        console.log(this.name + "在运动");
    }
}

// 通过原型链扩展属性和方法
Person.prototype.sex = "男";
Person.prototype.work = function () {
    console.log(this.name + "在工作");
};
// 通过类添加属性和静态方法
Person.city = "北京";
Person.eat = function () {
    console.log(this.name + "在吃")
};

function Student() {

}
Student.prototype = new Person();
var s = new Student();
console.log(s.name); // 张三
s.run(); // 张三在运动
console.log(s.sex); // 男
s.work(); // 张三在工作

在上面的代码中,我们通过原型链的方法进行继承,这样构造方法内的方法和原型链上的方法我们都能继承了,看似很不错,但是其实存在着一些问题,如下:

function Person(name,age) {
    // 定义参数
    this.name = name;
    this.age = age;
    // 定义方法
    this.run = function () {
        console.log(this.name + "在运动");
    }
}

// 通过原型链扩展属性和方法
Person.prototype.sex = "男";
Person.prototype.work = function () {
    console.log(this.name + "在工作");
};
var p = new Person("张三",18);
p.run(); // 张三在运动
p.work(); // 张三在工作

function Student(name,age) {

}
Student.prototype = new Person();
var s = new Student("李四", '20');
console.log(s.name); // undefined
s.run(); // undefined在运动
console.log(s.sex); // 男
s.work(); // undefined在工作

在上面的代码中,我们可以看出,通过原型链继承,在实例化子类的时候没法给父类进行传参。

3、原型链+对象冒充组合继承

function Person(name, age) {
    // 定义参数
    this.name = name;
    this.age = age;
    // 定义方法
    this.run = function () {
        console.log(this.name + "在运动");
    }
}

// 通过原型链扩展属性和方法
Person.prototype.sex = "男";
Person.prototype.work = function () {
    console.log(this.name + "在工作");
};
var p = new Person("张三", 18);
p.run(); // 张三在运动
p.work(); // 张三在工作

function Student(name, age) {
    Person.call(this, name, age); // 对象冒充
}

Student.prototype = new Person();
var s = new Student("李四", '20');
console.log(s.name); // 李四
s.run(); // 李四在运动
console.log(s.sex); // 男
s.work(); // 李四在工作

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值