js中先有Function,还是先有Object?

1,903 阅读3分钟

「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战

Function 和 Object 的微妙关系

在 JavaScript 中存在着两个关系很微妙的类,那就是 Function 和 Object,为什么说他们的关系微妙? 因为 Function instanceof ObjectObject instanceof Function 的值同时为 true

instanceof

instanceof运算符用于测试构造函数的prototype属性是否出现在对象的原型链中的任何位置

Function

Function 构造函数 创建一个新的Function对象。在 JavaScript 中, 每个函数实际上都是一个Function对象。

Object

Object 构造函数创建一个对象包装器。Object构造函数为给定值创建一个对象包装器。如果给定值是 null 或 undefined,将会创建并返回一个空对象,否则,将返回一个与给定值对应类型的对象。
当以非构造函数形式被调用时,Object 等同于 new Object()。

Object.prototype.constructor

返回创建实例对象的 Object 构造函数的引用。注意,此属性的值是对函数本身的引用,而不是一个包含函数名称的字符串。对原始类型来说,如1,true和"test",该值只可读。

也就是说他们的原型链上相互包含对方,要知道原型链间接的描述了对象之间的继承关系。

如果 Object 在 Function 的原型链上,则可以认为 Object 是 Function 的实例。

image.png

Object 是一个类或者构造函数,所以说他是一个函数的实例很合理

但是同时 Function instanceof Object 也为 true,着表面 Object 也在 Function 的原型链上,那么也可以说 Function 是 Object 是实例。

万物皆对象,这好像也没有问题

但是他们到底谁才是谁的实例?谁先诞生的呢?这无疑是一个先有鸡还是先有蛋的问题。

image.png

但是下面的代码好像在告诉我们,Function 不是 Object 的实例对象,而是 Function 本身的实例

Function.constructor === Object //false
Function.constructor === Function //true
Object.constructor === Function //true

但是事实是什么呢?

起源

盘古开天辟地,js 中并不是就有了 Object,而是 Object.prototype

js 中的万物(原始值除外)都是继承自 Object ,唯独一个对象例外,那就是 Object.prototype

Object instanceof Object;  //true
Object.prototype instanceof Object; // false 

JS 中没有类,当我们说一个变量是另一个变量的实例时,我们在说什么?( instanceof 比较的是什么?)

借助 Object.create 我们有以下的栗子:

var p = {test:1}
var obj = Object.create(p)
function A(){}
obj instanceof A  //false
A.prototype = p
obj instanceof A  //true 

当我们说一个对象继承自某个 Constructor 时,其实我们是在说,从这个对象的原型链上找到了 Constructor.prototype。

所以,Object.prototype 可以先于 Object 出现,然后用这个 prototype 构造出 Function.prototype,有了 Function.prototype 再构造出 Function , Object 这几个构造器。然后把 Object.prototype 挂到 Object 上,Function.prototype 挂到Function 上。

好比栗子中的 obj 构造自 p ,而 obj 构造出来之后,p 才挂到 A 上,我们说 obj 是 A 类型的,但是 obj 是用 A.prototype(就是 p ) 构造出来的。

分析可得:全局下的 Object 构造自 Function.prototype, Function.prototype 构造自 Object.prototype。

Object.getPrototypeOf(Object) === Function.prototype   //全等哦
Object.getPrototypeOf(Function.prototype) === Object.prototype  //全等哦 

所以,是先有的 Object.prototype,再有的 Function.prototype ,再有的 Function 和 Object。

伪代码大致是这样,create 元操作的含义是使用给定的对象作为原型构造一个新的对象。

let ObjectPrototype = create( );   // C++开天辟地
 
let FunctionPrototype = create( ObjectPrototype );   
//FunctionPrototype(后被赋值给了Function.prototype)是Object类型的
//因为其原型是ObjectPrototype
 
let Function = create( FunctionPrototype );
 
Function.prototype = FunctionPrototype;
 // Function是Function类型的,也是Object类型的
//言外之意,Function对象 原型链上有Function.prototype和Object.prototype
 
Object =  create( FunctionPrototype ); 
 
Object.prototype = ObjectPrototype;
 //Object是Function类型的,也是Object类型的
//言外之意Object对象的原型链上有Function.prototype和Object.prototype 

当然,在构造 Function 的时候远没有那么简单,这里只是简单解释了一下 Object 和 Function 之间错综复杂的关系。