http://realazy.org/blog/2007/08/20/nine-javascript-gotchas/
來自Nine Javascript Gotchas, 以下是JavaScript容易犯錯的九個陷阱。雖然不是什麼很高深的技術問題,但注意一下,會使您的程式設計輕松些,即所謂make life easier. 筆者對某些陷阱會混雜一些評點。
-
最後一個逗号
如這段代碼,注意最後一個逗号,按語言學角度來說應該是不錯的(python的類似資料類型辭典dictionary就允許如此)。IE會報文法錯誤,但語焉不詳,你隻能用人眼從幾千行代碼中掃描。<script> var theObj = { city : "Boston", state : "MA", } </script>
-
的引用會改變this
并不如你所願,答案并不是”JavaScript rules”。在執行<input type="button" value="Gotcha!" id="MyButton" > <script> var MyObject = function () { this.alertMessage = "Javascript rules"; this.ClickHandler = function() { alert(this.alertMessage ); } }(); document.getElementById("theText").onclick = MyObject.ClickHandler </script>
時,代碼中紅色這行,MyObject.ClickHandler
的引用實際上指向的是this
的引用。可以這麼解決:document.getElementById("theText")
實質上,這就是JavaScript作用域的問題。如果你看過,你會發現解決方案不止一種。<input type="button" value="Gotcha!" id="theText" > <script> var MyObject = function () { var self = this; this.alertMessage = "Javascript rules"; this.OnClick = function() { alert(self.value); } }(); document.getElementById("theText").onclick = MyObject.OnClick </script>
-
辨別盜賊
在JavaScript中不要使用跟HTML的id一樣的變量名。如下代碼:
IE會報對象未定義的錯誤。我隻能說:IE sucks.<input type="button" id="TheButton"> <script> TheButton = get("TheButton"); </script>
-
字元串隻替換第一個比對
如下代碼:
而實際上,結果是”<script> var fileName = "This is a title".replace(" ","_"); </script>
“. 在JavaScript中,This_is a title
的第一個參數應該是正規表達式。是以,正确的做法是這樣:String.replace
var fileName = "This is a title".replace(/ /g,"_");
-
mouseout意味着mousein
事實上,這是由于事件冒泡導緻的。IE中有
和mouseenter
,但不是标準的。作者在此建議大家使用庫比如YUI來解決問題。mouseleave
-
是基于進制體系的parseInt
還有第二個參數,用以指明進制。比如,parseInt
,如果你認為答案是9,那就錯了。因為,在此,字元串以0開頭,parseInt("09")
以八進制來處理它,在八進制中,parseInt
是非法,傳回09
,布爾值false
轉化成數值就是0. 是以,正确的做法是false
.parseInt("09", 10)
-
會周遊所有的東西for...in...
運作得好好的,不是嗎?但是有一天它不幹了,給我傳回的值變成了var arr = [5,10,15] var total = 1; for ( var x in arr) { total = total * arr[x]; }
, 暈。我隻不過引入了一個庫而已啊。原來是這個庫改寫了NaN
的Array
,這樣,我們的prototype
平白無過多出了一個屬性(方法),而arr
會把它給周遊出來。是以這樣做才是比較安全的:for...in...
其實,這也是污染基本類的for ( var x = 0; x < arr.length; x++) { total = total * arr[x]; }
會帶來危害的一個例證。prototype
-
事件處理器的陷阱
這其實隻會存在使用作為對象屬性的事件處理器才會存在的問題。比如window.onclick = MyOnClickMethod
這樣的代碼,這會複寫掉之前的
事件,還可能導緻IE的内容洩露(sucks again)。在IE還沒有支援DOM 2的事件注冊之前,作者建議使用庫來解決問題,比如使用YUI:window.onclick
這應該也屬于常識問題,但新手可能容易犯錯。YAHOO.util.Event.addListener(window, "click", MyOnClickMethod);
-
Focus Pocus
建立一個
文本元素,然後把焦點挪到它上面,按理說,這樣的代碼應該很自然:input
但是IE會報錯(sucks again and again)。理由可能是當你執行var newInput = document.createElement("input"); document.body.appendChild(newInput); newInput.focus(); newInput.select();
的時候,元素尚未可用。是以,我們可以延遲執行:fouce()
var newInput = document.createElement("input"); newInput.id = "TheNewInput"; document.body.appendChild(newInput); setTimeout(function(){ //這裡我使用閉包改寫過,若有興趣可以對比原文 document.getElementById('TheNewInput').focus(); document.getElementById('TheNewInput').select();}, 10);
在實踐中,JavaScript的陷阱還有很多很多,大多是由于解析器的實作不到位而引起。這些東西一般都不會在教科書中出現,隻能靠開發者之間的經驗分享。謝天謝地,我們生活在網絡時代,很多碰到的問題,一般都可以在Google中找到答案。
This entry was postedon Monday, August 20th, 2007 at 02:31 and is filed under JS / Dom.You can follow any responses to this entry through the RSS 2.0 feed.You can leave a response, or trackback from your own site.
21 Responses to “JavaScript的9個陷阱及評點”
-
Cloudream Says:
August 20th, 2007 at 03:32
那個親愛的IE……
-_,-
當然Firefox也有JS處理問題……OPERA同樣也不完美……
(偶承認,偶記不知他們仨HTML解析核心的名字……除了gecko……)
(○ ̄ ~  ̄○)
-
jaceju Says:
August 20th, 2007 at 09:56
譯得好!
不過為什麼標題是 “Scrip” ?是不是少了個 t ?
JavaScript的9個陷阱及評點 http://realazy.org/blog/2007/08/20/nine-javascript-gotchas/ -
子烏 Says:
August 20th, 2007 at 10:53
嗯,其實這些也并不算是陷阱,隻能算是js初學者容易犯的幾個錯誤:D
-
ÀÖÀÖ˶ Says:
August 20th, 2007 at 11:32
JavaScripµÄ9¸ö……
À´×ÔNine Javascript Gotchas, ÒÔÏÂÊÇJavaScriptÈÝÒ×·¸´íµÄ¾Å¸öÏÝÚå¡£ËäÈ»²»ÊÇʲôºÜ¸ßÉîµÄ¼¼ÊõÎÊÌ⣬µ«×¢Òâһϣ¬»áʹÄúµÄ±à³ÌÇáËÉЩ£¬¼´Ëùνmake life easier. ±…
-
cute Says:
August 20th, 2007 at 14:26
都是常犯錯誤。
-
沈蚊 Says:
August 21st, 2007 at 00:03
亞黑的英文真不是一般難看。
-
魏中華 Says:
August 21st, 2007 at 11:12
大緻看了下 YUI,驚歎于它龐大的規模,幾十個檔案夾,動辄數千行,莫非是傳說中的 Javascript 版本的 MFC ?
像我這種對複雜事物特别敏感的人士,似乎很難感興趣,看來要抱憾終生了。
-
kakawar Says:
August 21st, 2007 at 13:27
我覺得jQuery也挺好,因為目前隻會用這個……
-
hax Says:
August 21st, 2007 at 18:04
你的譯文與原文有點不一樣。有些你的評點應該說明一下,不是原文的。
“理由可能是當你執行fouce()的時候,元素還不存在。”
這裡你寫錯了。一個是筆誤,另外一個,元素當然已經存在了。原文說的是not available,不可用而已。
-
hax Says:
August 21st, 2007 at 18:10
To Cloudream:
ie的引擎叫做Trident,三叉戟。
opera似乎沒有專門的名字。
safari是WebCore。
它們的js引擎分别是:
JScript (IE)
SpiderMonkey(FF)
JavaScriptCore(Safari)
linear_b(Opera)
-
yason Says:
August 27th, 2007 at 18:00
确實非常不錯的内容
-
superwunc Says:
September 3rd, 2007 at 09:54
關于第三個陷阱
如果對變量使用var定義了就不會有問題
var TheButton ;
TheButton = get(“TheButton”);
-
fyting Says:
September 8th, 2007 at 15:42
用了好幾個suck,我剛開始以為原文如此,結果發現是你翻譯時把自己的個人喜好也加進去了。
This will work fine in Firefox but cause and object undefined error in Internet Explorer
IE會報對象未定義的錯誤。我隻能說:IE sucks.
-
aw Says:
October 1st, 2007 at 21:30
關于Prototype确實很惡心。用ActionScript2就很爽 ^_^
話說我當年剛開始寫AS的時候,滿眼望去都是Prototype……一個個都是地雷啊!
-
popper Says:
October 8th, 2007 at 08:58
正在學習 中 數于初學着感覺還是很有幫助的 。
-
Akira Says:
November 3rd, 2007 at 11:18
我也來評一下^^
最後一個逗号
如這段代碼,注意最後一個逗号,按語言學角度來說應該是不錯的(python的類似資料類型辭典dictionary就允許如此)。IE會報文法錯誤,但語焉不詳,你隻能用人眼從幾千行代碼中掃描。
————————————————————————————————————————-
這是JS解析器的問題,符合ECMA v3文法規範
這不算一個毛病,追求這個未免有點太……
允許最後一個逗号或許有好處,但是這樣的話,不利于判斷對象的結束,不認真的話也會産生問題
(舉一個可能不是十分恰當的例子:應該沒有人指責C語言字元串中的最後一個”)
this的引用會改變
————————————————————————————————————————-
對于習慣了Class-based OOP的人來說這是一個大問題
this指針怎麼應該改變呢,我也認為不應該
但是JavaScript不是Class-based OOP的語言,而且,更重要的是
它的this是在執行域生效,而不是在文法域生效
JS的函數是可以作為資料來對待的,是以this隻表示執行域上的對象所有者
這很讓人困擾,但是也有好處,好處之一是泛型,這裡我不過多作解釋,需要了解一些進階的概念
辨別盜賊
在JavaScript中不要使用跟HTML的id一樣的變量名。如下代碼:
—————————————————————————————————————–
這個完全不是問題,W3C的規範中DOM對象通過document.getElementById來獲得
它不應該和JS的變量沖突,如果沖突了是浏覽器的問題
例子中的問題加上var就可以避免
字元串隻替換第一個比對
—————————————————————————————————————-
想不出這個為什麼也算問題,或許應該把replace函數分成replaceFirst和replaceAll(笑)
mouseout意味着mousein
事實上,這是由于事件冒泡導緻的。IE中有mouseenter和mouseleave,但不是标準的。作者在此建議大家使用庫比如YUI來解決問題。
—————————————————————————————————————-
IE的事件模型,讨厭的相容性,交給基礎庫去處理
parseInt是基于進制體系的
這個是常識,可是很多人給忽略了parseInt還有第二個參數,用以指明進制。比如,parseInt(“09″),如果你認為答案是9,那就錯了。因為,在此,字元串以0開頭,parseInt以八進制來處理它,在八進制中,09是非法,傳回false,布爾值false轉化成數值就是0. 是以,正确的做法是parseInt(“09″, 10).
————————————————————————————————–
嗯,是啊……C語言的atoi會不會這樣?(笑)
for…in…會周遊所有的東西
————————————————————————————————-
應該是會周遊所有propertyIsEnumerable的東西
是以強烈BS直接修改Object原型的做法
但是數組也不應該用for…in…來周遊,那不符合語義
事件處理器的陷阱
這其實隻會存在使用作為對象屬性的事件處理器才會存在的問題。比如window.onclick = MyOnClickMethod這樣的代碼,這會複寫掉之前的window.onclick事件,還可能導緻IE的内容洩露(sucks again)。在IE還沒有支援DOM 2的事件注冊之前,作者建議使用庫來解決問題,比如使用YUI:
—————————————————————————————————–
嗯,事件模型很令人頭疼……
但是IE用attachEvent可以避免這個問題
Focus Pocus
建立一個input文本元素,然後把焦點挪到它上面,按理說,這樣的代碼應該很自然:
—————————————————————————————————-
這個……沒辦法……
還是事先做好一個hidden的input然後show出來吧
那樣也可以快一些
-
貓魚 Says:
November 29th, 2007 at 17:53
請問為何 第一個例子裡面的
MyObject.ClickHandler
ie總會報錯: MyObject.ClickHandler為空或不是對象?
-
weiye Says:
December 20th, 2007 at 23:49
關于this的問題,樓主的例子是有問題的,
var MyObject = function () {
var self = this;
this.alertMessage = “Javascript rules”;
this.OnClick = function() {
alert(self.value);
}
}();
document.getElementById(”theText”).onclick = MyObject.OnClick
第一個匿名函數的實際調用對象是window,self=this=window。匿名函數調用的結果傳回給MyObjct。它并不具有方法OnClick,OnClick實際是賦給了window。
可以改成這樣
function MyObject () {
this.alertMessage = “Javascript rules”;
this.OnClick = function() {
alert(self.value);
}
};
MyObject.call(MyObject);
document.getElementById(”theText”).onclick = MyObject.OnClick
————————————————————————————————————
第三個在JavaScript中不要使用跟HTML的id一樣的變量名。這根本不是問題。
IE會把id當作dom對象,當然不可以随意指派,使用的時候應該重新定義 TheButton = get(“TheButton”);就像不能直接給self指派一樣,self本身指向window對象。
-
飛天大神豬 Says:
January 8th, 2008 at 09:19
确實是遇到過裡面的一些問題。但不贊成遇到問題随便使用類庫來解決。因為你永遠不知道類庫會帶來什麼後果。
-
JavaScript的9個陷阱 - Elric’s Blog - 關注前端技術,關注生活. Says:
June 17th, 2009 at 09:17
[...] 譯文:http://realazy.org/blog/2007/08/20/nine-javascript-gotchas/ 日志分類:Javascript 标簽:Javascript [...]
-
Physure.com » [轉]JavaScript的陷阱 Says:
February 6th, 2010 at 00:16
[...] 這本來是翻譯Estelle Weyl的《15 JavaScript Gotchas》,裡面介紹的都是在JavaScript程式設計實踐中平時容易出錯或需要注意的地方,并提供避開這些陷阱的方法,總體上講,就是在認清事物本質的基礎樣要堅持好的程式設計習慣,其實這就是Douglas Crockford很久以前提出的JavaScript風格要素問題了,有些内容直接是相同的,具體請看《Javascript風格要素(1)》和《Javascript風格要素(2)》。在翻譯的過程中,我又看到了賢安去年翻譯的《JavaScript的9個陷阱及評點》,其内容又有些交叉在一起,是以我就在現有翻譯的基礎上做了一個簡單的拼合,并依據自己的了解增加了一些注釋和解釋。 [...]