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)
嚴格模式限制<br/ > 這裡我們來說幾個嚴格模式下的嚴格文法限制:
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()