参考: https://blog.csdn.net/cc18868876837/article/details/81211729 码飞_cc 图解prototype,__proto__,constructor
在阅读相关内容时,原本以为自己明白了prototype用处了,结果看着看着又有了一个__proto__,瞬间懵了,然后查了相关一些博客和文档,做出自己的简易理解
相关词说明:
prototype: 属性(仅用于function类型的对象)
__proto__: 属性(前后各为两个下划线,所有js对象)
constructor: 方法(所有js对象)
js 是一种面向对象的语言,与其他语言有一个不同,在 js 编程中,连函数也是一个对象.
1. 普通对象
- 每个对象都有自己的原型,换句话说,每个对象都是继承而来的,然后再新添加其他的属性,而__proto__属性就是访问继承下来的属性.
- 每个对象的创建都有构造函数,constructor就是其构造函数
- (原型链)根据__proto__的存在,js在查找对象属性时,若找不到自身的属性,便会向上(从__proto__找到原型)继续查找属性,不断向上,直到Object的原型null
2.函数对象
js的函数也是一个对象,可以通过new 关键字 像使用构造函数一样使用这个函数
1 // 一个新的函数 2 function fun (x = 0) { 3 this.x = x 4 console.log('fun(x):' + this.x) 5 } 6 7 // 利用new 创建对象 8 var obj = new fun(1) // fun(x):1 打印字符串,执行了fun()函数 9 10 // 此时 obj 对象有 x 属性 11 obj // fun{x:1} 打印对象,创建了一个对象
从关系上,我们可以看出 obj 是由 fun ("类构造函数")生成的, 得出 obj.constructor() = fun(),通过控制台很容易得到验证
再考虑 prototype,这个属性是函数所有的,通常的使用方法:是在一个函数(比如Vue)下,挂载一些其他实例(比如axios),这样所有的Vue实例都可以直接使用axios了
// 例子再现 // Vue原型挂载(绑定)一个axios实例 Vue.prototype.$axios = axios // 新建Vue对象 var myVue = new Vue() // 新建的对象可以访问原型绑定的axios实例 myVue.$axios.get('',{}) // 基于前面代码 // 为 fun 原型添加新属性 fun.prototype.y='新属性' // 直接查看 obj obj.y // 新属性 打印字符串 // 查看obj 原型 obj.__proto__.y // 新属性 打印字符串
从两个例子,我们可以看出,若函数在prototype上直接放上了一个新的属性/方法,无论是之前建好的实例还是后建的实例,都可以直接使用它.事实上,我们可以打印obj看一下:
obj 所谓的 y 属性和 constructor 都是 __proto__ 原型链上一级的东西.或者可以说, fun.prototype === obj.__proto__ 事实证明也是如此.同时,由于前面1.3所说的特性,我们可以不通过__proto__这个属性而直接访问所谓的 y 和 constructor .
3.个人思路总结
在定义 fun 的同时,系统定义了一个 fun.prototype 的对象,建立实例就是以这个对象为原型,建立了子对象.
原型链终点,fun(fun也是对象)的原型,以及其他深层理解,可以看参考的博客
在ES6标准,新的class关键字被用上了,通过对应关系,我们可以想象 fun.prototype 就是一个"类"级别的对象,而 obj 是"实例"级别的对象, 而原型链的传递关系就是继承关系