【相關推薦:、】
3.Type源於JavaScript,歸於JavaScript
高階程式語言都需要轉換成最終的機器指令來執行
事實上我們編寫的JavaScript無論交給瀏覽器或者Node執行,最後都是需要被CPU執行的
所以我們需要JavaScript引擎幫助我們將JavaScript程式碼翻譯成CPU指令來執行
這裡我們以WebKit為列,WebKit事實上由兩部分組成:
WebCore:負責HTML解析、佈局、渲染等等相關的工作
JavaScriptCore:解析、執行JavaScript程式碼
VO(Variable Object)變數物件 在最新的ECMA標準中,VO已經有另外一個稱呼了變數環境 VE
GO(Clobal Object)全域性物件,全域性執行上下文
AO(Activation Objece)包括了函數執行上下文
JavaScript會在定義變數時為我們分配記憶體
JS對於基本資料型別記憶體的分配會在執行時,直接在棧空間進行分配;
JS對於複雜資料型別記憶體的分配會在堆記憶體中開闢一塊空間,並將這塊空間的指標返回值變數參照
因為記憶體的大小是有限的,所以當記憶體不再需要的時候,我們需要對其進行釋放,以便騰出更多的記憶體空間
垃圾回收的英文是 Garbage Collection 簡稱GC
對於那先不再使用的物件,我們都稱之為是垃圾,它需要被回收,以釋放更多的記憶體空間
而我們的語言執行環境,比如java的執行環境JVM,JavaScript的執行環境js引擎都會記憶體垃圾回收器
垃圾回收器我們也簡稱GC,所以哎很多地方你看到 GC其實指的是垃圾回收器
在電腦科學中對閉包的定義(維基百科):
閉包(英語:Closure),又稱詞法閉包(Lexical Closure) 或函數閉包(function closures);
是在支援頭等函數的程式語言中,實現詞法系結的一種技術;
閉包在實現上是一個結構體,它儲存了一個函數和一個關聯的環境(相當於一個符號查詢表);
閉包跟函數最大的區別在於,當捕捉閉包的時候,它的自由變數會在捕捉時被確定,這樣即使脫離了捕捉時的上下文,它也能照常執行
閉包的概念出現於60年代,最早實現閉包的程式時Scheme,那麼我們就可以理解為什麼JavaScript中有閉包;
因為JavaScript中有大量的設計是來源於Scheme的;
我們再來看一下MDN對JavaScript閉包的解釋:
一個函數和對其周圍狀態(lexical environment,詞法環境) 的參照捆綁在一起(或者說函數被參照包圍),這樣的組合就是閉包
也就是說,閉包讓你可以在一個內層函數中存取到其外層函數的作用域;
在JavaScript中,每當建立一個函數,閉包就會在函數建立的同時被建立出來;
function foo() { var name = 'why' var age = 18 function bar() { console.log('bar ',name) } return bar}var fun = foo()fun()
總結:
一個普通的函數function,如果它可以存取外層作用於的自由變數,那麼這個函數就是一個閉包;
從廣義的角度來說:JavaScript中的函數都是閉包;
從狹義的角度來說:JavaScript中一個函數,如果存取了外層作用於的變數,那麼它是一個閉包;
在全域性作用域下:
瀏覽器:window
node環境:{}
箭頭函數是ES6 之後增加的一種編寫函數的方法,並且它比函數表示式更加簡潔;
箭頭函數不會繫結this、arguments屬性;
箭頭函數不能作為建構函式來使用(不能和new一起來使用,會丟擲錯誤)
arguments是一個對應於 傳遞給函數的引數的類(偽)陣列(array-like) 物件
函數語言程式設計中有一個非常重要的概念叫做純函數,JavaScript符合函數語言程式設計的規範,所以也有純函數的概念;
純函數的維基百科定義:
在程式設計中,若一個函數符合以下條件,那麼這個函數輩稱為純函數
此函數在相同的輸入值時,需要產生相同的輸出
函數的輸出和輸入值以外的其他隱藏資訊或狀態無關,也和由I/O裝置產生的外部輸出無關
改函數不能有語意上可觀察的函數副作用,諸如 「觸發事件」,使輸出裝置輸出,或更改輸出值以外物件的內容等
總結:
確定的輸入,一定產生確定的輸出;
函數在執行過程中,不能產生副作用;
副作用:
柯里化也是屬於函數語言程式設計裡面一個非常重要的概念
維基百科解釋:
在電腦科學中,柯里化(Currying) ,又譯為卡瑞化 或加里化
是八接收多個引數的函數,變成接收一個單一引數(最初函數的第一個引數)的函數,並且返回接受餘下的引數,而且返回結果的新函數
柯里化聲稱:如果你固定某些引數,你將得到接受餘下引數的一個函數
總結:
只傳遞給函數一部分引數來呼叫它,讓它返回一個函數區處理剩餘的引數;
這個過程就稱為柯里化
為什麼需要柯里化:
在函數語言程式設計中,我們其實往往希望一個函數處理的問題儘可能的單一,而不是將一大堆的處理過程交給一個函數來處理
function foo(x,y,c) { return x + y + c } console.log(foo(10,20,30)) //柯里化 function sum(x) { return function(y) { return function(z) { return x + y + z } } } var a = sum(10)(20)(30) console.log(a ) //簡化柯里化 var sum2 = x => y => z => { return x + y + z } console.log(sum2(10)(20)(30 ))
組合函數(Compose) 函數是在JavaScript開發中一種對函數的使用技巧、模式:
比如我們現在需要對某個資料進行函數的呼叫,執行兩個函數fn1 和 fn2,這兩個函數是依次執行的
那麼如果我們每次都需要進行兩個函數的呼叫,操作上就會顯示的重複
那麼是否可以將這兩個函陣列合起來,自動依次呼叫呢?
這個過程就是對函數的組合,我們稱之為組合函數(Compose Function)
with 語句
+作用: 可以形成自己的作用域
不建議使用with語句 ,因為它可能是混淆錯誤和相容性問題的根源
var obj2 = {name:'Tom',age:18,message:'obj2'} // var message = "hello world" function foo() { function bar () { with(obj2) { console.log(message) } } bar() } foo()
eval是一個特殊的函數,它可以將傳入的字串當作JavaScript 程式碼來執行
var strFn = 'var message = "Hello world"; console.log(message);'; eval(strFn)
不建議在開發中使用eval:
eval程式碼的可讀性非常的差(程式碼的可讀性是高品質程式碼的重要原則);
eval是一個字串,那麼有可能在執行的過程中輩可以篡改,那麼可能會造成被攻擊的風險;
eval的執行必須經過JS直譯器,不能不被JS引擎優化;
嚴格模式是一種具有限制性的JavaScript模式,從而使程式碼隱式的脫離了"懶散(sloppy) 模式" 支援嚴格模式的瀏覽器在監測到程式碼中有嚴格模式時,會以更加嚴格的方式對程式碼進行監測和執行 嚴格模式通過丟擲錯誤來消除一些原有的靜默(silent)錯誤 嚴格模式讓Js引擎週期執行程式碼時可以進行更多的優化(不需要對一些特殊的語法進行處理)
"use strict"; // 開啟嚴格模式var message = "hello world"console.log(message)
嚴格模式限制
這裡我們來說幾個嚴格模式下的嚴格語法限制:
JavaScript被設計為新手開發者更容易上手,所以有時候本來錯誤語法,被認為也是可以正常被解析的
但是在嚴格模式下,這種失誤會被當成錯誤,以便可以快速的發現和修正
// 1. 意外建立全域性變數 message = "Hello world" console.log(message) function foo() { age = 20 } foo() console.log(age)
//預設靜態錯誤 true.name ='xiaoluo'; NaN = 123
// 不允許函數引數有相同的名稱function foo(x,y,x) { console.log(x,y,x)}foo(10,20,30)
var num = 0o123 // 八進位制 var num2 = 0x123 // 十六進位制 console.log(num,num2)
var obj2 = {name:'Tom',age:18,message:'obj2'} with(obj2) { console.log(message) }
var strFn = 'var message = "Hello world"; console.log(message);'; eval(strFn) console.log(message)
function foo() { console.log(this) //undefined } foo()
【相關推薦:、】
以上就是深入聊聊JavaScript的詳細內容,更多請關注TW511.COM其它相關文章!