js 原型链污染和预防

原文链接: js 原型链污染和预防

上一篇: conda tf2 gpu 安装

下一篇: proxy 代理

通过修改原型对象污染原型链, 设置p1的toString方法间接的改变了p2的行为

let p1 = {name: "a"}
console.log(p1.name, p1.toString()) // a [object Object]
p1.__proto__.toString = () => "err"
console.log(p1.name, p1.toString()) // a err
let p2 = {name: 'b'}
console.log(p2.name, p2.toString()) // b err

我们可以采用 Object.freeze 达到目的:

Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze() 返回和传入的参数相同的对象。

冻结之后修改不生效

Object.freeze(Object.prototype);
Object.prototype.toString = 'evil'
console.log(Object.prototype.toString)  // [Function: toString]

不冻结的话会被修改

Object.prototype.toString = 'evil'
console.log(Object.prototype.toString)  //  evil

Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的 proto

Object.create(null) 的返回值不会链接到 Object.prototype:

let foo = Object.create(null)
console.log(foo.__proto__)// undefined

这样一来,无论如何扩充对象,都不会干扰到原型了。

采用新的 Map 数据类型,代替 Object 类型

Map 对象保存键/值对,是键/值对的集合。任何值(对象或者原始值)都可以作为一个键或一个值。使用 Map 数据结构,不会存在 Object 原型污染状况。

这里总结一下 Map 和 Object 不同点::

  • Object 的键只支持 String 或者 Symbols 两种类型,Map 的键可以是任意值,包括函数、对象、基本类型

  • Map 中的键值是有序的,而 Object 中的键则不是

  • 具体 API 上的差异:比如,通过 size 属性直接获取一个 Map 的键值对个数,而 Object 的键值无法获取;再比如迭代一个 Map 和 Object 差异也比较明显

  • Map 在频繁增删键值对的场景下会有些性能优势

补充:V8,chromium 的小机灵

同样存在风险的是我们常用的 JSON.parse 方法,但是如果你运行:

JSON.parse('{ "a":1, "__proto__": { "b": 2 }}')

db4f7c29ef34bd9c7e069d7b200ceb3b434.jpg

复写 Object.prototype 失败了, proto 属性还是我们熟悉的那个有安全感的 __proto__ 。这是因为:

V8 ignores keys named proto in JSON.parse

总之你可以记住,V8 默认使用 JSON.parse 时候会忽略 proto ,原因当然是之前分析的安全性了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值