JavaScript 原型系统:深入理解内置原型

JavaScript 原型系统:深入理解内置原型

ru.javascript.info Современный учебник JavaScript ru.javascript.info 项目地址: https://gitcode.com/gh_mirrors/ru/ru.javascript.info

引言

在 JavaScript 中,原型系统是实现继承的核心机制。理解内置对象的原型结构对于掌握 JavaScript 至关重要。本文将深入探讨 JavaScript 内置原型的工作原理,包括对象、数组、函数等内置类型的原型链结构。

对象原型(Object.prototype)

当我们创建一个空对象时:

let obj = {};
console.log(obj.toString()); // "[object Object]"

这个 toString() 方法从何而来?答案就在原型链中:

  1. 字面量 {} 等同于 new Object()
  2. 新创建的对象会自动继承 Object.prototype 的属性和方法
  3. toString() 正是定义在 Object.prototype 上的方法

原型链关系可以用以下图示表示:

obj -> Object.prototype -> null

我们可以验证这一点:

console.log(obj.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__); // null

其他内置原型

JavaScript 中的其他内置类型(Array、Date、Function 等)都有类似的机制:

  • 数组方法存储在 Array.prototype
  • 日期方法存储在 Date.prototype
  • 函数方法存储在 Function.prototype

以数组为例:

let arr = [1, 2, 3];

console.log(arr.__proto__ === Array.prototype); // true
console.log(arr.__proto__.__proto__ === Object.prototype); // true
console.log(arr.__proto__.__proto__.__proto__); // null

完整的原型链如下:

arr -> Array.prototype -> Object.prototype -> null

方法覆盖现象

当原型链上存在同名方法时,JavaScript 会优先使用最近的方法。例如:

let arr = [1, 2, 3];
console.log(arr.toString()); // "1,2,3" (来自 Array.prototype)

虽然 Object.prototype 也有 toString() 方法,但数组使用的是 Array.prototype 上专门为数组优化的版本。

原始值的特殊处理

字符串、数字和布尔值虽然是原始类型,但当我们尝试访问它们的属性时,JavaScript 会临时创建对应的包装对象:

  • 字符串 → String 包装对象
  • 数字 → Number 包装对象
  • 布尔值 → Boolean 包装对象

这些包装对象的方法都存储在对应的原型上:

String.prototype.show = function() {
  console.log(this);
};

"Hello".show(); // String {'Hello'}

注意:nullundefined 没有对应的包装对象和原型方法。

修改内置原型的注意事项

虽然可以修改内置原型(如添加新方法),但这通常是不推荐的,原因包括:

  1. 命名冲突风险:不同库可能添加同名方法
  2. 维护困难:代码行为可能变得难以预测
  3. 性能影响:可能干扰 JavaScript 引擎的优化

唯一例外的情况是创建polyfill(为尚未实现的标准方法提供兼容实现):

if (!String.prototype.repeat) {
  String.prototype.repeat = function(n) {
    return new Array(n + 1).join(this);
  };
}

方法借用技巧

我们可以从其他对象的原型"借用"方法。例如,让类数组对象使用数组的方法:

let arrayLike = {
  0: "Hello",
  1: "World",
  length: 2
};

arrayLike.join = Array.prototype.join;
console.log(arrayLike.join(',')); // "Hello,World"

这种技巧利用了 JavaScript 方法的通用性——许多数组方法只要求对象具有 length 属性和数字键。

总结

  1. 原型存储方法:所有内置对象的方法都存储在对应的原型对象上
  2. 原型链结构:内置类型的原型链最终都指向 Object.prototype
  3. 原始值处理:字符串、数字、布尔值通过临时包装对象访问原型方法
  4. 原型修改原则:除非实现 polyfill,否则避免修改内置原型
  5. 方法借用:可以灵活地从其他原型借用方法

理解这些概念将帮助你更深入地掌握 JavaScript 的面向对象特性,并编写更健壮的代码。

ru.javascript.info Современный учебник JavaScript ru.javascript.info 项目地址: https://gitcode.com/gh_mirrors/ru/ru.javascript.info

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

虞宜来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值