__proto__
一个Foo类实例化出来的foo对象,可以通过foo.__proto__
属性来访问Foo类的原型,也就是说:
foo.__proto__= Foo.prototype 对象 构造函数
所以,总结一下:
prototype
是一个类的属性,所有类对象在实例化的时候将会拥有prototype
中的属性和方法
一个对象的__proto__
属性,指向这个对象所在的类的prototype
属性
每个构造函数(constructor)都有一个原型对象(prototype)
对象的__proto__
属性,指向类的原型对象prototype
JavaScript使用prototype链实现继承机制
之前说到foo.__proto__
指向的是Foo
类的prototype
。那么,如果我们修改了foo.__proto__
中的值,是不是就可以修改Foo类呢?
做个简单的实验:
// foo是一个简单的JavaScript对象 let foo = {bar: 1} // foo.bar 此时为1 console.log(foo.bar) // 修改foo的原型(即Object) foo.__proto__.bar = 2 // 由于查找顺序的原因,foo.bar仍然是1 console.log(foo.bar) // 此时再用Object创建一个空的zoo对象 let zoo = {} // 查看zoo.bar console.log(zoo.bar)
最后,虽然zoo是一个空对象{},但zoo.bar
的结果居然是2
原因也显而易见:因为前面我们修改了foo的原型foo.__proto__.bar = 2
,而foo是一个Object类的实例,所以实际上是修改了Object这个类,给这个类增加了一个属性bar,值为2。
后来,我们又用Object类创建了一个zoo对象let zoo = {}
,zoo对象自然也有一个bar属性了。
那么,在一个应用中,如果攻击者控制并修改了一个对象的原型,那么将可以影响所有和这个对象来自同一个类、父祖类的对象。这种攻击方式就是原型链污染。
mess.js
(function() { var secret = ["aaa","bbb"]; secret.forEach(); })();
attach.html