理论篇:深入解析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。
相关推荐
开心工作室_kaic1 分钟前
ssm068海鲜自助餐厅系统+vue(论文+源码)_kaic
前端·javascript·vue.js
有梦想的刺儿20 分钟前
webWorker基本用法
前端·javascript·vue.js
cy玩具41 分钟前
点击评论详情,跳到评论页面,携带对象参数写法:
前端
清灵xmf1 小时前
TypeScript 类型进阶指南
javascript·typescript·泛型·t·infer
小白学大数据1 小时前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫
qq_390161771 小时前
防抖函数--应用场景及示例
前端·javascript
334554322 小时前
element动态表头合并表格
开发语言·javascript·ecmascript
John.liu_Test2 小时前
js下载excel示例demo
前端·javascript·excel
Yaml42 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
PleaSure乐事2 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro