prototype与__proto__的区别

140 阅读3分钟

对于一个小时候喜欢抄作业,长大喜欢抄代码的学渣来说 js 三个大山之一原型,哪怕是已经了解vue react还是有难度的,能抄抄,为什么要动脑呢? 哈哈哈哈
(正经脸)嗯~为了抄更好的代码

什么原型(prototype)

编程就是拒绝重复
简单的来说原型是一个对象用于存放某对象的公用属性和方法
拒绝重复开辟新的内存空间存放那些经常会用到的属性和方法

原型

为什么要用原型

废话不多说看代码
假设我们现在有一个需求,输入一个数字返回一个对象,这个对象有它自身的宽度还有计算它的面积的方法

let getArea = function (width){
   let obj = {}
   obj.width = width
   obj.getValue = function(){
       return this.width * this.width
   }
   return obj
}
let demo1 = getArea(6)
demo1.getValue()

如果这个代码只用一次那就没啥问题,可是如果只用一次,何必用函数封装起来,所以函数的目的是复用,对吧
继续:

//假设我们现在要计算5个不同的正方形,或者更多正方形
//嗯,你可以写5次调用也可以用循环,结果都一样
//计算方法不变
let getArea = function (width){
   let obj = {}
   obj.width = width
   obj.getValue = function(){
       return this.width * this.width
   }
   return obj
}

let result = []
let list = [5,6,9,10,20]
for (let i=0;i<list.length;i++){
    result[i] = getArea(list[i])
}
result[0].getValue()//得到结果

如果你对内存方面有所了解,你应该知道我们这么干,太浪费内存了。
不知道?看图

内存图
让我们用原型的方法实现这个功能

function GetArea(width) {
    this.width = width
}
GetArea.prototype.getValue = function () {
    return this.width * this.width
}
let demo1 = new GetArea(6)
demo1.getValue()

当我们把getValue() 这方法放到prototype原型对上身上以后每次就不会开辟新的内存空间,每次使用这个函数会在其构造函数的原型身上调用该函数

原型之windwo 中的Function Array Object

知道了为什么要用原型以及怎么用原型,那我们了解下window中的Function Array Object的原型关系吧
首先这三个都是构造函数对吧
所以我们第一条公式来了

该对象的.__proto__ === 其构造函数的.prototyope

这句话我们用中文可以理解为 当前对象(不要忘记函数也是对象的一种哦)的原型对象 等于 其构造函数的地址
let array = []//等价于 new Array()
array.__proto__ === Array.prototype //输出true

function say(){console.log('人活着的意义...')} //等价 new Function
say.__proto__ === Function.prototype //输出true

let ojbk = {} // 等价于new Object
ojbk.__proto__ === Object.prototype //输出true

原型链

知道了上面这些,你可能会更懵逼 那Function的原型又是啥呢? Array的原型又是啥呢? Object的原型又是神马东东?
来,看图

原型链
如果你懒得看图或者看不懂我的凤凰傲意图(小鸡吃米图)

凤凰傲意图
那么...继续记结论吧,然后自己去控制台推答案

该对象的.__proto__ === 其构造函数的.prototyope
Object.prototype是所有对象直接或间接的原型
所有函数的.__proto === Function.prototype

原型链就拿下面代码来举例吧
function Fn (){console.log('随便打个啥吧')}
let f = new Fn()
f.__proto__ === Fn.prototype //我是构造函数Fn构造的对吧 所以我的原型就是Fn嘛
Fn.__proto__ === Function.prototype //我是Function构造的吧,那我的原型就是Function 咯
Function.prototype.__proto__ === Object.prototype //我虽然是我自己构造的,但是我原型对象地址里面的原型是用了Object的东西呀
Object.prototype.__proto__ === null //这就很哲学了对吧,天地初开一片混沌(null),道生一(Object),一生二(Function),二生三(Array),三生万物(你爱咋写在写,不报错不死机你就是这浏览器的王)

对,原型链更像一个族谱,你搞不定的事情你找你爸,你爸搞不定的,你找你爷爷。也就是我们的就近原则,层层查找该属性或者该方法