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__ 賦值,以後就能夠利用代碼了。

相關文章
相關標籤/搜索