世界杯欧洲区预选赛_世界杯足球几年一次 - chinaacecloud.com



深入理解 JavaScript 原型与原型链:从关系图到核心逻辑

在 JavaScript 世界里,原型(Prototype)和原型链(Prototype Chain) 是理解对象继承、属性查找机制的基石。很多开发者初学时对它们 “又爱又恨”,这篇文章将结合经典关系图,用通俗易懂的方式拆解原型与原型链的核心逻辑,帮你彻底掌握这套机制!

一、先搞懂几个核心概念

在分析关系图前,先明确 JavaScript 中与原型相关的关键概念,避免后续混淆:

1. 函数对象与普通对象

函数对象:由 Function 构造出来的对象,本质是可执行的函数(比如 function Foo(){}、内置的 Object()、Function() )。

普通对象:由构造函数(如 new Foo()、new Object() )创建的实例,或直接字面量 {} 创建的对象。

关键区别:函数对象有 prototype 属性(用于关联原型对象),普通对象没有 prototype,但所有对象(包括函数对象)都有 __proto__ 属性(指向自身的原型)。

2. prototype vs __proto__ vs constructor

prototype:函数对象专属的属性,指向一个 “原型对象”。当用这个函数作为构造函数创建实例时,实例的 __proto__ 会指向该 prototype。

__proto__:所有对象(包括函数) 都有的隐式原型属性,指向当前对象的 “原型对象”,是 JavaScript 引擎实现原型链查找的关键。

constructor:原型对象 上的属性,指向创建该原型的 “构造函数”(形成循环引用,方便实例找到构造函数)。

二、拆解关系图:原型与原型链的核心链路

结合题目中的关系图,我们从 构造函数、实例对象、原型对象 三个维度,梳理它们的关联:

1. 自定义构造函数 Foo 的链路

假设我们写了一个构造函数 function Foo() {},它的原型链路是这样的:

(1)构造函数 Foo 自身

Foo 是函数对象,由 Function 构造而来(Foo = new Function(...) 的简化逻辑 )。

所以:

Foo.__proto__ → 指向 Function.prototype(函数对象的原型是 Function 的原型 )。

Foo.prototype → 指向 Foo 的 “原型对象”(Foo.prototype 是普通对象,默认包含 constructor: Foo )。

(2)Foo 的实例(f1、f2)

用 new Foo() 创建实例 f1、f2 时:

实例的 __proto__ → 指向 Foo.prototype(构造函数的 prototype 成为实例的原型 )。

所以:f1.__proto__ === Foo.prototype、f2.__proto__ === Foo.prototype。

(3)Foo.prototype 的链路

Foo.prototype 是普通对象,它的 __proto__ 指向谁?

因为所有普通对象默认由 Object 构造,所以:Foo.prototype.__proto__ → 指向 Object.prototype(普通对象的原型链路起点 )。

2. 内置构造函数 Object 的链路

Object 是 JavaScript 内置的构造函数,用来创建普通对象(如 new Object()、{} ),它的链路:

(1)构造函数 Object 自身

Object 是函数对象,同样由 Function 构造而来(Object = new Function(...) 逻辑 )。

所以:

Object.__proto__ → 指向 Function.prototype(函数对象的原型统一关联 Function.prototype )。

Object.prototype → 指向 Object 的 “原型对象”(所有普通对象的最终原型之一 )。

(2)Object 的实例(o1、o2)

用 new Object() 创建实例 o1、o2 时:

实例的 __proto__ → 指向 Object.prototype(构造函数 Object 的 prototype 是实例原型 )。

(3)Object.prototype 的链路

Object.prototype 是 JavaScript 原型链的终点之一(最顶层普通对象原型 ),所以:Object.prototype.__proto__ → 指向 null(没有更上层的原型了 )。

3. 万物之源 Function 的链路

Function 是 JavaScript 中最特殊的构造函数,所有函数对象(包括 Object、Foo、Function 自身)都由它构造,链路非常 “递归”:

(1)构造函数 Function 自身

Function 是函数对象,同时它也是自身的实例(Function = new Function(...) ,自己构造自己 )。

所以:

Function.__proto__ → 指向 Function.prototype(自己的原型指向自己的 prototype ,形成递归 )。

Function.prototype → 指向 Function 的 “原型对象”,它的 __proto__ 又指向 Object.prototype(因为 Function.prototype 本质是普通对象 )。

(2)Function.prototype 的链路

Function.prototype 是函数对象的原型,它的 __proto__:Function.prototype.__proto__ → 指向 Object.prototype(因为 Function.prototype 是普通对象,最终归属 Object 原型链 )。

三、原型链的本质:属性查找的 “追溯链”

理解了原型关联后,原型链 的作用就清晰了:

当你访问一个对象的属性(如 f1.name )时,JavaScript 引擎会:

先在对象自身找(f1 有没有 name 属性 );

如果没找到,就顺着 __proto__ 去原型对象里找(f1.__proto__ 即 Foo.prototype 里找 );

如果还没找到,继续顺着 Foo.prototype.__proto__ 去 Object.prototype 里找;

直到找到属性,或追到 __proto__ 为 null(原型链终点 ),返回 undefined。

举个例子:

js

function Foo() {}

Foo.prototype.sayHi = function() { console.log('Hi~'); };

const f1 = new Foo();

f1.toString(); // 能调用,因为:

// f1 自身没有 toString → 去 f1.__proto__(Foo.prototype)找 → 没有 → 去 Foo.prototype.__proto__(Object.prototype)找 → 找到 Object.prototype.toString

四、原型与原型链的实际应用

理解这套机制后,就能明白 JavaScript 中 “继承”“属性复用” 的底层逻辑,典型场景:

1. 原型继承

通过修改 __proto__ 或利用 prototype,让对象继承其他对象的属性:

js

const parent = { name: 'Parent' };

const child = { age: 18 };

child.__proto__ = parent;

console.log(child.name); // 从 parent 继承,输出 'Parent'

2. 构造函数复用方法

把方法挂载到 prototype 上,所有实例共享方法(节省内存):

js

function Person(name) {

this.name = name;

}

Person.prototype.sayName = function() {

console.log(this.name);

};

const p1 = new Person('Alice');

const p2 = new Person('Bob');

p1.sayName(); // Alice(p1 自身无 sayName,去 Person.prototype 找 )

p2.sayName(); // Bob

3. 理解内置对象的原型

比如数组 [] 的原型链:

js

const arr = [1, 2];

// arr.__proto__ → Array.prototype

// Array.prototype.__proto__ → Object.prototype

// 所以 arr 能调用 Array.prototype 的方法(如 push),也能调用 Object.prototype 的方法(如 toString)

五、总结:原型与原型链的核心逻辑

所有对象(包括函数) 都有 __proto__,指向自己的原型;

函数对象 额外有 prototype,用于关联实例的 __proto__;

原型链 是属性查找的链路,从自身到 __proto__ 层层追溯,直到 null;

Function 是 “函数对象的源头”,Object.prototype 是 “普通对象原型链的终点”,共同构成 JavaScript 对象体系的基石。