JS技巧技法總結——閉包原理、數組展平、前端語音、Proxy 數據綁定和監聽、計數器

開發、閱讀、學習中接觸到、整理的一些知識點。javascript

JS計數器的幾種實現

  • 全局變量
let  count = 0;
const  countUp = () =>  count++;
  • 閉包
// javascript

const  countUp = (() => {
    let  count = 0;
    return () => {
        return ++count;
    };
})();
console.log(countUp()); // 1
console.log(countUp()); // 2
  • 函數屬性
// javascript
let  countUp = () => {
    return ++countUp.count;
};
countUp.count = 0;
console.log(countUp()); // 1
console.log(countUp()); // 2
  • 函數屬性(TS)
interface  Counter {
(): void; // 這裏定義Counter這個結構必須包含一個函數,函數的要求是無參數,返回值爲void,即無返回值
count: number; // 並且這個結構還必須包含一個名爲count、值的類型爲number類型的屬性
}
const  getCounter = (): Counter  => { // 這裏定義一個函數用來返回這個計數器
    const  c = () => { // 定義一個函數,邏輯和前面例子的同樣
        c.count++;
    };
    c.count = 0; // 再給這個函數添加一個count屬性初始值爲0
    return  c; // 最後返回這個函數對象
};

const  counter: Counter = getCounter(); // 經過getCounter函數獲得這個計數器
counter();
console.log(counter.count); // 1
counter();
console.log(counter.count); // 2

前端語音

  • 語音播報:在項目中須要對ajax請求返回的消息進行語音播報,str 爲返回的data(能夠在瀏覽器控制檯嘗試喲~)
//語音播報

function  voiceAnnouncements(str){
//百度
    var  url = "http://tts.baidu.com/text2audio?lan=zh&ie=UTF-8&text=" + encodeURI(str); // baidu
    var  n = new  Audio(url);
    n.src = url;
    n.play();
}
voiceAnnouncements('你好,今天吃的什麼?')
A tiny JavaScript Speech Recognition library that lets your users control your site with voice commands.
annyang has no dependencies, weighs just 2 KB, and is free to use and modify under the MIT license.

數組展開的N種方法

  • 循環加遞歸
  • flat
  • flatMap
  • toString後split
  • join後split

使用 Proxy 來實現一個數據綁定和監聽

Proxy簡介:java

let  p = new  Proxy(target, handler);
// `target` 表明須要添加代理的對象
// `handler` 用來自定義對象中的操做
let  onWatch = (obj, setBind, getLogger) => {
    let  handler = {
        get(target, property, receiver) {
            getLogger(target, property)
            return  Reflect.get(target, property, receiver);
        },

        set(target, property, value, receiver) {
            setBind(value);
            return  Reflect.set(target, property, value);
        }
    };
    return  new  Proxy(obj, handler);
};


let  obj = { a:  1 }
let  value
let  p = onWatch(obj, (v) => {
    value = v
}, (target, property) => {
    console.log(`Get '${property}' = ${target[property]}`);
})
p.a = 2  // bind `value` to `2`
p.a  // -> Get 'a' = 2

再談閉包

一等公民的定義

  在編程語言中,一等公民能夠做爲函數參數,能夠做爲函數返回值,也能夠賦值給變量。例如,字符串在幾乎全部編程語言中都是一等公民,字符串能夠作爲函數參數,字符串能夠做爲函數返回值,字符串也能夠賦值給變量。對於各類編程語言來講,函數就不必定是一等公民了,好比Java 8以前的版本。對於JavaScript來講,函數能夠賦值給變量,也能夠做爲函數參數,還能夠做爲函數返回值,所以JavaScript中函數是一等公民。react

動態做用域與靜態做用域

  注意,是說做用域,不是類型。
  若是一門語言的做用域是靜態做用域,那麼符號之間的引用關係可以根據程序代碼在編譯時就肯定清楚,在運行時不會變。某個函數是在哪聲明的,就具備它所在位置的做用域。它可以訪問哪些變量,那麼就跟這些變量綁定了,在運行時就一直能訪問這些變量。即靜態做用域能夠由程序代碼決定,在編譯時就能徹底肯定。大多數語言都是靜態做用域的。
  動態做用域(Dynamic Scope)。也就是說,變量引用跟變量聲明不是在編譯時就綁定死了的。在運行時,它是在運行環境中動態地找一個相同名稱的變量。在 macOS 或 Linux 中用的 bash 腳本語言,就是動態做用域的。git

閉包

  閉包的內在矛盾是運行時的環境和定義時的做用域之間的矛盾。那麼咱們把內部環境中須要的變量,打包交給閉包函數,它就能夠隨時訪問這些變量了。github

  閉包這個概念,對於初學者來說是一個挑戰。其實,閉包就是把函數在靜態做用域中所訪問的變量的生存期拉長,造成一份能夠由這個函數單獨訪問的數據。正由於這些數據只能被閉包函數訪問,因此也就具有了對信息進行封裝、隱藏內部細節的特性。ajax

閉包與面向對象

  聽上去是否是有點兒耳熟?封裝,把數據和對數據的操做封在一塊兒,這不就是面向對象編程嘛!一個閉包能夠看作是一個對象。反過來看,一個對象是否是也能夠看作一個閉包呢?對象的屬性,也能夠看作被方法所獨佔的環境變量,其生存期也必須保證可以被方法一直正常的訪問。編程

閉包的實現

  • 函數要變成 playscript 的一等公民。也就是要能把函數像普通數值同樣賦值給變量,能夠做爲參數傳遞給其餘函數,能夠做爲函數的返回值。
  • 要讓內層函數一直訪問它環境中的變量,無論外層函數退出與否。

概括總結

  1. 由於JavaScript是靜態做用域的,因此它內部環境中須要的變量在編譯時就肯定了,運行時不會改變;
  2. 又由於JavaScript中,函數是一等公民,能夠被調用,能夠做爲參數傳遞,能夠賦值給變量,也能夠做爲函數返回值,因此它的運行時環境很容易變化;
  3. 當函數做爲參數返回時,其外層函數中的變量已經從調用棧彈出,可是咱們必須讓內部函數能夠訪問到它須要的變量,所以運行時的環境和定義時的做用域之間就產生矛盾;
  4. 因此咱們把內部環境中須要的變量,打包交給內層函數(閉包函數),它就能夠隨時訪問這些變量了,就造成了閉包。

本文首發於我的博客,歡迎指正和star。react-native

相關文章
相關標籤/搜索