標籤:new 運行 cti 使用 範圍 script 推導 add ret
詞法範圍是一套關於引擎如何尋找變數以及會在何處找到變數的規則。 (函數範圍和塊範圍)
JavaScript 中的範圍就是詞法範圍,也就是靜態範圍,由定義代碼決定
動態範圍似乎暗示有很好的理由讓範圍作為一個在運行時就被動態確定的形式,而不是在寫代碼時進行靜態確定的形式
動態範圍並不關心函數和範圍是如何聲明以及在何處聲明的,只關心它們從何處調用。換句話說,範圍鏈是基於調用棧的,而不是代碼中的範圍嵌套
ps:可以忽略下面這段話 :
靜態類型語言是指在編譯時間變數的資料類型即可確定的語言,多數靜態類型語言要求在使用變數之前必須聲明資料類型,某些具有類型推導能力的現代語言可能能夠部分減輕這個要求.
動態類型語言是在運行時確定資料類型的語言。變數使用之前不需要型別宣告,通常變數的類型是被賦值的那個值的類型
不要混淆概念噢
this 的綁定和函式宣告的位置沒有任何關係,只取決於函數的調用方式。當一個函數被調用時,會建立一個活動記錄(有時候也稱為執行內容)。這個記錄會包
含函數在哪裡被調用(調用棧)、函數的調用方法、傳入的參數等資訊。this 就是記錄的其中一個屬性,會在函數執行的過程中用到
綁定規則:
1. 由new 調用?綁定到新建立的對象。
2. 由call 或者apply(或者bind)調用?綁定到指定的對象。
3. 由內容物件調用?綁定到那個內容物件。
4. 預設:在strict 模式下綁定到undefined,否則綁定到全域對象。
1.預設綁定
function foo() {console.log( this.a );}var a = 2;foo(); // 2
2.
function foo() {console.log( this.a );}var obj = {a: 2,foo: foo};var bar = obj.foo; // 函數別名!var a = "oops, global"; // a 是全域對象的屬性bar(); // "oops, global"雖然bar 是obj.foo 的一個引用,但是實際上,它引用的是foo 函數本身,因此此時的bar() 其實是一個不帶任何修飾的函數調用,因此應用了預設綁定。
3.
function foo() {console.log( this.a );}function doFoo(fn) {// fn 其實引用的是foofn(); // <-- 調用位置!}var obj = {a: 2,foo: foo};var a = "oops, global"; // a 是全域對象的屬性doFoo( obj.foo ); // "oops, global"參數傳遞其實就是一種隱式賦值,因此我們傳入函數時也會被隱式賦值,所以結果和上一個例子一樣
類似的例子:
function setTimeout(fn,delay) {// 等待delay 毫秒fn(); // <-- 調用位置!}
fn若傳入obj.fn 實際也發生隱式賦值
硬綁定的典型應用情境就是建立一個包裹函數,傳入所有的參數並返回接收到的所有值:
function foo(something) {console.log( this.a, something );return this.a + something;}var obj = {a:2};var bar = function() {return foo.apply( obj, arguments );};var b = bar( 3 ); // 2 3console.log( b ); // 5
call和apply實際上就是調用fn(運行時綁定),將fn裡面的this 綁定指向obj,運行fn arguments是fn參數組成的數組 fn.apply(obj,【arguments】)
call類似只不過fn的參數不是數組形式
function foo(something) {console.log( this.a, something );return this.a + something;}// 簡單的輔助綁定函數function bind(fn, obj) {return function() {return fn.apply( obj, arguments );};}var obj = {a:2};var bar = bind( foo, obj );var b = bar( 3 ); // 2 3console.log( b ); // 5
箭頭函數:
箭頭函數最常用於回呼函數中,例如事件處理器或者定時器:function foo() {setTimeout(() => {// 這裡的this 在此法上繼承自foo()console.log( this.a );},100);}var obj = {a:2};foo.call( obj ); // 2
箭頭函數會繼承外層函數調用的this 綁定
動態範圍與this +apply和call +bind