理论篇:深入解析js中prototype、__proto__、constructor

前言

搞懂JS中的 prototype__proto__constructor 之间的关系是每一位前端工程师的必修课。

结合上一篇 javascript原型链继承的设计思想 继续梳理构造函数、原型和实例三者之间的关系:每个构造函数都有一个原型对象 ,原型对象都包含一个指向构造函数的指针,实例都包含一个原型对象的内部指针。

__ proto __

实例对象可以访问构造函数原型对象中的属性,它们是如何关联起来的?

一个对象的隐式原型指向构造该对象的构造函数的原型,这就保证了实例能够访问在构造函数原型中定义的属性和方法

作用 :当查找某个对象属性时,在当前对象内不存在这个属性,它可以通过__proto__去它的父对象中查找,找不到再通过父对象的__proto__对象往上找,直至原型链的终点 null

任何函数都可以看做是通过 Function()构造函数new操作实例化的结果。如果把函数Foo/Object/Function也看作是实例化对象,那么他们的构造函数都是Function

js 复制代码
Foo.__proto__ === Function.prototype  // true
Object.__proto__ === Function.prototype  // true
Function.__proto__ === Function.prototype  // true

注意:内部插槽 [[Prototype]] 可以通过 Object.getPrototypeOf()Object.setPrototypeOf() 函数来访问。这个等同于 JavaScript 的非标准但被许多 JavaScript 引擎实现的属性 __proto__ 访问器。

prototype

作用:定义所有实例共享的属性或方法

任何函数都可以看成是Function()构造函数new操作的实例化对象。那么,Function 也可以看成是调用其自身的new操作的实例化结果。如果Function作为实例对象,其构造函数是Function,其原型对象是Function.prototype,故:

js 复制代码
Function.prototype.constructor === Function  // true
Function.__proto__ === Function.prototype  // true

如果Function.prototype作为实例对象的话,其原型对象是什么呢?所有的对象都可以看成是Object()构造函数new操作的实例化结果。所以,Function.prototype的原型对象是Object.prototype,其原型函数是Object()

js 复制代码
Function.prototype.__proto__ === Object.prototype  //true
Object.prototype.__proto__ === null  // true
Function instanceof Object  // true
Object instanceof Function  // true

prototype是函数才会有的属性(注意:箭头函数没有原型对象)

js 复制代码
const fun = () => {};
console.log(fun.prototype); // undefined

constructor

constructor 是原型对象中的一个属性,这个属性包含了一个指针,指向该对象的构造函数,所有函数最终的构造函数都指向 Function

因实例对象可以继承原型对象的属性,所以实例对象也拥有constructor属性,也指向原型对象对应的构造函数

js 复制代码
function Parent() {}
function Child() {}

Child.prototype = new Parent();

const instance = new Child();
console.log(instance.constructor); // parent

任何一个prototype对象都有一个constructor属性,指向它的构造函数,Child.prototype.constructor原本应该指向Child,但执行Child.prototype = new Parent()后它指向了Parent,而访问实例对象的constructor属性时,默认调用prototype对象的constructor属性,因此实例对象的constructor也是指向的Parent。

为防止继承链混乱,我们需要手动纠正:

js 复制代码
Child.prototype.constructor = Child;
console.log(instance.constructor);  // Child

Function.__ proto __ === Function.prototype

在JavaScript中,Function本身是一个函数,也是一个对象,也是JavaScript中所有函数对象的构造函数。自然地拥有 __proto__ 属性和 prototype 属性。它由自己创建,这是JavaScript设计的一部分。这个设计意味着 Function 作为一个对象,遵循同样的原型继承规则,只是它比较特殊,它的原型链顶端就是自己的 prototype 属性。

js 复制代码
Function.constructor === Function // true
Object.constructor === Function  // true
Object.__proto__.constructor === Function  // true

总结

  • prototype是函数独有的属性(箭头函数没有原型对象),因为函数也是一种对象,所以函数也拥有__proto__和constructor属性。
  • 任何函数都可以看做是通过Function()构造函数new操作的实例化结果 所以函数可以作为实例对象,其构造函数是Function(),原型对象是Function.prototype。
  • 所有的对象都可以看成是Object()构造函数new操作的实例化结果 所以对象可以作为实例对象,其构造函数是Object(),原型对象是Object.prototype。
相关推荐
逾明12 分钟前
Electron自定义菜单栏及Mac最大化无效的问题解决
前端·electron
辰九九16 分钟前
Uncaught URIError: URI malformed 报错如何解决?
前端·javascript·浏览器
月亮慢慢圆16 分钟前
Echarts的基本使用(待更新)
前端
芜青29 分钟前
实现文字在块元素中水平/垂直居中详解
前端·css·css3
useCallback33 分钟前
Elpis全栈项目总结
前端
小高00740 分钟前
React useMemo 深度指南:原理、误区、实战与 2025 最佳实践
前端·javascript·react.js
LuckySusu1 小时前
【js篇】深入理解类数组对象及其转换为数组的多种方法
前端·javascript
LuckySusu1 小时前
【js篇】数组遍历的方法大全:前端开发中的高效迭代
前端·javascript
LuckySusu1 小时前
【js篇】for...in与 for...of 的区别:前端开发中的迭代器选择
前端·javascript
mon_star°1 小时前
有趣的 npm 库 · json-server
前端·npm·json