深入理解JavaScript原型链:[[prototype]]与prototype的区别
本文解析JavaScript原型链机制,区分[[prototype]]内部槽与prototype属性。通过代码示例说明实例对象、构造函数与Function.prototype的关系,阐述Object.create和setPrototypeOf对原型链的影响,并澄清行为委托基于[[prototype]]链的本质。
JavaScript语言特性与原型继承基础
JavaScript语言在设计时融合了多种编程语言的特性:其语法风格参考了Java,函数机制借鉴自Scheme,原型继承概念源自Self语言,而正则表达式则取自Perl(参考《JavaScript语言精粹》)。
[[prototype]]内部槽与prototype属性的区别
JavaScript是一种基于原型继承的面向对象语言。在该语言中,数组、函数以及通常意义上的“对象”本质上都是对象。每个对象内部都包含一个名为[[prototype]]的内部槽位,这是构建原型链的核心机制。虽然可以为对象设置prototype属性,但这只是表层现象,其背后隐藏着更复杂的机制。
可以使用isPrototypeOf()方法检测某个对象是否位于另一个对象的原型链上,但该方法的判断依据依然是基于[[prototype]]链的结构。
原型链关系代码示例分析
以下通过具体代码示例进行说明:
//建立一个函数
function foo () {}
//修改函数的prototype property
foo.prototype = {
name : "foo.prototype"
};
//建立一个实例
var a = new foo();
//重写 a 的默认原型,本应该是foo.prototype.
a.prototype = {
name : "a.prototype"
};
接下来探讨一个问题:foo.prototype是否等同于a的原型?
需要分情况讨论:一方面,a.prototype确实被赋值为{name : "a.prototype"};但另一方面,foo.prototype.isPrototypeOf(a)的返回结果为true。
具体关系如下:使用“--->”表示不明显的[[prototype]]链指向,使用“---”表示prototype属性关系。
Function ---> Function.prototype--->Object.prototype
Function.prototype <--- foo---foo.prototype ------>Object.prototype 。
内置类型与构造函数的原型关系
此外,Number、Boolean、String等内置类型的[[prototype]]均指向Function.prototype对象。Function.prototype对象本身类型为“function”,由于内部不包含[[construct]]能力,因此不能直接作为构造函数使用;实际上它类似于一个空函数function () {}。类型为“function”的对象除了拥有[[prototype]]内部槽外,还具备prototype属性。每个函数都会自动关联一个prototype对象:this.prototype = {constructor:this}(这是一个普通对象)。该普通对象的[[prototype]]连接到Object.prototype。
那么,由构造函数创建的实例对象的[[prototype]]是否指向Object.prototype?
该实例的[[prototype]]是由构造函数的prototype属性初始化的,注意这里指的是函数的prototype属性,而非函数自身的[[prototype]]。因此,如果对象是由Object函数构造的,那么其[[prototype]]确实指向Object.prototype。
Object本身是一个函数,其prototype属性指向著名的Object.prototype(这看似显而易见),但Object函数自身的[[prototype]]指向Function.prototype。具体关系如下:
Object----->Function.prototype------>Object.prototype.
修改原型链的方法与行为委托
如何修改这个[[prototype]]链?
可以采用var a = Object.create(obj)的形式,或者使用Object.setPrototypeOf(objA,objB)的形式。此处不再列举具体例子,因为关系较为简单;且仅举出一些生硬的示例并无实际意义。
最后一个问题:行为委托是否基于[[prototype]]链?
是的,行为委托正是基于[[prototype]]链实现的。
JavaScript怎么遍历对象的Symbol键和不可枚举属性
2026-11-05 13:13:39
封装一个健壮的JS字符串判空工具函数
2026-11-05 12:16:14
JavaScript合并数组的三种常用方法:concat、扩展运算符与push
2026-11-05 11:22:29
JavaScript立即执行函数(IIFE)是什么及基本语法
2026-11-05 10:51:19
JS对象数组转字符串为什么推荐用JSON.stringify()
2026-11-05 09:40:31
