元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
执行上下文
▶
创建过程
变量对象
作用域链
This绑定
▶
执行阶段
执行栈机制
词法环境
闭包实现
▶
内存管理
▶
内存模型
堆栈结构
内存分配
内存泄漏
▶
回收机制
标记清除
引用计数
代际假说
▶
事件循环
▶
运行机制
调用栈解析
任务队列
微任务优先
▶
异步处理
Promise原理
Async/Await
Web Workers
▶
原型系统
▶
原型基础
原型链机制
__proto__属性
构造函数
▶
类继承
ES6类语法
继承实现
super关键字
▶
类型系统
▶
基础类型
类型检测
装箱拆箱
类型转换
▶
高级类型
Symbol特性
BigInt实现
类型数组
▶
作用域与闭包
▶
作用域体系
词法作用域
动态作用域
作用域链生成
▶
闭包机制
闭包存储结构
IIFE模式原理
内存泄漏防范
发布时间:
2025-03-22 11:44
↑
☰
# JavaScript __proto__属性详解 __proto__属性是JavaScript中访问对象原型的传统方式。本文将深入讲解__proto__属性的工作原理、使用场景和最佳实践。 ## __proto__基础概念 __proto__是对象的一个内部属性,指向该对象的原型。虽然现代JavaScript不推荐直接使用__proto__,但理解它的工作原理对于掌握原型继承很有帮助。 ```javascript // 基本示例 const animal = { eat: true }; const rabbit = { jump: true }; // 设置原型 rabbit.__proto__ = animal; console.log(rabbit.eat); // true console.log(rabbit.jump); // true ``` ## __proto__工作原理 ### 1. 属性访问机制 ```javascript class ProtoAccess { static demonstrate() { const proto = { method: function() { return 'method from proto'; } }; const obj = { __proto__: proto }; // 属性查找过程 console.log(obj.method()); // 'method from proto' console.log(obj.hasOwnProperty('method')); // false console.log(obj.__proto__.hasOwnProperty('method')); // true } } ``` ### 2. 原型链遍历 ```javascript class ProtoChainTraversal { static traverse(obj) { let current = obj; const chain = []; while (current) { chain.push(current); current = Object.getPrototypeOf(current); } return chain; } static demonstrate() { class Animal {} class Mammal extends Animal {} class Dog extends Mammal {} const dog = new Dog(); const chain = this.traverse(dog); // 输出原型链 chain.forEach((proto, index) => { console.log(`Level ${index}:`, proto.constructor.name); }); } } ``` ## 现代替代方案 ### 1. Object.getPrototypeOf/setPrototypeOf ```javascript class ModernProtoAccess { static demonstrate() { const proto = { greet() { return 'Hello!'; } }; const obj = {}; // 设置原型 Object.setPrototypeOf(obj, proto); // 获取原型 const objProto = Object.getPrototypeOf(obj); console.log(obj.greet()); // 'Hello!' console.log(objProto === proto); // true } } ``` ### 2. Object.create ```javascript class ObjectCreateExample { static demonstrate() { const proto = { calculate(x, y) { return x + y; } }; // 创建以proto为原型的新对象 const calculator = Object.create(proto); console.log(calculator.calculate(2, 3)); // 5 console.log(Object.getPrototypeOf(calculator) === proto); // true } } ``` ## 性能考虑 ### 1. 动态原型修改 ```javascript class PerformanceImpact { static demonstrateImpact() { class Shape { constructor(color) { this.color = color; } } const shape1 = new Shape('red'); const shape2 = new Shape('blue'); // 不好的实践 - 运行时修改原型 shape1.__proto__.draw = function() { console.log(`Drawing ${this.color} shape`); }; // 好的实践 - 在类定义时设置方法 class BetterShape { constructor(color) { this.color = color; } draw() { console.log(`Drawing ${this.color} shape`); } } } } ``` ### 2. 原型链查找开销 ```javascript class LookupPerformance { static demonstrate() { const proto = { expensiveMethod() { return Math.random(); } }; const obj = Object.create(proto); // 不好的实践 - 频繁查找原型链 for (let i = 0; i < 1000; i++) { obj.expensiveMethod(); } // 好的实践 - 本地缓存方法 const method = obj.expensiveMethod; for (let i = 0; i < 1000; i++) { method.call(obj); } } } ``` ## 最佳实践 ### 1. 避免直接使用__proto__ ```javascript class BestPractices { static demonstrate() { // 不推荐 const bad = { __proto__: { method() {} } }; // 推荐 const good = Object.create({ method() {} }); // 或者使用类 class Better { method() {} } } } ``` ### 2. 原型安全 ```javascript class PrototypeSecurity { static secureCoding() { // 防止原型污染 function safeClone(obj) { return Object.create(null, Object.getOwnPropertyDescriptors(obj)); } // 冻结原型 function freezePrototype(obj) { let proto = Object.getPrototypeOf(obj); while (proto) { Object.freeze(proto); proto = Object.getPrototypeOf(proto); } } // 示例 const data = safeClone({ name: 'John', age: 30 }); freezePrototype(data); } } ``` ## 总结 关于JavaScript中的__proto__属性,我们需要记住: 1. __proto__是访问对象原型的传统方式 2. 现代JavaScript提供了更好的替代方案 3. 直接使用__proto__可能带来性能问题 4. 应该使用标准的原型操作方法 5. 注意原型安全,防止污染 在实际开发中,我们应该: 1. 优先使用Object.getPrototypeOf/setPrototypeOf 2. 使用Object.create创建对象 3. 避免运行时修改原型 4. 注意原型链查找性能 5. 实现必要的原型安全措施