作用域就是當前執行環境的上下文,它限制了變量、函數的有效范圍。 在當前作用域下聲明的變量、函數只能在當前作用域內以及它嵌套的子作用域內有效。這樣避免變量和函數的命名沖突,還可以形成私有數據,從而保證數據不會被外部作用域篡改。 作用域分為全局作用域和局部作用域、塊作用域。 全局全局作用域中定義的變量、函數,在任何地方都能訪問,在JAVAScript代碼中最外層定義的變量、函數,都是在全局作用域中的。 局部作用域可以訪問全局作用域或者父級作用域中的變量和函數。 在JavaScript中,函數使用var聲明的變量都具有提升機制,就是先引用后聲明。 這是因為JavaScript編譯器會提前檢查代碼中的函數和var聲明的變量,然后把它們提升到當前作用域的頂部,這樣保證代碼的正常運行,但是變量的賦值沒有被提升。該變量變成了undefined。 用let關鍵字定義的變量,不能在初始化之前訪問的原因是,它的聲明被放到了臨時隔離區,臨時隔離區會在執行塊級作用域的第一行代碼之前生效。在變量完成初始化之后,才被釋放出來。 在變量完成初始化之前,是不能訪問臨時隔離區的變量。 換句話來說,臨時隔離區就是存放變量初始化的過程。 函數式編程,是以函數為核心,每一個操作,通過對函數的組合和復用來形成復雜的業務邏輯。只需要調用一次函數,就完成所有的業務邏輯。 函數式編程中的閉包,指的是一種語法形式和變量查找機制,在一系列的函數嵌套中,所有內部函數都可以訪問外部函數以及全局作用域中的變量和函數。 閉包有一個用處:定義私有變量,閉包外面是不能訪問內部變量的,這對內部變量起到一個保護作用,調用者只能通過閉包暴露出來的函數或者是對象來對內部變量的修改。 高階函數就是接收函數作為參數,最終返回一個函數,這樣的函數就是高階函數。 柯里化就是把一個接收多個參數的函數,轉化為一系列接收一個參數的子函數。這個過程就是柯里化,比如:通過匯率計算一美元等于多少人民幣。 首先我們定義一個函數,接收匯率和美元數量,然后返回計算的結果,代碼如下: 但是每次計算的時候,都需要傳入匯率,我們可以通過柯里化的方式,來簡化這個函數,代碼如下 方法很多,柯里化僅僅是其中的一種。 函數緩存,就對于比較耗時的函數而言,把已經執行過的函數的結果保存下來作為緩存,如果下次再次需要這個函數的執行結果,那就先判斷緩存中是否含有該結果,如果有就不用執行該函數。 一般是把函數的參數列表當作緩存的key,如果第二次調用函數傳遞相同的參數,就會返回緩存中的結果。 函數緩存,有效提升了代=代碼程序的性能,加快相應速度。一般用于變化很少、不依賴外部條件并且很耗時的操作。比如計算斐波那契數列。 這是沒有設置緩存的代碼: 在這個例子中,有幾個值是計算多次的,這就造成不必要的性能消耗。這就體現了函數緩存的重要性了,我們可以將已經計算過的值保存起來,,在后面的計算中,判斷是否有緩存,如果有那么就是直接使用。 上面的例子修改后:全局作用域
局部作用域
變量的提升機制
臨時隔離區
閉包
高階函數
柯里化
function usToCny(amount,rate){
return amount * rate;
}
function converRate(rate){
return (amount)=> amount * rate;
}
// 普通調用
converRate(6.3)(100)
// 或者是
const uToC = converRate(6.24);
console.log(uToC(100))
函數緩存
function fib(n){
if(n<=1)return n;
return fib(n-1)+fib(n-2);
}
const start = new Date().getTime();
console.log(fib(10))
const end = new Date().getTime();
console.log("執行花費時間:",end - start);
function fib(n){
if(n<=1){return n}
if(fib[n]){return fib[n]}
fib[n] = fib(n-1) + fib(n-2);
return fib(n);
}