JS--原型链

原型链

先来一个小测试javascript

环境:对象 person1 有一个__proto__属性,建立它的构造函数是 Person,构造函数的原型对象是 Person.prototype
html

问题:java

  1. person1.__proto__是什么?
  2. person.__proto__是什么?
  3. Person.prototype.__proto__是什么?
  4. Object.__proto__是什么?
  5. object.prototype.__proto__ 是什么?

答案:
第一题:
由于 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

先看下图


分析一下:

  1. 一个函数在生成的时候,javascript都会默认生成一个prototype属性,经过prototype生成一个空对象,也就是原型对象。
  2. 原型对象经过constructor构造器,来指向它被声明的那个函数。
  3. 构造函数经过new 和实例产生关联, 实例又经过__ptoto__指向构造函数的原型。


能够看出原型链的觉得就是:原型链经过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__ 赋值,以后就能够利用代码了。

相关文章
相关标签/搜索