Re: [問題] 根據 if 決定叫用哪一個function

看板Ajax作者 (彷彿曾經一起死過)時間14年前 (2011/09/21 13:12), 編輯推噓4(403)
留言7則, 5人參與, 最新討論串7/8 (看更多)
雖然跟原po問題無關 但好像有人對為什麼 function my_function(){ do some stuff } 這種寫法不好感到好奇 在網路上 這篇文章有很詳細的解釋 http://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/ 但可能大家懶得看英文 所以看看我能不能解釋一下 可能有點長.. 首先js裡有一個東西 叫做hoisting 意思就是"提起來" "拉起來" 那到底是拉甚麼東西哩? 當我們作一個declaration 被browser解讀時 他會自動被放到他context的最上面 比如說: (function(){ alert(my_var); var my_var = 'say something man'; })(); 這裡不會產生js的ReferenceError 因為在 interpreter 眼裡是長這樣 (function(){ var my_var = undefined; alert(my_var); my_var = 'say something man'; })(); my_var已經被定義了(雖然是assign "undefined" object) 所以firebug裡不會看到 ReferenceError: my_var is not defined 那這和function有甚麼關係哩 比較以下兩例: (function(){ my_func(); var my_func= function(){ alert('yo'); }; })(); (function(){ my_func(); function my_func(){ alert('yo'); }; })(); 第一個會有 TypeError: my_func is not a function 第二個則會跑出"yo" 因為他被解讀為 (function(){ var my_func = undefined; my_func(); my_func= function(){ alert('yo'); }; })(); (function(){ function my_func(){ alert('yo'); }; my_func(); })(); 有看到差異了嗎? 在hoisting中 declaration會被整個搬上去 而var xx = function yy(){};這種寫法 只有左邊的部分是declaration 所以搬上去時 右邊不見了 這意味著甚麼呢? function yy(){};這種寫法 在同一個context裡 不管你寫在哪 全部都呼叫的到 和順序無關 有人會說 這超好的呀 網路script就是要隨便寫都通 要forgiving一點 這當然沒錯 就像var就有變數 管他甚麼型別 但是其實這種code在維護上有很大的缺點 1. 這某種層度像是種變數汙染 感覺還沒寫過的東西 上面卻叫得出來 或是不小心用到了同樣名字 會產生難預料又難debug的問題 2. Overwrite問題: (function(){ function sayHelloThenHi(){ alert('hello'); } sayHelloThenHi(); function sayHelloThenHi(){ alert('hi'); } sayHelloThenHi(); })(); 這會有甚麼結果呢? 他會跟你講兩聲hi 直觀上這是我們想要的嗎? (function(){ var sayHelloThenHi=function(){ alert('hello'); } sayHelloThenHi(); sayHelloThenHi = function(){ alert('hi'); } sayHelloThenHi(); })(); 此例中 他會先說hello在說hi 感覺似乎是我們比較想要的結果 至於為什麼? 相信你已經知道了 結論: 那到底要怎麼寫function比較好呢 1. 如果你JAVA或是C#等等classical的語言實在太強了 為什麼要為js這種詭異的prototypal語言改習慣?? 那千萬記住把function xxx(){}這種東西寫在每個context的最前面 這就可以省掉大部分錯誤和麻煩 (這也就是很多js的書說宣告變數要在最前面) 2. 如果你想鑽研js這詭異的語言 你的function應該大部分會出現在你global abatement的object下面 如 var MySite = { my_awesome_func : function(){ //do something good } }; MySite.my_awesome_func(); //invoke 或是expression的寫法 var callback = function(){ do some useful stuff }; 這常常用於callback的傳遞... 總之你應該不會有機會寫 function bad(){ //still do something } 這種東西 真是抱歉 講太多廢話了.. 一打就很難停下來.. 因為國內有少數教材 常會有不是很正確的觀念 讓我以前剛學習時 走了不少冤枉路 以至於看到種觀念有關的東西 我就特別想講 加上js又是很特別的語言 常常有人用其他語言的邏輯來套 但事實上含意是不同的 希望有人有耐心可以看到這裡 如果有錯誤 也希望可以指正:D ※ 引述《senser (彷彿曾經一起死過)》之銘言: : 您可能對於js的function宣告方式沒有很清楚 : 但我想可能很多人也有不正確的認識 : js的function宣告方式分為兩種 : function declaration和function expressions : 主要會因為hoisting 而有些微的不同 : invoke的方式 大概分為四種 : 主要和this的binding有關 : 在這例子中 您的設計想法是完全可行且合理的 : 只是實做上要注意 : 首先如果你加了() 就是一種invocation : 意思就是執行這function : 所以應該寫成 : $(selector).mousedown(function(){ : if(using IE){ : func1(); //invoke : }else { : func2(); //invoke : } : }); : 如果你不直接invoke : 應該用function expression : 因為functon declaration絕不應出現在{}block中 : 在if中作function declaration : 每個browser對這種錯誤會有不同的奇怪詮釋 : (新的browser supports 所謂的 function statement) : 再者也有可能因為hoisting而overwrite的問題產生 : if(using IE){ : var myHandler = func1; : }else { : var myHandler = func2; : } : $(selector).mousedown(myHandler); //function copying : 有興趣可以參考這兩篇 : http://kangax.github.com/nfe/ : http://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/ : ※ 引述《coldollsheep (加油加油^^)》之銘言: : : 不好意思 問一個比較粗淺的問題 : : 我做了一個按鈕 點了會有聲音 : : IE 跟其他瀏覽器是採用不同的方法 : : 如以下程式碼 : : 可以看到我毎次點擊都必須判斷一次 : : //關鍵那顆鈕 : : $('#click_btn').mousedown(function (ev) : : { : : //1.處理音效 : : if ($.browser.msie) : : { : : document.getElementById("soundeffect").src=soundfile; : : } else : : { : : var _audio2 = document.createElement('audio') ; : : _audio2.src = soundfile ; : : _audio2.play() : : } : : } : : ---- : : 有沒有辦法變成這樣 : : func1() : : { : : 實際內容 : : } : : func2() : : { : : 實際內容 : : } : : //1.處理音效 : : if ($.browser.msie) : : { : : playsound() = func1(); <------這裡就是關鍵 我不知道怎麼弄這裡 : : 觀念不好不好意思 : : } else : : { : : playsound() = func2(); : : } : : //關鍵那顆鈕 : : $('#click_btn').mousedown(function (ev) : : { : : //1.處理音效 : : playsound(); : : } -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 71.104.219.9 ※ 編輯: senser 來自: 71.104.219.9 (09/21 13:23)

09/21 14:30, , 1F
推清楚明白 尤其是當你需要讓function的內容依情況而有
09/21 14:30, 1F

09/21 14:30, , 2F
所改變時 一定不能用function xxx()的寫法
09/21 14:30, 2F

09/21 18:33, , 3F
簡單說就是 var 和 function declaration 的差異
09/21 18:33, 3F

09/22 13:39, , 4F
寫的太好了!
09/22 13:39, 4F

09/22 18:28, , 5F
好文~
09/22 18:28, 5F

09/22 19:03, , 6F
我是把 var=func() 當做是 function pointer
09/22 19:03, 6F

09/22 19:05, , 7F
C 會有重複宣告錯誤,js 重複宣告是後面的宣告會覆蓋前面的
09/22 19:05, 7F
文章代碼(AID): #1EUN8c01 (Ajax)
討論串 (同標題文章)
文章代碼(AID): #1EUN8c01 (Ajax)