# 🌟 JavaScript原型与原型链终极指南:从Function到Object的完整闭环解析 ,深入理解JavaScript原型系统核心
深入理解JavaScript原型系统核心
📖 目录
🎯 核心概念
四大基本原则
-
原则一:每个对象都有构造函数(constructor)
- 指向构建该对象或实例的函数
-
原则二:只有函数对象才有prototype属性
- 非函数对象没有prototype属性
- 实例只有
__proto__属性 - 两者指向同一个对象(函数的原型对象)
-
原则三:Function函数是所有函数的构造函数
- 包括它自己
- 代码中声明的所有函数都是Function的实例
-
原则四:Object也是函数
- 所以Object也是Function函数的实例
实例,函数,对象,原型对象,构造函数,关系总览图
🔍 非函数对象分类
- 实例对象,
const person = new Foo(),person就是实例对象 - 普通对象(
{}或new Object()) - 内置非函数对象实例
🔄 显式原型与隐式原型
对象分类
-
函数对象:拥有
prototype属性 -
非函数对象:只有
__proto__属性
相同点
- 都指向同一个原型对象
📝 示例代码
function Person(){}
const person = new Person();
console.log("Person.prototype指向:", Person.prototype)
console.log("person.__proto__指向", person.__proto__)
🖼️ 执行结果
🎯 构造函数的指向
默认情况
function Person(){}
const person = new Person();
console.log("Person.prototype.constructor指向", Person.prototype.constructor)
// 输出:[Function: Person]
执行结果
修改原型对象后
function Person(){}
const person = new Person();
Person.prototype = new foo(); // 修改原型对象
console.log("Person.prototype.constructor指向", Person.prototype.constructor)
// 输出:[Function: foo]
执行结果
📊 核心原理说明
解释
Person.prototype被当作函数foo的实例,继承了foo函数(此篇不展开继承详解)
总结规律
- 每个原型对象或实例都有
.constructor属性 - 实例通过原型链查找constructor
- 原型对象默认指向自身的函数(如果不是其他函数的实例)
查找过程示例
// Person.prototype被当作实例时
Person.prototype.__proto__ → foo.prototype → foo()
🖼️ 可视化关系图
三者关系图
🔬 代码验证
function Person(){}
// 创建新的原型对象
Person.prototype = {
name: "杨",
age: "18",
histype: "sleep"
}
// 添加方法
Person.prototype.print = function(){
console.log("你好我是原型对象");
}
// 创建实例
const person01 = new Person();
const person02 = new Person();
// 验证指向
console.log("Person.prototype指向:", Person.prototype)
console.log("person01.__proto__指向", person01.__proto__)
console.log("person02.__proto__指向", person02.__proto__)
console.log("Person.prototype.constructor指向", Person.prototype.constructor)
执行结果
⚠️ 特别说明
关键细节
创建新对象时,Person.prototype.constructor指向Object,因为Person.prototype成了Object的实例。
对比情况
-
创建新对象时:
Person.prototype.constructor→Object -
未创建新对象时:
Person.prototype.constructor→Person
示意图
Function和Object
小故事
从前有个力大无穷的大力神,能举起任何东西,有一天,小A在路上和这个大力神相遇了。
大力神:小子,我可是力大无穷的大力神,我能举起任何东西,你信不信?
小A:呦呦呦,还大力神,你说你能举起任何东西,那你能把你自己抬起来吗?
...
-
Function是所有函数的加工厂,你在代码声明的所有函数都是Function的实例,包括Function函数本身,Object也是函数,所以它也是Functiod的实例
-
Function就是这样的大力神,而且是可以把自己抬起来的大力神,这听起来比较扯,但是这就是事实,请看VCR:
function Person (){}
const person01 = new Person();
console.log("Function.__proto__指向",Function.__proto__)//Function.__proto__指向 [Function (anonymous)] Object
console.log("Function.prototype指向",Function.prototype)//Function.prototype指向 [Function (anonymous)] Object
console.log("Function.__proto__ == Function.prototype???",Function.__proto__ == Function.prototype)
//Function.__proto__ == Function.prototype??? true
Object 在 JavaScript 中扮演三重角色:
-
构造函数:用于创建对象
-
命名空间:提供一系列静态方法用于对象操作
-
原型终点:Object.prototype 是所有原型链的终点,在往上没有了,值==null
请看VCR:
function Person (){};
const persoon01 = new Person();
const obj = {};//通过对象字面量{}创建obj实例
const obj1 = new Object();//通过构造函数new Object()创建obj1实例
const obj2 = Object.create(Object.prototype);//通过委托创建,或者叫原型创建,来创建obj2实例
console.log("Person.prototype.__proto__指向",Person.prototype.__proto__);
//Person.prototype.__proto__指向 [Object: null prototype] {}
console.log("Function.prototype.__proto__指向",Function.prototype.__proto__)
//Function.prototype.__proto__指向 [Object: null prototype] {}
console.log("通过对象字面量{}创建的obj实例,obj.__proto__指向",obj.__proto__);
//通过对象字面量{}创建的obj实例,obj.__proto__指向 [Object: null prototype] {}
console.log("通过构造函数new Object()创建obj1实例,指向",obj1.__proto__);
//通过构造函数new Object()创建obj1实例,指向 [Object: null prototype] {}
console.log("通过委托创建,或者叫原型创建,来创建obj2实例,指向",obj2.__proto__);
//通过委托创建,或者叫原型创建,来创建obj2实例,指向 [Object: null prototype] {}
Function和Object的关系
- 相互依赖的循环引用
-
Object 是 Function 的实例(构造函数层面)
-
Function 是 Object 的子类(原型继承层面)
-
这是 JavaScript 的自举(Bootstrap)机制
-
根据关系总览图,我们可以看到,Function和Object,它们两形成了一个闭环,将所有的函数和对象都包裹在这个闭环里
📋 JavaScript 原型系统核心概念表
| 概念 | 描述 | 示例 | 特殊说明 |
|---|---|---|---|
| prototype | 函数特有,指向原型对象 | Person.prototype |
只有函数对象才有此属性 |
| proto | 所有对象都有,指向构造函数的原型 | person.__proto__ |
实际应使用 Object.getPrototypeOf()
|
| constructor | 指向创建该对象的构造函数 | Person.prototype.constructor |
可被修改,查找时沿原型链进行 |
| 原型链查找 | 通过 __proto__ 逐级向上查找 |
person.__proto__.__proto__ |
终点为 null
|
| Function | 所有函数的构造函数 | Function.prototype |
Function.__proto__ === Function.prototype |
| Object | 所有对象的基类 | Object.prototype |
原型链终点,Object.prototype.__proto__ === null
|
🔍 补充说明
prototype 补充
- 函数的
prototype属性默认包含constructor属性指向函数自身 - 用于实现基于原型的继承
proto 补充
- 现在更推荐使用
Object.getPrototypeOf(obj)和Object.setPrototypeOf(obj, proto) -
__proto__是访问器属性,不是数据属性
constructor 补充
-
constructor属性可以通过原型链查找 - 示例:
person.constructor === Person(实际查找的是person.__proto__.constructor)
原型链查找补充
- 当访问对象属性时,如果对象自身没有,会沿着原型链向上查找
- 直到找到该属性或到达原型链终点
null
Function 补充
- 是所有函数的构造函数,包括内置构造函数(Object、Array等)和自定义函数
- 自身也是函数,所以
Function.__proto__ === Function.prototype
Object 补充
-
Object.prototype是所有原型链的最终原型对象 - 通过
Object.create(null)可以创建没有原型的"纯净对象"
💡 记忆口诀
- 函数看prototype,实例看__proto__
- constructor找根源,原型链上寻答案
- Object是终点,Function是关键
结语:
看完这篇文章,你应该可以读懂上面的关系总览图了,望学习愉快!!!