jQuery創始人知道function test(){}這樣定義函數不好嗎?

在javascript語言精粹這本書里指出…function test( ){ }這樣定義函數是不好的,推薦用: var test = function( ){ }。

既然函數function test( ){ }這樣定義函數不規範,違反了 先定義後執行 的特點,那麼為什麼好多優秀的資料(比如精通javascript....)仍然這樣寫?是因為jQuery創始人他不知道嗎?


你可以嘗試把DC和JR拉在一起讓他們討論這個問題,他們應該會用眼角瞟你一眼,嘀咕一句「這人傻了吧」,然後高興地相互摟著腰去吃飯了……

很顯然蝴蝶書就是一本給入門者看的,你100%遵循裡面的原則會達到「不容易寫出糟糕代碼」的程度,但這不代表以下2點的任何一點:

  1. 你不會寫出糟糕的代碼
  2. 不遵循這些原則就一定寫出糟糕的代碼

先定義後使用?你信不信2個函數相互調用的時候直接就精分了?

var test = function () {}就一定好?你信不信ES7繼續往下推出function decorator的時候不能對這種形式定義的函數用?

JR是什麼水平的人大家都知道,雖然我個人還是小小地不爽他的代碼風格的,但其是JavaScript方向上站在山頂看我們努力攀爬這一點,是很難有人反對的

到這個層次的人,他知道應該做什麼,怎麼做是好的,他的目標已經從「遵循某個教義」變為了「寫出好的代碼」,某些教義只是他的工具,工具不適合的場景就換工具,如此簡單

我自己也不認為蝴蝶書里的所謂原則有多大的好處,對於函數定義這一點我的規則是:

  1. 定義後不會再變的,用函數定義
  2. 定義後這個變數的值還會變的,如要做一次bind的,或者要在某個if里改為其它函數的,用var
  3. 在分支、循環里的,一概用var


我想知道你們看了 Haskell 的 where 語法又該怎麼想呢?

——

補充,我看前面還是沒有講清楚,其實根本沒有什麼「先定義後執行」原則。請問贊同這個原則的人,什麼叫「先定義」?你們能解釋清楚嗎?如果是指函數代碼必須寫在其調用之前,那麼如此你的代碼必將變得難於閱讀。因為這樣就是讓所有函數按照倒置的Dependency Graph進行排列,最末端最底層的工具函數放到最前面,而高層的業務邏輯代碼反而出現在最後面。你打開一個程序,先映入眼帘的是一些瑣碎的工具函數代碼,拖到下面才看到主體邏輯,這合理嗎?看:

function convert(arrayOfModel) {
function mark(model) {
// 如果 mark、isValid 函數代碼有幾十行,
// 你自己看看是將它寫在前面好還是後面好?
}
function isValid(model) {
//......
}
return arrayOfModel.map(mark).filter(isValid);
}

那為什麼會有「先定義後執行」這種說法呢?

—— 其實壓根沒這說法啊!

回去把書多讀幾遍看,哪本書說函數定義必須寫在調用前面的?那明明是「先聲明再使用」啊,「聲明 Declaration」和「定義 Definition」分得清嗎?像C語言中,你必須在調用之前先寫上函數聲明,不然編譯器會猜錯。C語言中可以單獨寫函數聲明,但JS這類語言函數定義聲明無法分開來寫。像《Java編程思想》那樣推薦將 public 方法寫在 private 方法前面,豈不是總是與你們不知從哪兒聽來的「先定義再使用」的原則相悖了? JavaScript中函數聲明語句有Hoisting,所以不存在什麼先聲明先定義的麻煩,本就是為了讓你寫的爽,你卻不領情? 至於什麼時候用 var 什麼時候用函數聲明語句,贊同 @張立理 的規則。

————

Babel作者寫的一個插件Demo,我感覺明明是在嘲諷DC啊:

sebmck/babel-plugin-example · GitHub

Bob hates function declarations with a passion (nobody knows why). Bob loves to enforce this on his
coworkers, he"s snuck this plugin into their build system to force his tyrannical code style.

PS:Please don"t be like Bob.


盡信書則不如無書。

別教條主義。


那是因為題主你假設 JavaScript 語言精粹的作者 Douglas Crockford 的水平要比 jQuery 作者 John Resig 的水平高。然而事實並不見得是這樣。

這兩個人都曾經是 ECMA TC39 的成員,對 JavaScript 有足夠的了解,不會存在連這些常見做法都不知道的情況。John Resig 不這樣寫,只是他不見得贊同 Douglas Crockford 的觀點,覺得 function test() {} 完全 OK 而已。

JavaScript 語言精粹是一本充滿了作者偏見的書,有些偏見可能是對的,有些偏見可能是錯的,沒必要因為作者是個磚家就一概信之,兼聽則明就好。


只要你知道它們各自有什麼區別,使用有什麼結果,就可以合理利用,這兩種方式並沒有很明顯的好壞之分。

而這本書里,作者是有個人偏好的,不能全信。你這種情況有點像,拿到一個鎚子,看哪都像釘子。


這個寫法也不能算是不好。甚至我還聽說過這種寫法更好。

我記得有種說法是,如果用 var fn = function () {} 的方式定義函數,那麼這個函數在拋錯的時候,trace 記錄里會顯示這是個匿名函數。而用 function fn () {} 的形式定義則是具名函數。

不懂現在 vm 對於這一塊是不是做過優化,效果一樣了。

如果把函數看做一等公民的話,確實 var fn 的形式看起來更統一。而且 coffeescript 翻譯過來的代碼也是長這個樣子的。

但說起來哈,http://github.com/tj 的代碼也是喜歡寫 function fn () {} 這種形式的。

jquery 的作者內力高深,在這種複雜度完全不高的地方,選擇了一個他更習慣的。僅此而已啦。


貨物崇拜

貨物崇拜_百度百科


書里沒說為什麼不好嗎。你複製上來討論一下。


function test(){}這種方式還是有自己的使用場景的,比如將輔助邏輯後置,突出主要邏輯,方便代碼閱讀者理清整體結構。舉例如下:

function veryLongFn(request, response) {

var email = request.data.email;

var name = request.data.name;

if (!isEmailValid(email)) {

response.end("error");

}

if (!isNameValid(name)) {

response.end("error");

}

// 驗證通過,執行相關代碼

function isEmailValid() {

// 可能有五十行代碼

}

function isNameValid() {

// 可能有一百行代碼

}

}

上面的代碼中,其他人來閱讀的時候,第一眼看見的代碼就是簡潔的主幹邏輯代碼,不會被有點長的驗證代碼嚇住。

當然,一般情況下,示例中的驗證函數會被提出來,方便其他地方復用。此處的例子僅是為了說明這種風格明顯增加了代碼的可讀性。


雖然的確是 C 系語法的歷史遺留沒錯,但兩者還是有區別的,這大概也是沒有被廢棄的原因之一,譬如 var a = function b(){},你可以試著賦值或是列印來看看 a b 的區別。

最後嘮叨一句,閉包函數(特別是回調場景)不匿名才是真正的好習慣,不要問為什麼,多實踐多編碼,自己慢慢去體會。


違反了又咋滴~


我暈,怎麼沒人說函數表達式和和函數聲明式?

var eat = function () {bala bala };只有運行到這裡了,這個函數名才指向函數,所以在需要動態改變函數實現的地方 使用函數表達式定義。

函數聲明式 function eat () ??會在創建上下文環境的時候,這個函數就會被加入到作用域鏈裡面。這就是為什麼你用聲明式定義在全局的函數,可以在聲明前使用,早就被加入作用域鏈了,而表達式需要運行到那裡了才會加入作用域鏈。


最好的方法就是多寫代碼,寫多了就慢慢總結出經驗了,盡信書不如無書,那是出書人的喜好


為毛就是喜歡在某本書或某些博客里看了幾段字之後就來說好很不好


不知道在哪裡看到的是說function test(){}這種方式更好,然後就一直用這種。。。可能這種寫起來更方便更快,當然各人習慣不同。。。個人感覺吧怎麼順眼怎麼寫。。。


事實是一般編程都用function test(){},因為省事。。。此外,現在編程語言都流行對變數進行默認初始化。從int、string等多種變數類型到$、var直接定義變數,再到現在直接使用,其實一直都在簡單化。

自己用著習慣就好。


推薦閱讀:

參加 2017 年 8 月 26 日北京第三屆 FEDAY 是個什麼樣的體驗?
Weebly 官網是怎麼把 2560x1400 的圖片壓縮到如此之小的?
React 有哪些優秀實用的組件?
HTML5 能不能完全取代 Flash ?
為什麼有那麼多編輯器插件?

TAG:Web開發 | 前端開發 | JavaScript |