当前位置: 首页 > news >正文

JavaScript 原型继承与属性访问规则详解

一、原型继承基本概念

JavaScript 使用原型继承(Prototypal Inheritance)作为其面向对象编程的基础,这与传统的基于类的继承有本质区别。

1. 原型链(Prototype Chain)

每个 JavaScript 对象都有一个内部链接指向另一个对象,称为它的原型(prototype)。当访问对象的属性时,如果对象自身没有该属性,就会沿着原型链向上查找。

function Animal(name) {this.name = name;
}Animal.prototype.speak = function() {console.log(`${this.name} makes a noise.`);
};const dog = new Animal('Dog');
dog.speak(); // 先在dog实例查找,然后在Animal.prototype查找

2. 关键对象和属性

  • __proto__(现已标准化为 Object.getPrototypeOf()):对象的实际原型

  • prototype:构造函数特有的属性,用于设置新创建实例的原型

  • constructor:指向创建该对象的构造函数

二、属性访问规则

1. 属性查找机制

当访问对象属性时,JavaScript 引擎遵循以下顺序:

  1. 检查对象自身属性(包括可枚举和不可枚举属性)

  2. 如果未找到,沿着原型链向上查找

  3. 直到 Object.prototype(所有对象的顶层原型,其 __proto__ 为 null

  4. 如果最终未找到,返回 undefined

const parent = { a: 1 };
const child = Object.create(parent);
child.b = 2;console.log(child.b); // 2 (自身属性)
console.log(child.a); // 1 (继承属性)
console.log(child.c); // undefined (不存在)

2. 属性遮蔽(Property Shadowing)

如果对象和它的原型有同名属性,对象自身的属性会遮蔽原型上的属性

const proto = { value: 10 };
const obj = Object.create(proto);
obj.value = 20; // 遮蔽原型属性console.log(obj.value); // 20 (自身属性)
delete obj.value;
console.log(obj.value); // 10 (恢复访问原型属性)

三、原型继承的实现方式

1. 构造函数模式

function Person(name) {this.name = name;
}Person.prototype.greet = function() {console.log(`Hello, I'm ${this.name}`);
};const john = new Person('John');
john.greet(); // Hello, I'm John

2. Object.create()

const animal = {eat() {console.log(`${this.name} eats.`);}
};const rabbit = Object.create(animal, {name: { value: 'White Rabbit' }
});rabbit.eat(); // White Rabbit eats.

3. ES6 Class 语法糖

class Animal {constructor(name) {this.name = name;}speak() {console.log(`${this.name} makes a noise.`);}
}class Dog extends Animal {speak() {console.log(`${this.name} barks.`);}
}const d = new Dog('Rex');
d.speak(); // Rex barks.

四、属性访问的特殊情况

1. 不可写属性

如果原型属性被标记为 writable: false,子对象无法修改该属性:

const proto = {};
Object.defineProperty(proto, 'value', {value: 10,writable: false
});const obj = Object.create(proto);
obj.value = 20; // 严格模式下会报错console.log(obj.value); // 10 (修改失败)

2. setter/getter 继承

const proto = {get value() {return this._value * 2;},set value(v) {this._value = v;}
};const obj = Object.create(proto);
obj.value = 10;
console.log(obj.value); // 20

五、原型相关方法

1. 检查原型关系

// 检查对象是否是另一个对象的原型
console.log(proto.isPrototypeOf(obj)); // true// 检查实例关系
console.log(obj instanceof Object); // true

2. 获取/设置原型

// 获取原型
const proto = Object.getPrototypeOf(obj);// 设置原型(性能差,不推荐)
Object.setPrototypeOf(obj, newProto);

六、最佳实践

  1. 不要直接修改内置对象原型(如 Array.prototype

  2. 优先使用 Object.create() 而非 __proto__

  3. 对于性能敏感代码,避免长原型链

  4. 考虑使用 ES6 Class 语法提高可读性

七、原型继承图示

实例对象 (obj) → 构造函数.prototype → Object.prototype → null↑                   ↑|__proto__          |__proto__

JavaScript 的原型继承提供了极大的灵活性,理解其工作原理对于编写高效、可维护的代码至关重要。

http://www.dtcms.com/a/337332.html

相关文章:

  • ES入门教程
  • CSDN转PDF【无水印且免费!!!】
  • linux 内核 - 进程地址空间的数据结构
  • 【STM32】STM32H750 CubeMX 配置 USB CDC 虚拟串口笔记
  • 保姆级教学:使用 Jenkins 部署前端项目(2025 年最新版)
  • 基于JS实现的中国象棋AI系统:多模块协同决策与分析
  • ffmpeg编译
  • 音视频面试题集锦第 26 期
  • 计算机网络-IPv6
  • 679. 24 点游戏
  • Android Cutout(屏幕挖孔)详解
  • ubuntu 编译ffmpeg6.1 增加drawtext,libx264,libx265等
  • Leetcode 3648. Minimum Sensors to Cover Grid
  • OCR库pytesseract安装保姆级教程
  • LeetCode:无重复字符的最长子串
  • SQLite 加密与不加密性能对比与优化实践
  • Opsqueue:为重负载而生的轻量级批处理队列,已开源!
  • 视频因为264问题无法网页播放,解决方案之一:转化视频
  • 智创飞跃|2025 Google 开发者大会伴你成长精进
  • 兴趣爱好——虾哥开源小智AI机器人搭建(丐版—最低成本)ESP32开发板 MicroPython V1.0.0 Rev1
  • 嵌入式Linux学习 -- 进程和线程4
  • 三高架构杂谈
  • Ansible 自动化运维实践笔记:Jinja2 模板、LNMP+WordPress 部署与大项目管理
  • 飞算JavaAI智慧校园场景实践:从校园管理到师生服务的全链路技术革新
  • 【C++✨】多种 C++ 解法固定宽度右对齐输出(每个数占 8 列)
  • 常见的光源频闪控制方式
  • GitHub 热榜项目 - 日榜(2025-08-18)
  • 为什么有些相机“即插即用”,而有些则需要采集卡?
  • 联动无影(TscanPlus)送激活码
  • 短剧小程序系统开发:推动短剧行业规范化与标准化发展