【JS迷你書】個人 JavaScript 世界觀

咱們都生活在主觀的世界裏,但真實世界倒是個複雜系統。 javascript

對於一個非線性系統來講,用任何線性思惟去理解都會所偏頗。java

用《失控》的觀點來講,對於非線性系統,你只有運行起來才知道它具體會是什麼。git

話雖如此! github

《好好學習》一書中,一個重要假設就是:複雜現象背後都是由幾個簡單的規律所主導的編程

我的認爲 JS 也是屬於這種情形的。設計模式

JavaScript(ES3)爲啥是這樣? 數組

也許只有 JavaScript 的做者才清楚吧,畢竟他只花了 10 天就發明了這個強大的存在。瀏覽器

本文不想去回顧歷史,也不是去還原做者的創做思路。而是以嘗試以本身的思路去理解 JS閉包

但願本篇文章,能給一些初學者點啓發,尤爲對於以類爲主導的語言出身者(好比 Java 使用者)。app

除此以外,本文再無所求。

JS 的發明者 Brendan Eich 說這門語言主要有兩大特性:一等函數對象原型

一等函數,我認爲這個纔是 JS 最爲核心的東西。

以函數是一等公民爲出發點,就能解釋 JS 爲啥有那些難點。

什麼是一等函數呢(First-class function)?

函數是一等公民是說,函數被設計成了「值」。

值能幹什麼它就能幹什麼。

值能夠存進某個變量,或者某個結構,那麼函數表達式聲明就是理所固然的。

值除了能夠被賦予某個變量,也能夠單獨存在。好比 "x",因此函數就能夠是匿名的。

值能夠做爲參數傳入函數,函數也能夠,所以在 JS 中回調的實現顯得那麼天然。

值能夠做爲返回值,函數也能夠。這一點就很是重要了,由於這直接致使閉包這一機制必須存在。

值能夠隨時用,也就是動態的,函數也可隨時用,所以匿名函數自執行,我以爲很是合理。

除了函數以外還有其餘一等公民嗎?

函數是,數組是,對象也是。他們都體現了「值」的特性。

所以在 JS 中,有兩句話,特別有名:

JavaScript 的一切都是對象,

JavaScript 的一切也都是值。

兩者在 JS 中實現了對立統一。

知道這些後,也許你對不少東西就再也不迷糊了,反而會越合計越合理。

下面將舉例來講明,爲啥 JS 中有那麼多「奇怪」的東東。

1. 函數作爲參數

好比:

setTimeout(function({}, 1000);
複製代碼

還記得當初學習JS時,感受很迷糊。函數居然能當參數。

setTimeout(later, 1000);
複製代碼

你還記得,不少書都告訴你不要寫成 later() 嗎?

後來我認識到函數是一等公民後,學習 es5 時,也就再也不迷糊:

[123].map(function(valuereturn value * value; });
複製代碼

函數能當參數傳遞,JQuery 對它的使用能夠說達到了極致。具體應該不用舉例了吧。

2. 函數做爲返回值

函數做爲返回值這塊兒,直接致使了閉包的存在。

固然這不是充要條件,但能夠做爲一個理解閉包出發點。

咱們知道,函數基本做用就是做爲一個可複用代碼的封裝,有輸入,有輸出。

好比:

function sum(a, b{
  return a + b;
};
複製代碼

可是當函數居然還能返回函數時,有趣的事情就發生了:

function sumCreater(x{
  return function(y{
    return x + y;
  };
}
var sum10 = sumCreater(10);
sum10(12)// 22
複製代碼

函數能返回函數是好事,可是被返回的函數最起碼應該能運行才行。

你要運行的話,內部引用的外部變量天然而然就該能被找到。

否則怎麼辦?難道你想讓瀏覽器直接報錯?這個機制就是閉包。

這裏具體不展開,由於我只是在搭建世界觀。

關於函數能當返回值,能當參數。這就涉及了高級函數概念。

所以也有了不少函數式編程的基礎知識,好比柯里化,偏函數,函數組合等等。

3. 匿名函數調用表達式

(function({})();
複製代碼

函數是能夠調用的,這沒啥可說的。那麼聲明個函數,直接運行一下,這應該一點也不奇怪。

4. 對象

一等函數是核心,之因此這麼說,也由於它對 JS 支持面向對象編程機制起到了關鍵做用。

一個對象,應該有屬性,有方法。由於函數是值,因此下面的代碼,應該很親切:

var object = {
  sayfunction({
    console.log('hello world!');
  };
};
複製代碼

5. this 問題

由於對象的方法,要常常用到本身的屬性,this

是應該必須有的,否則用什麼指代當前這個對象自己呢?

var object = {
  name'laoyao',
  sayfunction({
    console.log(this.name);
  };
};
複製代碼

那麼這裏就涉及到一個問題,this 是在函數語義下的存在。

假如直接調用函數,this 指向什麼呢?

我又能夠不能夠動態修改一個函數 this 指向呢?

以上就是 JSthis 指向問題。

6. 對象複用機制

你有個東西,我以爲好,想爲我所用。

辦法1,我去偷或者借,JS 中能夠 callapply

辦法2,我 copy 一份,這就是 JS 中的混入(mixin)。

辦法3,我認你爲爹。你都是我爹了,我用你的東西,還不行嗎?這是 Java 的世界觀。

辦法4,我當你是個人智囊。我解決不了問題,找你來想辦法。

辦法3和辦法4,就是兩種複用思想,一個是繼承,一個是委託。

JSprototype,就是委託的機制。請參考《你不知道的JavaScript》上卷。

7. new 操做符

我總不能每使用一個類似的對象時,就聲明一個吧。

所以必須有種方式,經過相似「模板」的形式來作。這就是 new 的做用。

JS 中的 newJava 中的 new,表層含義是同樣的,都是用於生成對象實例。

然而,JS 中的 new 在我看來只是封裝了對象間的委託關係罷了。

後記

上面總總就是我對 JS 的世界觀。

爲啥要用「世界觀」這個詞語呢?由於我最近在看一本書,《世界觀》。

書中說,對世界的見解和信念,雖是一片一片的,倒是相互聯繫的,是能整合到一塊兒去的,從而構成完整的拼圖。

好比你相信世界是以地球爲中心的,那麼就能夠解釋物體爲啥會向下落。

一樣,假如你相信萬有引力,也能夠解釋物體爲什麼向下落。

若是採用某種方式,能讓本身以爲一些知識是天然而然,就本該是那樣的,也許會更好地對其吸取和利用。

固然,採用不一樣語言世界觀,就會造成不一樣的編程範式。

就像有人喜歡使用面向對象編程來使用 JS,而有人喜歡函數式編程那樣。

說到編程範式,提下設計模式。

面向對象有面向對象的設計模式,函數式編程也有本身的設計模式。

解決問題的動機是同樣的,但在 Java 中的複雜形式,而在 JS 中,卻簡單了不少。

這跟 JS 函數是一等對象是密不可分的。

提到了設計模式,最後說句 JS 的原型繼承方式,就是合成複用模式。

每每「有一個」比「是一個」的方式更好。

因此,你想有錢,不必定須要是富二代,你能夠傍個大款。

因此,你想認識世界,不必定須要本身變成旅行者,你能夠上知乎問「周遊世界是一種怎樣的體驗?」。

因此,你想幹成大事,不必定須要本身能力多強,你只要有幾個聰明人爲你所用就好了。

因此,借刀殺人、狐假虎威以及借雞下蛋都是聰明人最愛使用的方法。

。。。

但願你也能找到一種方式,讓你產生 JS 就該是這樣的一種錯覺。

本文完。

《JavaScript 迷你書》傳送門,全面夯實基礎

掘金收藏

相關文章
相關標籤/搜索