function Person() { } var person = new Person(); person.name = 'zhangsan'; console.log(person.name) // zhangsan
上邊這個例子,咱們經過構造函數建立了一個實例,從這個實例到他的原型到最後得object,他們之間得關係,就造成了一個原型鏈html
prototype __proto__ 和 constructor
首先上邊這個例子裏邊,咱們聲明瞭一個構造函數,在後再這個構造函數裏邊有一個prototype的屬性。瀏覽器
注意這個prototype屬性,是隻有函數纔會有屬性
Person.prototype.name = 'zhangsan'; var person1 = new Person(); var person2 = new Person(); console.log(person1.name) // zhangsan console.log(person2.name) // zhangsan
首先咱們看到再函數的prototype屬性上邊咱們定義了一個name屬性,而後經過new建立了兩個實例,
而後經過調用實例的name屬性,也能夠拿到構造函數prototype屬性上邊的name屬性,
那麼這個prototype究竟是有什麼用處呢,函數
這個只有函數纔會有的屬性,他其實指向了一個對象,而這個對象就是調用了構造函數建立實例的原型
,能夠理解成是person1,person2在建立的時候從他們的原型把原型的屬性委託給了person1和person2this
這裏爲何不叫他繼承,由於繼承的定義是賦值一個如出一轍的實例出來,可是js裏邊並不會複製
這個__proto__屬性是每一個對象實例都會有的一個屬性,這個屬性也會指向該對象的原型spa
function Person() {} var person1 = new Person(); console.log(person1.__proto__ === Person.prototype); // true
能夠粘貼一下代碼到瀏覽器打印一下person1 能夠看到__proto__這個屬性prototype
constructor這個屬性以前我也叫他構造函數,叫習慣了,由於每一個原型上邊都會有一個constructor這個屬性,指向其相關的構造函數指針
function Person() {} console.log(Person === Person.prototype.constructor); // true
首先在你建立一個實例的時候,你去讀取實例上邊的屬性,他會首先再實例上邊去查找,若是找不到,那麼就去這個實例的原型上邊去找,若是仍是找不到,就會去原型的原型上邊去找,直到最後找到Object對象,固然object對象也是有原型的 就是nullcode
記得以前的時候,遇到過這麼一個問題就是typeof null的 時候爲何是個object,記得當時獲得的答案是說null是一個對象的空指針,從如今來看null打印object是有緣由的
那麼仍是查找不到的話會怎麼樣的,不要慌(.゚ー゚), 他會返給你一個undefined(.゚ー゚)htm
最後拉一張圖對象
圖中藍色的這個鏈狀的結構的線就是原型鏈
首先什麼叫作做用域
做用域是指程序源代碼中定義變量的區域。做用域規定了如何查找變量,也就是肯定當前執行代碼對變量的訪問權限。
JavaScript 採用詞法做用域(lexical scoping),也就是靜態做用域。
var value = 1; function foo() { console.log(value); } function bar() { var value = 2; foo(); } bar();
網上拿來的例子,直接說過程
在執行階段執行foo的時候,直接在foo尋找value ,由於js是靜態做用域,因此在foo裏邊沒有找到的時候,直接去上一層找,最後結果是1
var value = 1; function bar() { var value = 2; console.log(value); } bar();
同理這段代碼bar裏邊有value 直接打印2
那麼再看一個例子
var scope = "global scope"; function checkscope(){ var scope = "local scope"; function f(){ return scope; } return f(); } checkscope();
這個例子會打印出什麼,你們能夠猜一猜
結果就是local scope
那麼爲何上邊的第一段代碼裏邊一樣是在函數裏邊執行另外一個函數,可是他不會用第一個函數裏邊的變量呢,
緣由就是js是靜態做用域,js執行一個函數的時候分爲兩個階段,首先會解析一變,這個時候肯定了詞法做用域和this指向,屬性聲明等,而後纔是函數執行階段
函數的做用域是基於函數建立的位置的,因此第一段代碼和下邊這段代碼的函數做用域是不想同的
說到這裏的時候,我在上文中提到了執行上下文和函數執行的過程,以前在我得另外一篇博客裏邊寫道過,有興趣的能夠去看下 js的堆棧隊列
以上是我對js原型鏈和做用域的一些認識,有不足的但願指正,以前在博客園寫的。搬過來的