如下是我的對這三個老大難的總結(最近一直在學習原生JS,翻了很多書,很多文檔,雖然仍是新手,但我會繼續堅持走我本身的路)閉包
全部對象都是基於Object.prototype
,Object.prototype
就是JavaScript的根對象,在Object.prototype
中定義的方法均可以被其它對象訪問到,固然也能夠被重寫了,因此直接在Object.prototype
上調用的是原始功能的toString()
方法,該方法會放回參數對象的內置屬性[[class]]
的值,這個值是個字符串,好比'[Object String]'
app
要理解原型鏈機制的話,首先得知道根本緣由:JavaScript中的對象都有一個內置屬性[[Prototype]]
,這個屬性和非標準的__proto__
屬性同樣,__proto__
在ES6中被歸入標準了,能夠說它們基本上是等價的,但內置屬性是沒法訪問到的。對象之間經過內置屬性[[Prototype]]
關聯了起來就造成了原型鏈,而原型鏈的頂層就是根對象Object.prototype
,Object.prototype
的原型將是null
,即Object.prototype.__proto__ === null;
函數
例如:
在訪問對象的屬性的時候,如:obj.a
,首先查找自身,沒有,就到它的內置屬性[[Prototype]]
所引用的對象上找,仍是沒有,就繼續在這個上層對象的內置屬性[[Prototype]]
所引用的對象上找,一直找到根對象Object.prototype
,找不到就返回undefined
;學習
理解this的第一步就是要明白:this
既不指向函數自身,也不指向函數的詞法做用域;
this是在運行時進行綁定的,而不是在編寫時綁定,它的上下文取決於函數調用時的各類條件;
this的綁定和函數聲明的位置沒有任何關係,只取決於函數的調用位置和調用方式;
this綁定規則有4點:按優先級1到4判斷this
由new調用?綁定到新建立的空對象;prototype
由call、apply、bind
調用?綁定到指定的參數對象;如foo.call(obj)
code
由上下文對象調用?綁定到這個上下文對象;如obj.foo()
對象
默認狀況下綁定到全局對象,foo()
;在嚴格模式下綁定到undefined
;ip
function foo(){ var a = 2; function bar(){} return bar; } var a = foo(); a();
閉包:不是指函數bar也不是a,它是一個引用,這個引用被內部函數bar持有,這個引用指向外部函數foo的整個做用域,它使得這個做用域即便在外部函數foo()執行後也不會被垃圾回收器回收。也就是說這個外部函數foo的做用域就是閉包自己。
不管經過何種手段(直接或間接)將內部函數傳遞到所在的詞法做用域之外,它都會持有對原始定義做用域的引用,不管在何處執行這個函數都會使用閉包。原型鏈
var fn; //間接傳遞函數 function foo(){ var a = 2; function baz(){ console.log(a); } fn = baz; } function bar(){ fn();} foo(); bar();
function foo(){ var a = 2; function baz(){ console.log(a); } bar(baz); } function bar(fn){ fn(); }