惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

阮一峰的网络日志
阮一峰的网络日志
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Schneier on Security
The Last Watchdog
The Last Watchdog
Cyberwarzone
Cyberwarzone
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cyber Attacks, Cyber Crime and Cyber Security
L
Lohrmann on Cybersecurity
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 司徒正美
The Cloudflare Blog
V
V2EX
博客园_首页
博客园 - 聂微东
Vercel News
Vercel News
人人都是产品经理
人人都是产品经理
G
GRAHAM CLULEY
T
Tenable Blog
Last Week in AI
Last Week in AI
Y
Y Combinator Blog
L
LINUX DO - 最新话题
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
SecWiki News
SecWiki News
博客园 - 三生石上(FineUI控件)
S
Secure Thoughts
N
News | PayPal Newsroom
T
The Blog of Author Tim Ferriss
The GitHub Blog
The GitHub Blog
T
Troy Hunt's Blog
博客园 - 【当耐特】
Forbes - Security
Forbes - Security
H
Hacker News: Front Page
A
About on SuperTechFans
B
Blog RSS Feed
Engineering at Meta
Engineering at Meta
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
罗磊的独立博客
D
DataBreaches.Net
P
Privacy & Cybersecurity Law Blog
Schneier on Security
Schneier on Security
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Jina AI
Jina AI
D
Docker
P
Proofpoint News Feed

博客园 - smile轉角

【js】setTimeout、Promise、Async/Await 的区别 【面试题】思维逻辑方面 【js】js内置对象Error(错误机制) 【TS】学习笔记 【js】CommonJS、AMD、CMD三种规范 【其他】查看Animate.css官网动画没有效果 【vue3】父子组件通信之 vue3 defineProps,defineEmits ,defineExpose 【js】JS严格模式有什么特点 【css】使用弹性盒子布局时,省略号问题 【vue】 Failed to load resource: the server responded with a status of 404 (Not Found) 【第三方】富文本调研 【js】元素是否在可视区范围内 【js】json的相关操作 【vue3】资料 【css】展示背景图片的底部部分 【html】 svg 【html5】html5中input 标签 type值为range时,修改其默认css 【js】forEach,for...in,for...of 区别 【js】map,reduce,filter的区别
【js】ES5,ES6继承是如何实现的
smile轉角 · 2026-03-16 · via 博客园 - smile轉角

==详解 ES5 组合继承(构造函数+原型链)==

function Parent(){...}

function Child(){
  Parent.call(this) //
}

Child.prototype = new Parent() //

1. 先记住目的

我们要让:

- Child 实例 继承 Parent 的属性 + 方法

- 这是 ES5 没有 class/extends 时的标准写法


2. 逐句解释

① Parent.call(this)

function Child(){
  Parent.call(this)
}

- call(this) 把 Parent 里的 this 换成 Child 的实例

- 等于:在创建 Child 时,把 Parent 的属性“复制”一份给自己

- 作用:继承父构造函数里的实例属性

例子:

function Parent() {
  this.name = "父类"
}
function Child() {
  Parent.call(this)
}
const c = new Child()
console.log(c.name) // "父类" 继承到了
---
② Child.prototype = new Parent()
Child.prototype = new Parent()

- 把 Child 的原型对象,变成 Parent 的一个实例

- 原型链就通了:

Child实例 → Child.prototype → Parent.prototype

- 作用:继承父类原型上的方法

例子:

Parent.prototype.say = function(){
  console.log('说话')
}

const c = new Child()
c.say() // 能调用,因为原型链找到了

---
3. 合起来:组合继承 = 最常用的 ES5 继承

- Parent.call(this)

→ 继承实例属性

- Child.prototype = new Parent()

→ 继承原型方法

所以它叫 组合继承:

借用构造函数 + 原型链继承 合在一起。


4. 面试常问缺点

它有个小问题:

- Parent 会被执行两次

1. new Child() 时:Parent.call(this)

2. 挂原型时:new Parent()

后来就有了寄生组合式继承(优化版),但面试先把这个搞懂就稳了。


5. 一句话总结(面试背诵版)

这段代码是 ES5 组合继承:

1. Parent.call(this) 继承父类实例属性;

2. Child.prototype = new Parent() 继承父类原型方法;

3. 结合了借用构造函数和原型链两种方式,是 ES5 最常用继承方案。

===寄生组合继承==

一、最终最优代码(背它)

function Parent() {
  this.name = 'parent';
}

Parent.prototype.say = function () {
  console.log('hello');
};

function Child() {
  Parent.call(this); // 继承属性(只调用1次父构造)
}

// 核心:寄生组合继承关键一句
Child.prototype = Object.create(Parent.prototype);

// 修正 constructor
Child.prototype.constructor = Child;

---
二、和你之前写法的区别

你之前:

Child.prototype = new Parent();

问题:

- 会调用两次 Parent 构造函数

- 会把 Parent 实例属性挂到原型上,多余、浪费

优化后:

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

- 只继承原型,不调用 Parent 构造

- 干净、高效、标准


---
三、三句话背会

1. 用 Parent.call(this) 继承实例属性

2. 用 Object.create(Parent.prototype) 继承原型方法

3. 最后修正 constructor 指向

这就是 JS 最标准、最推荐的继承方式。

---
四、我再给你一句超简记忆版

call 拿属性,create 拿原型,constructor 指回去

---
题目1(基础组合继承)

function Parent() {
  this.name = "父亲";
}
Parent.prototype.say = function () {
  console.log(this.name);
};

function Child() {
  Parent.call(this);
  this.name = "儿子";
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;

var child = new Child();
child.say();

问:输出什么?//儿子

执行过程

1.  new Child() 

2. 里面先跑: Parent.call(this) 

- 给当前 child 实例设置: this.name = "父亲" 

3. 然后跑: this.name = "儿子" 

- 把上面的 name 覆盖了

4. 调用  child.say() 

-  say  在原型上, this  指向  child 

- 所以输出: this.name  → 儿子

答案:儿子


---
题目2(寄生组合继承 + 箭头函数)

function Parent() {
  this.age = 40;
}
Parent.prototype.getAge = () => {
  console.log(this.age);
};

function Child() {
  Parent.call(this);
  this.age = 20;
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

var child = new Child();
child.getAge();

问:输出什么?//undefined

关键知识点
 
箭头函数没有自己的  this 
它的  this  是定义时外层作用域的 this,不是调用时的实例。
 
这里:
 
- 箭头函数写在最外层(全局)

- 所以  this  = window / 全局对象

- 全局没有  age  属性
 
答案:undefined
 
 
 
两题核心总结
 
1. 普通函数: this  指向调用它的对象(实例)

2. 箭头函数: this  指向定义时的外层 this,不绑定实例

===ES6 Class 继承===

题目 1(基础 class + extends)

class Person {
  constructor() {
    this.name = "普通人";
  }
  sayName() {
    console.log(this.name);
  }
}

class Student extends Person {
  constructor() {
    super(); // 先执行父类的 constructor
    this.name = "小学生"; // 覆盖掉前面的 name
  }
}

const stu = new Student();
stu.sayName();

问:输出什么?//小学生

- extends 就是继承

- super() = 调用父类构造方法

- 先设 name = 普通人,又改成 小学生

- 普通方法 this 指向实例


---
题目 2(super 传参)

class Animal {
  constructor(type) {
    this.type = type;
  }
  showType() {
    console.log(this.type);
  }
}

class Cat extends Animal {
  constructor() {
    super("猫"); // 传给父类构造:type = "猫"
  }
}

const cat = new Cat();
cat.showType();

问:输出什么?

- super("猫") 等于调用父类:new Animal("猫")

- 所以实例上 this.type = "猫"


---

超简口诀

- extends:继承

- super():调用父构造

- 后面赋值会覆盖前面

==JS 继承 · 终极总结==

一、ES5 组合继承(老写法)

function Parent() {
  this.name = '父';
}
Parent.prototype.say = function () {};

function Child() {
  Parent.call(this); // 继承实例属性
}
Child.prototype = new Parent(); // 继承原型方法
Child.prototype.constructor = Child;
  • 优点:属性、方法都能继承
  • 缺点:Parent 执行两次,冗余

二、寄生组合继承(最优 ES5

function Child() {
  Parent.call(this);
}
// 核心:只继承原型,不执行构造
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
  • 面试必写:最标准、最高效

三、ES6 class 继承(最简单)

class Parent {}
class Child extends Parent {
  constructor() {
    super(); // 必须写!
  }
}
  • extends:继承
  • super():调用父类构造
  • 语法清晰,日常开发用这个

四、this 必坑

普通函数在原型上

  • this → 实例对象

箭头函数在原型上

  • 没有自己的 this
  • this → 定义时外层作用域(通常是全局)
  • 千万别在原型上写箭头函数!

五、一句话串起所有继承

  • ES5call 拿属性,Object.create 拿原型
  • ES6extends + super 一把梭
  • 普通函数 this 看调用,箭头函数 this 看定义