有学有练才叫学习:学而不思则罔,思而不学则殆:学而不习,纸上谈兵,习而不进,画地为牢!

js 原型继承

javascript cat 10个月前 (12-06) 57次浏览 已收录 0个评论 扫描二维码

1、原型链继承

原型链继承:原型链继承就是将父类的实例对象赋值给子类的原型对象。

面试题:如何用一句话实现继承:将父的实例赋给子的原型(一定要说,有不足)。

不足:

1、如果父类有引用类型,子类一改,会导致后续的都改了

2、子的constructor指向父类,这是不对的,应该指向自己的构造函数

// 父类
function Student() {
    this.job = '学生';
    this.ah = ['游戏', '睡觉', '找平头妹'];
}
Student.prototype.showJob = function () {
    console.log(this.job);
}

// 子类
function SmallStudent(name) {
    this.name = name;
}

// 原型链继承就是将父类的实例对象赋值给子类的原型对象。
// 面试题:如何用一句话实现继承:将父的实例赋给子的原型(一定要说,有不足)。
// 不足
// 1、如果父类有引用类型,子类一改,会导致后续的都改了
// 2、子的constructor指向父类,这是不对的,应该指向自己的构造函数
SmallStudent.prototype = new Student();

var s1 = new SmallStudent('小花');
console.log(s1);
// console.log(s1.job);
// console.log(s1.ah);
// console.log(s1.name);
// s1.showJob();
s1.ah.push('学习'); // 添加一项,会导致后面创建的都有这一项

var s2 = new SmallStudent('小黄');
console.log(s2);
console.log(s2.ah);
console.log(s2.constructor);

// 每一个函数都有原型对象,原型对象下面有一个constructor又指向构造函数
// function fn() { }
// console.log(fn.prototype);
// console.log(fn.prototype.constructor); // 指向构造函数

2、对象冒充继承

对象冒充继承:在子类的构造函数中,调用父类的构造函数,并用call改this指向为子的实例

好处:解决了父类引用类型子类一改全改的问题

不足:只能继承父类构造函数中的属性,不能继承父类原型上的方法

// 父类
function Student() {
    this.job = '学生';
    this.ah = ['游戏', '睡觉', '找平头妹'];
}
Student.prototype.showJob = function () {
    console.log(this.job);
}

// 子类
function SmallStudent(name) {
    Student.call(this);
    this.name = name;
}

// 对象冒充继承:在子类的构造函数中,调用父类的构造函数,并用call改this指向为子的实例
// 好处:解决了父类引用类型子类一改全改的问题
// 不足:只能继承父类构造函数中的属性,不能继承父类原型上的方法

var s1 = new SmallStudent('zs');
console.log(s1);
s1.ah.push('学习');
console.log(s1.name);
console.log(s1.job);
console.log(s1.ah);

var s2 = new SmallStudent('ls');
console.log(s2.ah);

3、组合继承

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

对象冒充继承属性

原型链继承方法

// 父类
function Student() {
    this.job = '学生';
    this.ah = ['游戏', '睡觉', '找平头妹'];
}
Student.prototype.showJob = function () {
    console.log(this.job);
}

// 子类
function SmallStudent(name) {
    Student.call(this); // 对象冒充继承
    this.name = name;
}
SmallStudent.prototype = new Student(); // 原型链继承(会将父的方法和属性都继承过来)

var s1 = new SmallStudent('zs');
console.log(s1);
console.log(s1.job);
console.log(s1.ah);
console.log(s1.name);
s1.showJob();

// 组合继承(对象冒充+原型链)
// 问题:
// 1、同样的属性,在原型链中会出现多次
// 2、两次调用父的构造函数

4、寄生组合继承

// 父类
function Student() {
    this.job = '学生';
    this.ah = ['游戏', '睡觉', '找平头妹'];
}
Student.prototype.showJob = function () {
    console.log(this.job);
}

// 寄生组合继承(是我们继承的标准方法)
// 将属性和方法分开继承。属性利用冒充继承,方法利用原型链继承

// 子类
function SmallStudent(name) {
    Student.call(this); // 冒充继承,继承属性
    this.name = name; // 再添加自己的
}

inherits(SmallStudent, Student); // 原型链继承,仅仅只继承方法
// 添加自己的方法,一定要写在继承方法的后面
SmallStudent.prototype.showName = function () {
    console.log(this.name);
}

var s1 = new SmallStudent('zs');
console.log(s1);
console.log(s1.job);
console.log(s1.ah);
console.log(s1.name);

s1.showJob();
s1.showName();
console.log(s1.constructor);

function inherits(child, parent) {
    var F = function () { };
    F.prototype = parent.prototype;
    child.prototype = new F();
    child.prototype.constructor = child;
}
喜欢 (0)
cat
关于作者:
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址