JS 中 __proto__ 和 prototype 存在的意义是什么?

在这里插入图片描述
在这里插入图片描述
你的 JS 代码还没运行的时候,JS 环境里已经有一个 window 对象了window 对象有一个 Object 属性,window.Object 是一个函数对象window.Object 这个函数对象有一个重要属性是 prototype,干什么用的等会说window.Object.prototype 里面有这么几个属性 toString(函数)、valueOf(函数)好,目前先知道这些就够了。然后我们写一句代码var obj = {}
obj.toString()这句代码做了啥?为什么 obj 有 toString() 属性?
在这里插入图片描述
这句话大概是让 obj 变量指向一个空对象,这个空对象有个 proto 属性指向 window.Object.prototype。这样你在调用 obj.toString() 的时候,obj 本身没有 toString,就去 obj.proro 上面去找 toString。所以你调用 obj.toString 的时候,实际上调用的是 window.Object.prototype.toString那么 window.Object.prototype.toString 是怎么获取 obj 的内容的呢?那是因为 obj.toString() 等价于 obj.toString.call(obj) 同时 obj.toString.call(obj) 等价于 window.Object.prototype.toString.call(obj)这句话把 obj 传给 toString 了

在这里插入图片描述
我们写一句代码

var arr = []
arr.push(1) // [1]
请问这两句话做了什么
在这里插入图片描述

看红色部分,var arr = [] 大概会让 arr 指向一个空对象,然后 arr.proto 指向 window.Array.prototype。(其实 arr 有一个 length:0,不过这里就忽略吧)这样你在调用 arr.push 的时候,arr 自身没有 push 属性,就去 arr.proto 上找 push因此 arr.push 实际上是 window.Array.prototype.pusharr.push(1) 等价与 arr.push.call(arr,1) arr.push.call(arr,1) 等价于 window.Array.prototype.push.call(arr, 1)再再复杂一点arr.valueOf() 做了什么?arr 自身没有 valueOf,于是去 arr.proto 上找arr.proto 只有 pop、push 也没有 valueOf,于是去 arr.proto.proto 上找arr.proto.proto 就是 window.Object.prototype所以 arr.valueOf 其实就是 window.Object.prototype.valueOfarr.valueOf() 等价于 arr.valueOf.call(arr)arr.valueOf.call(arr) 等价于 window.Object.prototype.valueOf.call(arr)看,JavaScript 其实很优美很简单。只是你想复杂了而已:prototype 指向一块内存,这个内存里面有共用属性__proto__ 指向同一块内存prototype 和 proto 的不同点在于prototype 是构造函数的属性,而 proto 是对象的属性难点在于……构造函数也是对象!如果没有 prototype,那么共用属性就没有立足之地如果没有 proto,那么一个对象就不知道自己的共用属性有哪些。反证法假设我们把 proto 去掉,那么var obj = {}
obj.toString() // 报错,没有 toString 方法所以你只能这样声明一个对象咯:var obj = {
toString: window.Object.prototype.toString,
valueOf: window.Object.ptototype.valueOf
}
obj.toString() // ‘[object Object]’

知道 proto 帮你省多少代码了吗?假设我们删掉 prototype,包括 window.Object.prototype 和 window.Array.prototype。那么 window.Object.prototype.toString 也一并被删除了。然后我们基本就没法写代码了……var obj = {}
obj.toString() // toString 不存在,因为 toString 没有定义过啊prototype 的意义就是把共有属性预先定义好,给之后的对象用。自己想想吧~
比如很多人不懂什么是伪数组,很简单:如果一个数组的 proto 直接或间接指向 Array.prototye(用到了数组的共用属性),那么就是真数组如果一个数组的 proto 没有直接或间接指向 Array.prototye,那么就是伪数组var realArr = {0: ‘a’, 1:‘b’, length: 2}
realArr.proto = Array.prototype
// 这就是真数组(并不完全是)
// 基本等价于 realArr = [‘a’, ‘b’]
realArr.push !== undefined // true

var fakeArr = {0: ‘a’, 1:‘b’, length: 2}
// 这就是伪数组
realArr.push === undefined // true

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

故事只若初见

坚持就是胜利

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值