先来一个小测试javascript
环境:对象 person1 有一个__proto__属性,建立它的构造函数是 Person,构造函数的原型对象是 Person.prototype
html
问题:java
答案:
第一题:
由于 person1.__proto__==person1 的构造函数 .prototype数组
由于 person1的构造函数 ===Personbash
因此 person1.__proto__ === Person.prototype函数
第二题:
由于person.__proto__===Person的构造函数 .prototype
由于Person的构造函数===Function
因此person.__proto__===Function.prototype测试
第三题:
Person.prototype 是一个普通对象,咱们无需关注它有哪些属性,只要记住它是一个普通对象。
由于一个普通对象的构造函数 === Object
因此Person.prototype.__proto__===Object.prototypethis
第四题,参照第二题,由于 Person 和 Object 同样都是构造函数spa
第五题:
Object.prototype对象也有proto属性,但它比较特殊,为 null 。由于 null 处于原型链的顶端,这个只能记住。Object.prototype.
Object.prototype.__proto__=== null
prototype
先看下图
分析一下:
能够看出原型链的觉得就是:原型链经过prototype和__proto__来完成原型的查找。从一个实例对象往上找构造这个实例的相关的原型对象,而后相关联的原型对象再往上找创造它的原型对象,一直到object.prototype原型对象终止。
经过原型链,能够进行数据共享,也就是找到原型对象,原型对象的方法被不一样的实例所共有。
查找一个实例中的一个方法或者属性,若是这个这个实例没有找到,就会经过__proto__往上一级找原型对象,若是还找不到就会再往上找,直到object.proototype位置,若是还找不到,就会返回这个属性或者方法没有找到或者没有定义。若是在中间任何一个原型对象找到了,那么返回这个属性和方法,就不会再往上寻找。
强调一下只有函数才会有有prototype,对象是没有prototype的,只有实例对象有 __proto__
解释一下为何函数也会有__proto__
从图中能够看到,函数name()也是函数Function的原型对象,因此函数也即对象。
万物皆对象!但对象也是有区别的。分为普通对象和函数对象,Object 、Function 是 JS 自带的函数对象。
看下面例子
//a.js
(function()
{
var secret = ["aaa","bbb"];
secret.forEach();
})();
复制代码
//b.html
<body>
<script>
Array.prototype.forEach = function() {
var result = 'result: ';
for(var i=0,length = this.length; i<length;i++){
result += this[i];
result += ''
}
document.write(result);
}
</script>
<script src="./a.js"></script>
</body>
复制代码
运行结果:
在a.js中声明了一个数组 secret ,而后该数组调用了属于 Array.prototype的forEach方法,以下
可是,在调用js文件以前,js代码中将 Array. prototype.forEach 方法进行了重写,而prototype链为 secret -> Array.prototype ->object.prototype,secret中无 foreach 方法,因此就会向上检索,就找到了 Array.prototype 而forEach方法已经被重写过了,因此会执行输出。
这就是原型链污染。很明显,原型链污染就是:在咱们想要利用的代码以前的赋值语句若是可控的话,咱们进行 __proto__ 赋值,以后就能够利用代码了。