为何JS内置对象Function与Object互为实例?如何实现?
JavaScript中Function与Object互为实例的困惑及自定义实现验证
一、Function与Object互为实例的代码验证
下面的代码可以验证Function是Object的实例:
// 以下代码展示 Function 是 Object 的实例 Function instanceof Object; // true Object.prototype.isPrototypeOf.call(Function.prototype, Object); // true Function.prototype.isPrototypeOf(Object); // true
下面的代码可以验证Object是Function的实例:
// 以下代码展示 Object 是 Function 的实例 Object instanceof Function; // true Object.prototype.isPrototypeOf.call(Object.prototype, Function); // true Object.prototype.isPrototypeOf(Function); // true
另外,以下代码证明Function.__proto__和Object.__proto__指向内存中的同一个对象:
// 以下代码表明 Function.__proto__ 和 Object.__proto__ 指向内存中的同一个对象 Object.is(Function.__proto__, Object.__proto__); // true Object.getPrototypeOf(Function) === Object.getPrototypeOf(Object); // true Function.constructor.prototype === Object.constructor.prototype; // true Function.__proto__ === Object.__proto__; // true
同时,Function和Object的MDN文档显示二者存在互相继承的关系。
二、核心疑惑
按传统OOP的逻辑,实例是由类初始化生成的,但类不该由实例来初始化生成。我知道JavaScript是基于原型的面向对象编程,和Python这类传统OOP语言不同,但还是没法理解为什么Function与Object会互为实例,这在逻辑上是否属于怪异的设计?
三、自定义类互为实例的尝试
我尝试实现两个自定义类互为实例,下面的示例是否正确?
// 让 MyClass1 和 MyClass2 互为实例的示例 class MyClass1 { constructor() {} } class MyClass2 { constructor() {} } Object.setPrototypeOf(MyClass1, MyClass2.prototype); Object.setPrototypeOf(MyClass2, MyClass1.prototype); // 验证 MyClass1 是 MyClass2 的实例 MyClass1 instanceof MyClass2; // true Object.prototype.isPrototypeOf.call(MyClass2.prototype, MyClass1); // true MyClass2.prototype.isPrototypeOf(MyClass1); // true // 验证 MyClass2 是 MyClass1 的实例 MyClass2 instanceof MyClass1; // true Object.prototype.isPrototypeOf.call(MyClass1.prototype, MyClass2); // true MyClass1.prototype.isPrototypeOf(MyClass2); // true
四、解答
1. 为什么Function与Object互为实例?
这是JavaScript原型链体系的固有特性,并不存在逻辑怪异的问题:
- Object是Function的实例:JS中所有内置构造函数(包括Object)都是由Function构造出来的,所以
Object instanceof Function为true; - Function是Object的实例:JS中所有函数本质上都是对象,所有对象最终都继承自
Object.prototype,Function作为函数对象,自然属于Object的实例,所以Function instanceof Object为true。
这种看似循环的关系,根源在于JS的“函数即对象”设计——函数同时具备函数和对象的双重特性,这和传统类式OOP的严格类/实例划分完全不同。
2. 自定义类互为实例的代码是否正确?
你的实现完全正确。instanceof的判断逻辑是右侧构造函数的prototype是否存在于左侧对象的原型链上:
- 通过
Object.setPrototypeOf(MyClass1, MyClass2.prototype),将MyClass1的原型指向MyClass2的原型对象,此时MyClass2的prototype出现在MyClass1的原型链上,所以MyClass1 instanceof MyClass2返回true; - 同理,设置MyClass2的原型为MyClass1的
prototype后,MyClass2 instanceof MyClass1也会返回true。
不过这种互为实例的设计在实际开发中几乎没有实用场景,更多是用于加深对JS原型链底层逻辑的理解。
内容的提问来源于stack exchange,提问作者Lucas
相关产品推荐
相关产品推荐

