跨過編程入門門檻,從寫一首“代碼詩”開始
對很多人來說,學寫代碼很難。本文將通過編寫與眾不同且富有詩意的代碼來克服學習代碼最初遇到的困難。如果你是個JavaScript新手,或者是在編程學習過程中遇到了困難,本文介紹的方法也許可以幫到你。
為什么學習編程這么難?
以下是人們對編程很難學及JavaScript(或任何編程語言)很枯燥的一些誤解:
- 代碼晦澀難懂令人望而生畏,只有實用功能毫無樂趣;
- 代碼僅適用于機器,人們無法與它交流或參與其中;
- 代碼不算一種語言,因為它與一般語言的用法截然不同,形式上的差別也很大;
- 提到程序員,人們就會想到邪惡的黑客或黑客帝國的成員等刻板形象,因此沒有認同感。
未接觸編程的人
開發人員需要以一種非常特殊的方式看待代碼,甚至要以一種完全不同且高度邏輯化的方式來思考。編程語言非常嚴格,對錯誤零容忍,單個字符就可能使機器無法理解人們的意思,并使應用程序奔潰。學習編程時,應將之前學習人類語言時的讀寫規則歸零(順便說一下,在學習一種新的人類語言時也是如此)。
但并非網上的編程語言、文檔或視頻教程都是針對“從人類語言到編程語言的轉換”這一思維而編寫的。當然,他們也沒有必要這樣做。畢竟,寫代碼的主要是為了告訴機器要做什么。
鑒于此目的,沒有機會對這兩種語言進行比較,因此人類的語言(包括詞匯和語法規則)似乎對學習編程語言毫無用處。JavaScript語言中沒有“愛”這個詞,“我愛你。”這句話在其中也沒有意義。機器(或瀏覽器)根本不理解愛。這種“聞所未聞”、“無從下手”的感覺可能會讓人感到害怕。
***次接觸編程的人
這就是本文的意義所在,借助已掌握的人類語言知識,將JavaScript看作一種人類語言,以一種更容易、更具藝術性的方式來學習它。舉個小例子來說明吧!
一個有趣的事實是,一些編程語言實際上已經從一種編程語言轉換到另一種編程語言。這就是為什么掌握多種編程語言變得簡單多了——只學一門編程語言就夠啦。
一個小例子
例如,在很多情況下,要想運行JavaScript代碼,需要準備好“文檔”(基本上是網站,用戶每次訪問時都在下載),以便與HTML元素進行交互。在純JavaScript語言中,可能會偶然發現以下內容。
- (function() {
- // Your code goes here
- })();
或者有時像這樣:
- if (document.readyState === ‘complete’) {
- // Your code goes here
- }
上述***個代碼肯定需要加以解釋,而對第二個代碼(也許需要一些想象),可以這樣理解:滿足了必需的某個條件后,后續步驟僅通過觀察就能進行下去。
試想這樣的場景:
- onceUponATime(function () {
- // Your code (story) goes here
- })
連小孩都能理解“Once upon a time” (“曾幾何時”)這樣的內容。這種內容在與開發者對話(通過喚起他們的童年回憶),同時在理論上也能做開發。這就是“讓人類語言轉換為編碼語言”的想法。
關于“functions(函數)”的簡要說明:函數基本來說是一種技能,在調用之前處于休眠狀態。“To read”是function read() { …}}的一項技能,想讀取某內容時就寫成這樣:read(),就會調用才會調用該函數。還有一種是“匿名函數”,即function(){ … }(沒有名字,就像上面的代碼片段那樣),它基本上是“一次性的臨時操作”,甚至不算一種技能,例如“按下按鈕”。
扭轉乾坤:從信息到基礎
要更進一步了解這個想法,可將上述的原因和誤解顛倒過來:
一首小詩,
用JavaScript語言編寫。
為人類而寫,
講述兩個人之間的愛。
- // Love at first sight
- if (me.getDistanceTo(you.position) < 200) {
- me.setFeelings({
- inLove: true,
- });
- }
它不具有功能性,目前也不適用于機器,只是方便人們閱讀和理解。
如果你能看懂這首詩,你實際上是理解了一段JavaScript代碼,也許你還會拿來與英語進行比較。
現在你可能會問自己:我理解這一點,但它為什么這么寫呢?這種語言背后的規則(語法)是什么呢?“me”在技術層面是什么意思?為什么這段代碼看起來很像英語?
規則、詞匯和變量
學習編程語言時,最重要的事情之一就是理解變量的概念。
每一種人類語言都有其規則(語法)和大量詞匯(意思均已知)。顯然,只有先學習這兩點才會說這種語言。
與許多其它編程語言一樣,JavaScript也有一套規則(例如,單詞之間要加“.”或如何編寫“if”語句)和詞匯(if、document、window、Event等)。這些關鍵字由JavaScript(和瀏覽器)所有(或“預先定義”),并且每個關鍵字都有其特定用途。
就像之前提到的那樣,似乎沒有機會去和英語中的單詞和句子做比較,因為JavaScript中根本沒有對應的詞和句子。
這就是引入變量這個概念的原因,開發人員可以(甚至必須)定義變量,以便讓機器和開發人員理解某些東西代表什么。變量可以采用多種形式(因此得名):它們可以是一串單詞和字母(字符串)、數字、操作(函數)、甚至集合(數組),不勝枚舉。
在所有人類語言中,可能都有一個關于“love”的詞,你大概明白它是什么意思,但不太肯定,因為它太主觀了。但無論怎樣,還是有一個詞可以形容它。
但在JavaScript中,如果不定義“love”,就沒有與之對應的表達,至于形式,則完全取決于你。
- var love = {
- color: ‘red’,
- duration: 365,
- loveTarget: ‘cats’,
- };
- // a simple variable expression,
- // where love is an object “{ … }”, a thing
- // with some properties (color, duration, loveTarget).
- const love2 = {
- color: ‘purple’,
- duration: ‘forever’,
- loveTarget: ‘dogs’,
- };
- // also a variable expression, where love2 (aconstant),
- // cannot be redefined / overwritten completely:
- // love2 = undefined; // => will not work
- // (“undefined” is a pre-defined javascriptkeyword,
- // basically saying “has no value”)
區分JavaScript中預定義的內容(JavaScript規則和詞匯表)與開發人員實際自定義的內容(也稱為“應用程序邏輯”或“業務邏輯”)十分重要。
回到上面寫的詩:
- // Love at first sight
- if (me.getDistanceTo(you.position) < 200) {
- me.setFeelings({
- inLove: true,
- });
- }
這些表達式來自以下JavaScript詞匯表規則集:
- if (…) { … }
- // if statement: when … is met, do things in { … }
- {
- inLove: true,
- }
- // an “object” with some info, some thing in the world.
- // can contain other info, and “skills” (functions).
- // “inLove” is a custom property,
- // “true” is pre-defined in javascript, (meaning: “yes”)
- // and the value of “inLove”.
- .
- // needed to access an objects property “my name: me.name”
- getDistanceTo()
- // an expression to “call” a function (a “skill”).
- // getDistanceTo is custom (not JavaScript), and a function,
- // so it can be executed / called upon with the “()” after.
- // sometimes you can pass arguments in those brackets (like “position”)
- // to change the outcome of a function.
這些是變量,可以自定義它們的名稱和行為。
- me // an object, some thing in the world
- you // an object, some thing in the world
- position // an info about “you”, accessed by the “.”
- getDistanceTo // a skill of me, accessed by the “.”
- getDistanceTo() // the skill, with javascript grammar telling: do it.
- getDistanceTo(position) // same, but do it with “position”.
- setFeelings // another skill of me, accessed by the “.”
- setFeelings({ inLove: true }); // the skill, with some instructions (anobject).
假設這是一首人類讀得懂的詩,你可能已經理解了其中的信息,也可能看到了需要遵循的JavaScript語言規則與需要提出的內容(變量)之間有何區別。
但機器又會怎么做呢?
如果是機器(瀏覽器)讀取這首詩,那就會識別為錯誤。機器需要一個“me”和“you”的定義,因為它試圖訪問其屬性(通過在me.getDistanceTo()中的“.”來訪問)。有了上面提到的區分能力,實際上你可以設計“me”和“you”,讓計算機能夠執行或讀取詩,如下所示:
- // This is how the definition of a being (me/you)could look like
- var me = {
- position: {x: 0, y: 0} // some coordinates, maybe
- getDistanceTo: function(position) {
- // calculate the distance, relative to own position
- },
- setFeelings: function(feelings) {
- // handle those feelings…
- }
- }
- var you = {
- position: {x: 0, y: 0} // some coordinates, maybe
- }
- // the poem itself
- if (me.getDistanceTo(you.position) < 200) {
- me.setFeelings({
- inLove: true,
- });
- }
那么在這里發生了什么?
- 為了讓人們理解,讀取一首用JavaScript“語法”編寫而成的JavaScript詩;
- 在理解信息之后,為理解詩的結構(JavaScript的語法和基礎知識),對規則、詞匯和變量進行了區分;
- 通過這種區分后,使用JavaScript規則設計了其余的詩歌變量,使其可以通過機器(在瀏覽器中)運行。
這可以做到,因為處理JavaScript,就像處理英語語言一樣。
更大的例子:交互式代碼詩歌
LoveBits是一種代碼學習或用代碼講故事的體驗。

LoveBits:基于JavaScript的代碼詩歌項目
它試圖通過以下方式讓人們對JavaScript或代碼感興趣:
- 將可讀性和人類語言放在***位;
- 將代碼與讀者可能熟知的藝術形式相結合。
故事情節與兩個比特(矩形狀)有關;其中一個比特(blueBit)是浪漫主義者,為另一個比特(purpleBit)寫出JavaScript的愛情詩。
啟動LoveBits時,可選擇其中一首愛情詩(由JavaScript代碼編寫而成)。每首詩都有一個代碼片段,不甚熟悉編程的人都能理解其中的編寫方式。這個項目唯一的要求就是要懂英語。
例如,“love at first sight”(實際上是LoveBits詩歌中的一首)講述的是這兩個比特之間的故事,詩中,blueBit大致是這么說的,“If I get close enough toyour position, I will ‘set my feelings’ to inLove: true.”
這些詩歌的特殊之處在于你可以通過點擊下面的“play”按鈕,“run”或“play”它們。在“Love at first sight”的詩中,你會見到一個藍色和紫色的矩形以及一個數字。正如你猜到的那樣,它們就是詩中提到的兩個比特,而blueBit下面的數字實際上是blueBit和purpleBit之間的距離。
正如詩歌所暗示的那樣,你可能想要通過減少它們之間的距離讓blueBit愛上purpleBit。那要怎么做呢?可以和blueBit互動,把它拖來拖去,讓它墜入愛河。但要小心,有時結果可不只一種。
實際上有人可能會說程序員成為了這里的機器,但程序員才是需要解釋JavaScript代碼,并采取行動幫助兩個數字生物墜入愛河的那個人。
未來將何去何從?
如果你是個奮力拼搏的開發者,試著將JavaScript視為人類語言吧,只了解需首先執行的代碼片段就夠了,不必去考慮它們最終運行的結果。
進一步的建議:
- 永遠優先選擇能將規則、詞匯和變量組合在一起形成應用程序邏輯的整個應用程序;
- 應用程序邏輯會講故事,這些故事將幫你填補上述代碼示例中的空白。代碼庫和實用程序(如lodash)只能提供新的詞匯表,在你能閱讀和理解JavaScript代碼后會有所幫助;
- 檢查現有代碼,并嘗試將其分解為具有反映其功能名稱的小函數。編寫適用于人和機器的代碼,編寫出可以像句子一樣閱讀的代碼,并在需要的地方加以注釋。思考:怎么用人類語言(向另一個開發者)表述這個代碼?
結論
將代碼視為人類語言而不是外星人發明的東西,學習代碼就會更容易。學習區分語言屬性(內置)和應用程序邏輯的變量/自定義代碼至關重要。理解了應用程序邏輯,你就無需了解語言特征即可作出改進和更改。
學習基礎知識前需明白:理解了任一代碼片段的信息,JavaScript的基礎知識自然就能隨之掌握。有多少次你聽到有人說:“我能看懂這種語言,但我還不會說。”這是一個自然過程,能夠并可能適用于人類語言和編碼語言的學習。
此外,請牢記代碼有明確的功能性目的,但也并非總是如此。即使是人類語言,曾經也只滿足純粹的功能性需求,后來才出現了詩歌甚至歌曲(說到這,有人對JavaScript歌曲感興趣嗎?)這些以截然不同方式使人們密切相聯的語言形式。這同樣適用于編程語言。