#JavaScript

前言

部落格需要顯示發佈時間,餐廳網站要顯示訂位時間,拍賣網站則是要顯示訂單的各種時間,無論你做什麼,都會碰到「顯示時間」這個很常見的需求。

這問題看似簡單,不就是顯示個時間嗎?但如果牽扯上「時區」的話,問題就會變得再更複雜一些。以時區來說,通常會有這幾個需求:

  1. 網站上的時間需要在某個固定時區顯示,我在美國跟在台灣要在網站上看到同樣的時間
  2. 網站上的時間會根據使用者的瀏覽器設置不同,我在美國跟在台灣看到的時間會不一樣
  3. PM 根本沒想過這問題,只考慮到當地的使用者,所以暫時不用擔心這個

而這還只是顯示的部分而已,還有另外一個部分是與後端的溝通,這個我們可以待會再提,但總之呢,要正確處理時間跟時區並不是一件簡單的事。

在最近這一兩份工作剛好都有碰過相關的問題,因此對這一塊有點小小心得,就寫了這一篇來跟大家分享一下。

閱讀更多

前言

最近公司的同事修了一門資安相關的課,因為我本來就對資安滿有興趣的,所以就會跟同事討論一下,這也導致了我這兩週一直在研究相關的東西,都是一些以前聽過但沒有認真研究過的,例如說 LFI(Local File Inclusion)、REC(Remote code execution)、SSRF(Server-Side Request Forgery)或是各種 PHP 的神奇 filter,也能複習原本就已經相對熟悉的 SQL Injection 跟 XSS。

而 CTF 的題目裡面常常會出現需要繞過各種限制的狀況,而這就是考驗對於特定協定或者是程式語言的理解程度的時機了,要想想看怎麼在既有的限制之下,找出至少一種方法可以成功繞過那些限制。

原本這一週不知道要寫什麼,想寫上面提的那些東西但還沒想好怎麼整理,之前的 I Don’t know React 後續系列又還沒整理完,就想說那來跟大家做個跟「繞過限制」有關的趣味小挑戰好了,那就是標題所說的:

在 JavaScript 當中,你可以做到不用英文字母與數字,就成功執行 console.log(1) 嗎?

換句話說,就是程式碼裡面不能出現任何英文字母(a-zA-Z)與數字(0-9),除此之外(各種符號)都可以。執行程式碼之後,會執行 console.log(1),然後在 console 印出 1。

如果你有想到以前聽過什麼有趣的服務或是 library 可以做到,先不要。在這之前可以自己先想一下,看有沒有辦法寫出來,然後再去查其他人的解決方法。

若是能從零到有全都自己寫出來,就代表你對 JS 這個程式語言以及各種自動轉型的熟悉程度應該是滿高的。

底下我就提供一下我自己針對這一題的一些想法以及解題過程,有雷,還沒解完不要往下捲動。

==防雷==
==防雷==
==防雷==
==防雷==
==防雷==

閱讀更多

前言

不知道大家有沒有聽過 vite 這個工具,看它名字有個 v,大概就可以猜到可能跟 Vue 有關。沒錯,這是 Vue 的作者尤雨溪開發出來的另外一套工具,原本是想要給 VuePress 用的,但是強大之處就在於它不僅限於此。

Vite 在 GitHub 上的 About 只寫了兩個句子:

Native-ESM powered web dev build tool. It’s fast.

如果你有體驗過,就會發現真的很快。Vite 是 build tool 跟 dev server 的綜合體,這篇會簡單教大家使用一下 vite,然後來談 ES modules,再來看看 vite 神奇的地方。

閱讀更多

前言

如果有先寫過其他 function 不是 first-class 的程式語言,在寫 JavaScript 的時候應該會經歷一些陣痛期,想說到底在做什麼——至少我是這樣的。

我當初發現可以把 function 當作參數到處傳遞的時候,對於比較複雜的 code 就要想很久,而 function 的其他行為也是讓我一頭霧水,例如說 function 居然也是 object,還有 this 到底是什麼鬼東西。

這一篇主要是想分享一些我覺得 function 比較有趣的地方。可是呢,直接開始講一大堆知識太無趣了,我希望能引起大家對這些知識的好奇程度,而想要引起好奇,最好的方法就是提供一個「你也會感興趣的問題」,你就會有動力繼續往下看了。

因此底下就以幾個小問題作為開場,雖然是問題的形式,但答不出來也完全沒有關係,如果你對這些問題的答案有興趣的話再往下看,沒興趣的話出口直走到底左轉。

話說這篇標題本來想取叫:「JavaScript function 知多少」或是「有趣的 JavaScript function」,但這種標題太無趣了,所以才想到這種輕小說式(?)的標題。

閱讀更多

前言

在我以前寫過的兩篇文章:我知道你懂 hoisting,可是你了解到多深?以及所有的函式都是閉包:談 JS 中的作用域與 Closure 裡面,都談到了 let 與 var 作用域的不同。

let 的作用域是 block,而 var 則是 fucntion,像這個就是經典案例:

原本預期會依序輸出 1~10,沒想到卻輸出了 10 個 11。背後原因就是因為第三行那個 i 永遠都只有一個,就是 for 迴圈宣告的那個 var i,從頭到尾都是同一個變數。

而經典解法也很簡單,把 var 改成 let 就搞定了:

搞定的原因是,可以把上面程式碼看作是下面這種形式:

由於 let 的作用域是 block,所以在每一圈迴圈裡面,其實都是一個新的 i,因此迴圈跑 10 圈就有了 10 個不同的 i,最後當然是輸出 10 個不同的數字。

因此 var 跟 let 在這個範例最大的區別就在於變數的數量,前者只有 1 個,後者卻有了 10 個。

好,既然知道了 let 與 var 的差別以後,就可以來看看這篇最主要想討論的問題。

其實這問題是來自於 YDKJS(You Dont Know JS,中譯本翻做:你不知道的JavaScript) 的作者 @getify 在他的推特上所提出的:

question for JS engines devs…
is there an optimization in place for this kind of code?

IOW, where the behavior of creating a new i per iteration is not needed nor observable… does JS skip doing it?

若是沒有看得很懂,可以繼續看延伸的另外一則推

here’s a variation on the question… will JS engines exhibit much performance difference between these two loops?

簡單來說呢,平常用 let 搭配迴圈的時候,不是如我們上面所說的,每一圈都會有一個新的i嗎?既然是這樣的話,那 var 與 let 應該就會有效能上的差異,因為 let 必須每一圈都 new 一個新的變數出來,所以 let 會比較慢。

那如果迴圈裡面並不需要每一圈都有新的 i,JS 引擎會做優化嗎?這個問題就是這樣,主要是想探討 JS 引擎會不會針對這種行為去做優化。

那要怎麼知道呢?要嘛你是 JS 引擎的開發者,要嘛你去看 JS 引擎的原始碼,但這兩種難度都有點太高。不過別擔心,還有第三種:看 JS bytecode。

閱讀更多

前言

在這兩三年之間,「刷題」似乎成為了一種風潮。本科系要去面試大公司的時候要刷題,非本科系出去面試也要刷題,好像只要沒有刷題就會落後他人,就會被公司刷掉。

其實我一直不是很喜歡「刷題」這個詞,主要是因為「刷」這個字。不知道大家對這個字的解讀是什麼,但我會認為有種「為了寫題目而寫題目」的感覺,就好像題海戰術那樣。雖然說題海戰術用得好的話成效滿顯著的,但總感覺很多人刷到最後會變成「看過的題目就會,沒看過的就一定不會」,如果是這樣子的話,那我覺得不是一件好事。

之前我有寫了一篇文章:當我們在學程式時,要學的到底是什麼?,稍微談了一下這件事情。

總之呢,比起刷題這個詞,我更喜歡用「程式解題」四個字來表達我想表達的意思。

閱讀更多

前言

如果要舉出一個在 JavaScript 裡面很重要也很常用,但新手常常搞混的概念,那「非同步(Asynchronous)」當仁不讓,絕對是第一名。跟其他那些 thisclosureprototype 或是 hoisting 比起來,非同步在實際開發的時候用到的頻率高太多了,而且是初學者常常會踩坑的地方。

非同步真的那麼難嗎?

我相信不是的。只要循著一個正確的脈絡前進,就可以循序漸進理解為什麼需要非同步,也能知道在 JavaScript 裡面是怎麼處理這種操作的。

類似的主題我其實在四年前就寫過,但現在回頭看實在是寫得滿差的,所以四年後重新挑戰這個主題,希望能寫出一篇品質不錯的文章,把非同步這件事情講清楚。

在寫這篇文章之前,參考了 Node.js 的官方文件,發現在非同步的講解上其實做得不錯,因此本文會以類似的切入點開始談這個問題。如果不會 Node.js 也沒關係,我底下會稍微做點介紹。

建議閱讀本文以前需要具備 JavaScript 基礎,知道如何使用 JavaScript 操作 DOM,也知道什麼是 ajax。

接著就讓我們開始吧!

閱讀更多

前言

在 JavaScript 裡面,有一個令新手十分頭痛,老手也不一定能完全理解的主題:「this 是什麼?」。身為一個以 JavaScript 當作吃飯工具的前端工程師,我也被這個問題困擾了許久。

我原本以為我這輩子都不會寫有關於 this 的文章。

原因有兩個,第一個是講解 this 的文章已經超級無敵多了,而且每一篇都寫得很不錯,之前看完 What’s THIS in JavaScript ? 系列之後覺得講解的很完整,若是沒有把握自己能夠講得更清楚或是以不同的角度切入,似乎就沒必要再寫一篇文章;第二個原因是若是想要「完全」搞懂 this,要付出的成本可能比你想像中要大得多。

閱讀更多

前言

請先原諒我用了一個比較聳動的標題,因為實在是想不到還有什麼標題好下,最後選擇了一個可能比較有爭議的標題,但能利用這樣的標題激起討論也是滿有趣的,何況我說這話也是有根據的。

在觀看此篇文章之前請先看過上一篇:我知道你懂 hoisting,可是你了解到多深?,因為文章內容有部分相關,所以必須先有 Execution Context 以及 Variable Object 的觀念以後,才能夠吸收這篇文章的東西。

如果你只對文章標題的那句:「所有的函式都是閉包」有興趣,那可以直接往下拉,因為要講閉包就必須先從作用域開始講起,所以這篇文章按照慣例不會太短,前面也會有一定程度的鋪陳。

好,讓我們從作用域開始吧。

閱讀更多

前言

這陣子我在忙一些教學相關的東西,稍微準備一些資料之後教了學生們 JavaScript 裡面的 hoisting,也就是「提升」這個觀念,例如說以下程式碼:

會輸出undefined而不是ReferenceError: a is not defined,這種現象就叫做 Hoisting,變數的宣告被「提升」到最上面去了。

如果你只想了解最基本的 hoisting,其實差不多就是這樣,但後來我還教了letconst相關的一些知識,不過前一天剛教學完,隔天就立刻看到相關的技術文章還發現自己教錯,因此特別花了一點時間打算好好理解 hoisting 這個東西。

很多東西沒有深入研究的時候你都會覺得沒什麼,真的跳下去深入去看才會發現自己其實還有一大堆概念沒有搞懂。

有很多人都知道 hoisting,但是理解程度卻不盡相同,我列出了 10 個項目,如果有任何一點你剛好不知道的話,那恭喜,這篇文章應該可以為你帶來一些收穫。

  1. 你知道什麼是 hoisting
  2. 你知道 hoisting 只會提升宣告而非賦值
  3. 你知道 function 宣告、function 的參數以及一般變數宣告同時出現時的提升優先順序
  4. 你知道 let 跟 const 沒有 hoisting
  5. 你知道第四點是錯的,其實有但只是表現形式不一樣
  6. 你知道有關第五點,有個概念叫做 TDZ(Temporal Dead Zone)
  7. 你看過 ES3 的規格書,知道裡面是怎麼描述的
  8. 你看過 ES6 的規格書,知道裡面是怎麼描述的
  9. 你知道 hoisting 背後的原理是什麼
  10. 你看過 V8 編譯出來的程式碼

你可能會問說:「我為什麼要知道的這麼深?有什麼用?」,其實我也覺得對 hoisting,只要知道基本的就行了。只要你有好好地宣告變數,就算不知道那些,對日常生活或是工作也不會有太大的影響。

可是假如你像我一樣,想要有朝一日在自己的履歷上面放上「精通 JavaScript」的話,那對這些東西就不能逃避。同時你如果對底層的這些細節愈熟悉,會碰到的問題就愈少,也愈能理解為什麼會有 hoisting 的出現,當你想要在技術這條路上走得更遠爬得更高時,我覺得這些細節是很重要的。

接下來,我們就一步步來看 hoisting 吧!

閱讀更多

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×