js原型

js 原型

构造函数

构造函数与普通函数唯一的区别就是调用方式不同,构造函数也是函数,并没有把某个函数定义为构造函数的特殊语法。任何函数只要使用 new 操作符调用就是构造函数,而不使用 new 操作符调用的函数就是普通函数。实际上并不存在所谓的“构造函数”,只有对于函数的“构造调用”。

按照惯例,构造函数名称的首字母都是要大写的,非构造函数则以小写字母开头。这是从面向对象编程语言那里借鉴的,有助于在 ECMAScript 中区分构造函数和普通函数。

prototype

无论何时,只要创建一个函数,就会按照特定的规则为这个函数创建一个 prototype 属性(指向原型对象)。这个属性是一个对象,包含应该由特定引用类型的实例共享的属性和方法。实际上,这个对象就是通过调用构造函数创建的对象的原型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Person() {}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function () {
console.log(this.name);
};
let person1 = new Person();
person1.sayName(); // "Nicholas"
let person2 = new Person();
person2.sayName(); // "Nicholas"
console.log(person1.sayName == person2.sayName); // true

debugger;

这里,所有属性和方法都直接添加到了 Person 的 prototype 属性上,构造函数体中什么也没有。但调用构造函数创建的新对象仍然拥有相应的属性和方法。使用这种原型模式定义的属性和方法是由所有实例共享的。因此 person1 和 person2 访问的都是相同的属性和相同的 sayName()函数。

constructor

默认情况下,所有原型对象自动获得一个名为 constructor 的公有并且不可枚举的属性,指回与之关联的构造函数。

即: Constructor.prototype.constructor === Constructor

1
2
3
4
5
6
7
8
9
10
11
12
13
function Person() {}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function () {
console.log(this.name);
};
let person1 = new Person();
let person2 = new Person();
console.log(person1.constructor);
console.log(person2.constructor);

debugger;

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function ParentConstructor(name) {
this.name = name;
}
ParentConstructor.prototype.getName = function () {
console.log(this.name);
};
function ChildConstructor(name, age) {
this.age = age;
ParentConstructor.call(this, name);
}
ChildConstructor.prototype = Object.create(ParentConstructor.prototype);

const instance = new ChildConstructor("Zhangsan", 20);

console.log(instance.constructor);
debugger;

new 操作符调用

使用 new 来调用函数,或者说发生构造函数调用时会自动执行下面的操作:

  1. 在内存中创建一个新对象
  2. 这个新对象内部的 [[Prototype]] 特性被赋值为构造函数的 prototype 属性
  3. 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)
  4. 执行构造函数内部的代码(给新对象添加属性)
  5. 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象

[[Prototype]]

JavaScript 中的对象有一个特殊的 [[Prototype]] 内置属性,其实就是对于其他对象的引用。几乎所有的对象在创建时 [[Prototype]] 属性都会被赋予一个非空的值。

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

1
2
3
4
5
6
7
function Personal(name) {
this.name = name;
}

const person1 = new Personal("Alice");
console.log(person1.__proto__ === Personal.prototype); // true
debugger;

当你试图引用对象的属性时会触发 [[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.

参考


js原型
https://www.my-web.cn/js/prototype/
发布于
2026年6月2日
许可协议