js原型
js 原型

构造函数
构造函数与普通函数唯一的区别就是调用方式不同,构造函数也是函数,并没有把某个函数定义为构造函数的特殊语法。任何函数只要使用 new 操作符调用就是构造函数,而不使用 new 操作符调用的函数就是普通函数。实际上并不存在所谓的“构造函数”,只有对于函数的“构造调用”。
按照惯例,构造函数名称的首字母都是要大写的,非构造函数则以小写字母开头。这是从面向对象编程语言那里借鉴的,有助于在 ECMAScript 中区分构造函数和普通函数。
prototype
无论何时,只要创建一个函数,就会按照特定的规则为这个函数创建一个 prototype 属性(指向原型对象)。这个属性是一个对象,包含应该由特定引用类型的实例共享的属性和方法。实际上,这个对象就是通过调用构造函数创建的对象的原型。

1 | |

这里,所有属性和方法都直接添加到了 Person 的 prototype 属性上,构造函数体中什么也没有。但调用构造函数创建的新对象仍然拥有相应的属性和方法。使用这种原型模式定义的属性和方法是由所有实例共享的。因此 person1 和 person2 访问的都是相同的属性和相同的 sayName()函数。
constructor
默认情况下,所有原型对象自动获得一个名为 constructor 的公有并且不可枚举的属性,指回与之关联的构造函数。
即: Constructor.prototype.constructor === Constructor

1 | |

此外,我们可以看到通过“构造函数”调用 new Person() 创建的对象也有一个 .constructor 属性,指向“创建这个对象的函数”。实际上实例本身并没有 .constructor 属性。而且,虽然 person1.constructor 确实指向 Person 函数,但是这个属性并不是表示 person1 由 Person “构造”。对于引用类型来说 constructor 属性值是可以修改的。
1 | |

new 操作符调用
使用 new 来调用函数,或者说发生构造函数调用时会自动执行下面的操作:
- 在内存中创建一个新对象
- 这个新对象内部的
[[Prototype]]特性被赋值为构造函数的prototype属性 - 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)
- 执行构造函数内部的代码(给新对象添加属性)
- 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象
[[Prototype]]
JavaScript 中的对象有一个特殊的 [[Prototype]] 内置属性,其实就是对于其他对象的引用。几乎所有的对象在创建时 [[Prototype]] 属性都会被赋予一个非空的值。

这个实例的内部 [[Prototype]] 指针就会被赋值为构造函数的原型对象。脚本中没有访问这个 [[Prototype]] 特性的标准方式,但 Firefox、Safari 和 Chrome会在每个对象上暴露 __proto__ 属性,通过这个属性可以访问对象的原型。实例与构造函数原型之间有直接的联系,但实例与构造函数之间没有。

1 | |

当你试图引用对象的属性时会触发 [[Get]] 操作,对于默认的 [[Get]] 操作来说,第一步是检查对象本身是否有这个属性,如果有的话就使用它。如果无法在对象本身找到需要的属性,就会继续访问对象的 [[Prototype]] 链。如果属性找不到,并且 [[Prototype]] 链不为空的话,就会继续查找下去。这个过程会持续到找到匹配的属性名或者查找完整条 [[Prototype]] 链。因此,原型链就是对象之间通过 [[Prototype]] 属性连接起来的一条链式结构。
每个原型对象本身(默认情况下)都是使用 Object() 构造函数创建的,因此原型对象的原型是 Object.prototype 。所以,所有实例,无论类型如何,最终都会继承 Object.prototype 的属性。

Function
ECMAScript 2025 语言规范
20.2.2 Properties of the Function Constructor
The Function constructor:
- is itself a built-in function object.
- has a [[Prototype]] internal slot whose value is %Function.prototype%.
20.2.3 Properties of the Function Prototype Object
The Function prototype object:
- is %Function.prototype%.
- is itself a built-in function object.
- has a [[Prototype]] internal slot whose value is %Object.prototype%.
20.2.3.4 Function.prototype.constructor
The initial value of Function.prototype.constructor is %Function%.
Function.__proto__ 指向 Function.prototype, 这会导致 Function.constructor === Function,也就是说:函数就是它自己的构造函数!

Object
ECMAScript 2025 语言规范
20.1.1 The Object Constructor
The Object constructor:
- is %Object%.
- is the initial value of the “Object” property of the global object.
20.1.2 Properties of the Object Constructor
The Object constructor:
- has a [[Prototype]] internal slot whose value is %Function.prototype%.
20.1.3 Properties of the Object Prototype Object
The Object prototype object:
- is %Object.prototype%.
has a [[Prototype]] internal slot whose value is null.

参考
- ECMAScript:Properties of the Function Constructor
- ECMAScript:Properties of the Function Prototype Object
- ECMAScript:Function.prototype.constructor
- JavaScript Object Layout
- 《JavaScript 高级程序设计 第 4 版》
- 《你不知道的 JavaScript(上卷)》