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

推荐订阅源

cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
C
CERT Recently Published Vulnerability Notes
C
Cybersecurity and Infrastructure Security Agency CISA
P
Proofpoint News Feed
Security Latest
Security Latest
P
Privacy International News Feed
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
AI
AI
Cisco Talos Blog
Cisco Talos Blog
K
Kaspersky official blog
S
Secure Thoughts
PCI Perspectives
PCI Perspectives
Simon Willison's Weblog
Simon Willison's Weblog
D
DataBreaches.Net
GbyAI
GbyAI
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
大猫的无限游戏
大猫的无限游戏
T
Tailwind CSS Blog
The Cloudflare Blog
阮一峰的网络日志
阮一峰的网络日志
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
罗磊的独立博客
V
Visual Studio Blog
aimingoo的专栏
aimingoo的专栏
H
Hackread – Cybersecurity News, Data Breaches, AI and More
IT之家
IT之家
V
V2EX
Last Week in AI
Last Week in AI
有赞技术团队
有赞技术团队
月光博客
月光博客
酷 壳 – CoolShell
酷 壳 – CoolShell
T
Tenable Blog
T
Threat Research - Cisco Blogs
T
Troy Hunt's Blog
V2EX - 技术
V2EX - 技术
S
Security @ Cisco Blogs
Security Archives - TechRepublic
Security Archives - TechRepublic
Project Zero
Project Zero
The GitHub Blog
The GitHub Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
L
Lohrmann on Cybersecurity
F
Full Disclosure
H
Help Net Security
博客园 - Franky
Stack Overflow Blog
Stack Overflow Blog
N
Netflix TechBlog - Medium
Engineering at Meta
Engineering at Meta
A
Arctic Wolf
O
OpenAI News
S
Securelist

博客园 - 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 看定义