JavaScript之继承与原型链

JavaScript的继承的实现与其它基于类的语言不同,JavaScript中的每个对象都有一个属性(__proto__),通过它来指向一个名为原型的对象,该原型对象也有自身的原型,层层向上,直到nullnull表示再往上没有原型。通过这种方式,形成了原型链。

函数

在js中,函数是非常特殊的,只有函数才有prototype属性。函数可以是一般函数(实现某个逻辑的代码块),也可以作为构造函数用于创建对象。

构造函数

js 复制代码
function person(name) {
    this.name = name
}
const personA = new person('xiaoming');
console.log(personA.name); // xiaoming

new Person('xiaoming')通过person构造函数创建了一个实例对象personA。而personA的原型就是函数personprototype,即personA.__proto__指向preson.prototype

js 复制代码
console.log(personA.__proto__ === person.prototype); // true
console.log(person.prototype);

函数person的prototype是一个对象,大概如下所示:

js 复制代码
{
  constructor: ƒ person(name),
  [[Prototype]]: {
    constructor: ƒ Object(),
    hasOwnProperty: ƒ hasOwnProperty(),
    isPrototypeOf: ƒ isPrototypeOf(),
    propertyIsEnumerable: ƒ propertyIsEnumerable(),
    toLocaleString: ƒ toLocaleString(),
    toString: ƒ toString(),
    valueOf: ƒ valueOf()
  }
}

可以看出person.prototype自带一个属性constructor,它指向了构造函数本身,我们可以验证一下

js 复制代码
console.log(person.prototype.constructor === person); // true

通过在构造函数的prototype对象上增加属性or函数,从而让所有的实例都能访问和使用。

js 复制代码
person.prototype.speak = function(msg) {
    console.log(msg);
}
person.prototype.hasEyes = true;
console.log(personA.hasEyes); // true
console.log(personA.speak('hello')); // hello

用下面这张图表示构造函数、实例和实例原型之间的关系:

__proto__

每个对象都有__proto__属性,指向的是它对应的原型对象。__proto__属性其实是来自于Object.prototype,所有的对象都继承了Object.prototype

另外,使用__proto__是不被推荐的,只是现代浏览器保留了而已,在未来的web标准中,可能会被移除,官方推荐使用Object.getPrototypeOf(obj)来获取对象的原型,使用Object.setPrototypeOf(obj, parent)可以将一个指定对象(obj)的原型设置为另一个对象(parent)。

js 复制代码
const obj = {};
console.log(Object.getPrototypeOf(obj) === Object.prototype); // true

改变原型链

实现对象A继承对象B,有很多种方法

使用Object.setPrototypeOf

js 复制代码
const A = {a: 1};
const B = {b: 2}
Object.setPrototypeOf(A, B);
console.log(A.b); // 2

使用类

js 复制代码
class A {
    a = 1;
}
class B extends A {
    b = 2
}
const b = new B();
console.log(b.a); // 1
console.log(b.__proto__ === B.prototype); // true
console.log(Object.getPrototypeOf(b) === B.prototype); // true
console.log(B.prototype.__proto__ === A.prototype); // true
console.log(Object.getPrototypeOf(B.prototype) === A.prototype); // true
相关推荐
We་ct3 分钟前
LeetCode 295. 数据流的中位数:双堆解法实战解析
开发语言·前端·数据结构·算法·leetcode·typescript·数据流
青槿吖5 分钟前
第一篇:Redis集群从入门到踩坑:3主3从保姆级搭建+核心原理一次性讲透|面试必看
前端·redis·后端·面试·职场和发展·bootstrap·html
美狐美颜sdk15 分钟前
2026主流直播美颜sdk对比:效果、算法与成本分析
前端·人工智能·计算机视觉·美颜sdk·直播美颜sdk·第三方美颜sdk·视频美颜sdk
王霸天18 分钟前
🚨 还在用 rem) 做大屏适配?用 vfit.js 一键搞定,告别改稿8版的噩梦!
前端·vue.js·数据可视化
文心快码BaiduComate32 分钟前
Comate AI IDE三大能力升级:支持语音输入& AI可操作浏览器 & Figma设计与代码双向转换
前端·后端·程序员
coder_Eight44 分钟前
LRU 缓存实现详解:双向链表 + 哈希表
前端·算法
1024小神1 小时前
kotlin安卓项目配置app横屏等方式
前端
Cxiaomu1 小时前
React + Node.js 实战:用豆包端到端实时语音大模型 API 落地web纯语音助手
前端·react.js·node.js
Electrolux1 小时前
2026年了,你敢信一些知名的开源库都还不会正确使用防抖节流吗
前端
Beginner x_u1 小时前
前端八股整理|JavaScript|高频小题 01
开发语言·前端·javascript