九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
[轉(zhuǎn)]JavaScript的陷阱

版權(quán)聲明

:轉(zhuǎn)載時(shí)請(qǐng)以超鏈接形式標(biāo)明文章原始出處和作者信息及本聲明

http://monw3c.blogbus.com/logs/31056019.html

這本來(lái)是翻譯Estelle Weyl的《15 JavaScript Gotchas》

,里面介紹的都是在JavaScript編程實(shí)踐中平時(shí)容易出錯(cuò)或需要注意的地方,并提供避開這些陷阱的方法,總體上講,就是在認(rèn)清事物本質(zhì)的基礎(chǔ)樣要堅(jiān)持好的編程習(xí)慣,其實(shí)這就是Douglas Crockford很久以前提出的JavaScript風(fēng)格要素問(wèn)題了,有些內(nèi)容直接是相同的,具體請(qǐng)看《Javascript風(fēng)格要素(1)》
《Javascript風(fēng)格要素(2)》
。在翻譯的過(guò)程中,我又看到了賢安去年翻譯的《JavaScript的9個(gè)陷阱及評(píng)點(diǎn)》
,其內(nèi)容又有些交叉在一起,所以我就在現(xiàn)有翻譯的基礎(chǔ)上做了一個(gè)簡(jiǎn)單的拼合,并依據(jù)自己的理解增加了一些注釋和解釋。

  1. 區(qū)分大小寫:變量名、屬性和方法全部都區(qū)分大小寫
  2. 不匹配的引號(hào)、圓括號(hào)或花括號(hào)將拋出錯(cuò)誤
  3. 條件語(yǔ)句:3個(gè)常見陷阱
  4. 換行:一直用分號(hào)結(jié)束語(yǔ)句來(lái)避免常見的換行問(wèn)題
  5. 標(biāo)點(diǎn)法:在對(duì)象聲明的尾部逗號(hào)將導(dǎo)致出錯(cuò)
  6. HTML id 沖突
  7. 變量作用域:全局變量對(duì)局部變量
  8. 函數(shù)重載:當(dāng)重載不存在時(shí),覆蓋函數(shù)
  9. 區(qū)分string.replace()函數(shù)不是全局的
  10. parseInt應(yīng)該包含兩個(gè)參數(shù)
  11. “this”和綁定問(wèn)題
  12. 為參數(shù)設(shè)置默認(rèn)值,以免你遺漏它們
  13. for each循環(huán)是用于對(duì)象而不是數(shù)組
  14. switch語(yǔ)句需要點(diǎn)技巧
  15. 如果你要檢查null,應(yīng)該先檢查undefined
  16. 時(shí)間處理陷阱

區(qū)分大小寫

變量名和函數(shù)名都是區(qū)分大小寫的。就像配錯(cuò)的引號(hào)一樣,這些大家都知道。但是,由于錯(cuò)誤是不作聲的,所以這是一個(gè)提醒。為自己選擇一個(gè)命名規(guī)則,并堅(jiān)持它。而且,記住JavaScript中的原生函數(shù)和CSS屬性都是駱駝拼寫法(camelCase)

getElementById(’myId’) != getElementByID(’myId’); //它應(yīng)該是“Id”而不是“ID”getElementById(’myId‘) != getElementById(’myID‘); // “Id”也不等于“ID”document.getElementById('myId').style.Color; //返回 "undefined"

不匹配的引號(hào)、圓括號(hào)或花括號(hào)

避免陷入不匹配的引號(hào)、圓括號(hào)或花括號(hào)陷阱的最好方式是編碼時(shí)一直同時(shí)寫出打開和關(guān)閉這兩個(gè)元素符號(hào),然后在其中間加入代碼。開始:

var myString = ""; //在輸入字符串值之前寫入這對(duì)引號(hào)function myFunction(){if(){//關(guān)閉每個(gè)打開的括弧}}//統(tǒng)計(jì)所有的左括號(hào)和右括號(hào)數(shù)量,并且確保它們相等alert(parseInt(var1)*(parseInt(var2)+parseInt(var3))); //關(guān)閉每個(gè)打開的圓括號(hào)

每當(dāng)你打開一個(gè)元素,請(qǐng)關(guān)閉它。當(dāng)你添加了關(guān)閉圓括號(hào)后,你再把函數(shù)的參數(shù)放進(jìn)圓括號(hào)中。如果有一串圓括號(hào),統(tǒng)計(jì)所有打開的圓括號(hào)和所有關(guān)閉的圓括號(hào),并且確保這兩個(gè)數(shù)字相等。

條件語(yǔ)句(3個(gè)陷阱)

  1. 所有的條件語(yǔ)句都必須位于圓括號(hào)中。執(zhí)行語(yǔ)句主體不管是一句還是多句都強(qiáng)烈建議用花括號(hào)包圍起來(lái),這樣能避免很多因修改或嵌套而產(chǎn)生的潛在錯(cuò)誤。
    if(var1 == var2){//statement}
  2. 不要犯無(wú)意地使用賦值運(yùn)算符的錯(cuò)誤:把第二個(gè)參數(shù)的值賦給第一個(gè)參數(shù)。因?yàn)樗且粋€(gè)邏輯問(wèn)題,它將一直返回true且不會(huì)報(bào)錯(cuò)。
    if(var1 = var2){} // 返回true。把var2賦值給var1
  3. JavaScript是弱類型,除了在switch語(yǔ)句
    中。當(dāng)JavaScript在case比較時(shí),它是非弱類型。
    var myVar = 5;    if(myVar == '5'){ //返回true,因?yàn)镴avaScript是弱類型    alert("hi");  //這個(gè)alert將執(zhí)行,因?yàn)镴avaScript通常不在意數(shù)據(jù)類型    }    switch(myVar){    case '5':    alert("hi"); //這個(gè)alert將不會(huì)執(zhí)行,因?yàn)閿?shù)據(jù)類型不匹配    }    

換行

當(dāng)心JavaScript中的硬換行。換行被解釋為表示行結(jié)束的分號(hào)。即使在字符串中,如果在引號(hào)中包括了一個(gè)硬換行,那么你會(huì)得到一個(gè)解析錯(cuò)誤(未結(jié)束的字符串)。

var bad  = '<ul id="myId"><li>some text</li><li>more text</li></ul>'; // 未結(jié)束的字符串錯(cuò)誤var good = '<ul id="myId">' +‘<li>some text</li>‘ +‘<li>more text</li>‘ +‘</ul>’; // 正確

前面討論過(guò)的換行被解釋為分號(hào)的規(guī)則并不適用于控制結(jié)構(gòu)這種情況:條件語(yǔ)句關(guān)閉圓括號(hào)后的換行并不是給其一個(gè)分號(hào)。

一直使用分號(hào)和圓括號(hào),那么你不會(huì)因換行而出錯(cuò),你的代碼易于閱讀,且除了那些不使用分號(hào)的怪異源碼外你會(huì)少一些顧慮:所以當(dāng)移動(dòng)代碼且最終導(dǎo)致兩個(gè)語(yǔ)句在一行時(shí),你無(wú)需擔(dān)心第一個(gè)語(yǔ)句是否正確結(jié)束。

多余的逗號(hào)

在任何JavaScript對(duì)象定義中,最后一個(gè)屬性決不能以一個(gè)逗號(hào)結(jié)尾。Firefox不會(huì)出錯(cuò),而IE會(huì)報(bào)語(yǔ)法錯(cuò)誤。

var theObj = {city : "Boston",state : "MA",//IE6和IE7中有“缺少標(biāo)識(shí)符、字符串或數(shù)字”的錯(cuò)誤,IE8 beta2修正了它}

HTML id 沖突

JavaScript DOM綁定(JavaScript DOM bindings)

允許通過(guò)HTML id索引。在JavaScript中函數(shù)和屬性共享同一個(gè)名字空間。所以,當(dāng)在HTML中的一個(gè)id和函數(shù)或?qū)傩杂邢嗤拿謺r(shí),你會(huì)得到難以跟蹤的邏輯錯(cuò)誤。然而這更多是一個(gè)CSS最佳實(shí)踐
的問(wèn)題,當(dāng)你不能解決你的JavaScript問(wèn)題時(shí),想起它是很重要的。

<ul><li id="length">1</li><li id="thisLength">2</li><li id="thatLength">3</li></ul><script>var listitems = document.getElementsByTagName('li');var liCount = listitems.length; //IE下返回的是<li id="length">1</li>這個(gè)節(jié)點(diǎn)而不是所有<li的數(shù)量var thisLength = document.getElementById('thisLength');thatLength = document.getElementById('thatLength');//IE下會(huì)出現(xiàn)“對(duì)象不支持此屬性和方法”的錯(cuò)誤,IE8 beta2下首次加載頁(yè)面會(huì)出錯(cuò),刷新頁(yè)面則不會(huì)//在IE中thisLength和thatLength直接表示以其為id值的DOM節(jié)點(diǎn),//所以賦值時(shí)會(huì)出錯(cuò),當(dāng)有var聲明時(shí),IE會(huì)把其當(dāng)著變量,這個(gè)時(shí)候就正常了。</script>

如果你要標(biāo)記(X)HTML,絕不要使用JavaScript方法或?qū)傩悦鳛閕d的值。并且,當(dāng)你寫JavaScript時(shí),避免使用 (X)HTML中的id值作為變量名。

變量作用域

JavaScript中的許多問(wèn)題都來(lái)自于變量作用域:要么認(rèn)為局部變量是全局的,要么用函數(shù)中的局部變量覆蓋了全局變量。為了避免這些問(wèn)題,最佳方案是根本沒有任何全局變量。但是,如果你有一堆,那么你應(yīng)該知道這些陷阱。

不用var關(guān)鍵字聲明的變量是全局的。記住使用var關(guān)鍵字聲明變量,防止變量具有全局作用域。在下面例子中,在函數(shù)中聲明的變量具有全局變量,因?yàn)闆]有使用var關(guān)鍵字聲明:

anonymousFuntion1 = function(){globalvar = 'global scope'; //全局聲明,因?yàn)?#8220;var”遺漏了return localvar;}();alert(globalvar); //彈出“global scope”,因?yàn)楹瘮?shù)中的變量是全局聲明anonymousFuntion2 = function(){var localvar = 'local scope'; //使用“var”局部聲明return localvar;}();alert(localvar); //錯(cuò)誤 “localvar未定義”。沒有全局定義localvar

作為參數(shù)引進(jìn)到函數(shù)的變量名是局部的。如果參數(shù)名也是一個(gè)全局變量的名字,像參數(shù)變量一樣有局部作用域,這沒有沖突。如果你想在函數(shù)中改變一個(gè)全局變量,這個(gè)函數(shù)有一個(gè)參數(shù)復(fù)制于這個(gè)全局變量名,記住所有全局變臉都是window對(duì)象的屬性。

var myscope = "global";function showScope(myscope){return myscope; //局部作用域,即使有一個(gè)相同名字的全局變量}alert(showScope('local'));function globalScope(myscope){myscope = window.myscope; //全局作用域return myscope;}alert(globalScope(’local’));

你甚至可以在循環(huán)中聲明變量:

for(var i = 0; i < myarray.length; i++){}

覆蓋函數(shù)/重載函數(shù)

當(dāng)你不止一次的聲明一個(gè)函數(shù)時(shí),這個(gè)函數(shù)的最后一次聲明將覆蓋掉該函數(shù)的所有前面版本且不會(huì)拋出任何錯(cuò)誤或警告。這不同于其他的編程語(yǔ)言,像Java,你能用相同的名字有多重函數(shù),只要它們有不同的參數(shù):調(diào)用函數(shù)重載。在JavaScript中沒有重載。這使得不能在代碼中使用JavaScript核心部分的名字極其重要。也要當(dāng)心包含的多個(gè)JavaScript文件,像一個(gè)包含的腳本文件可能覆蓋另一個(gè)腳本文件中的函數(shù)。請(qǐng)使用匿名函數(shù)和名字空間。

(function(){// creation of my namespace 創(chuàng)建我的名字空間if(!window.MYNAMESPACE) {window['MYNAMESPACE'] = {};}//如果名字空間不存在,就創(chuàng)建它//這個(gè)函數(shù)僅能在匿名函數(shù)中訪問(wèn)function myFunction(var1, var2){//內(nèi)部的函數(shù)代碼在這兒}// 把內(nèi)部函數(shù)連接到名字空間上,使它通過(guò)使用名字空間能訪問(wèn)匿名函數(shù)的外面 window['MYNAMESPACE']['myFunction'] = myFunction;})(); // 圓括號(hào) = 立即執(zhí)行// 包含所有代碼的圓括號(hào)使函數(shù)匿名

這個(gè)例子正式為了實(shí)現(xiàn)解決上一個(gè)陷阱“變量作用域”的最佳方案。匿名函數(shù)詳細(xì)內(nèi)容請(qǐng)看《Javascript的匿名函數(shù)》

。YUI
整個(gè)庫(kù)只有YAHOO和YAHOO_config兩個(gè)全局變量,它正是大量應(yīng)用匿名函數(shù)和命名空間的方法來(lái)實(shí)現(xiàn),具體請(qǐng)看《Javascript的一種模塊模式》
。

字符串替換

一個(gè)常見錯(cuò)誤是假設(shè)字符串替換方法的行為會(huì)對(duì)所有可能匹配都產(chǎn)生影響。實(shí)際上,JavaScript字符串替換只改變了第一次發(fā)生的地方。為了替換所有發(fā)生的地方,你需要設(shè)置全局標(biāo)識(shí)。同時(shí)需要記住String.replace()的第一個(gè)參數(shù)是一個(gè)正則表達(dá)式。

var myString = "this is my string";myString = myString.replace("","%20"); // "this%20is my string"myString = myString.replace(/ /,"%20"); // "this%20is my string"myString = myString.replace(/ /g,"%20"); // "this%20is%20my%20string"

parseInt

在JavaScript得到整數(shù)的最常見錯(cuò)誤是假設(shè)parseInt返回的整數(shù)是基于10進(jìn)制的。別忘記第二個(gè)參數(shù)基數(shù),它能是從2到36之間的任何值。為了確保你不會(huì)弄錯(cuò),請(qǐng)一直包含第二個(gè)參數(shù)。

parseInt('09/10/08'); //0parseInt(’09/10/08′,10); //9, 它最可能是你想從一個(gè)日期中得到的值

如果parseInt沒有提供第二個(gè)參數(shù),則前綴為 ‘0x’ 的字符串被當(dāng)作十六進(jìn)制,前綴為 ‘0′ 的字符串被當(dāng)作八進(jìn)制。所有其它字符串都被當(dāng)作是十進(jìn)制的。如果 numString 的前綴不能解釋為整數(shù),則返回 NaN(而不是數(shù)字)。

‘this’

另一個(gè)常見的錯(cuò)誤是忘記使用“this”。在JavaScript對(duì)象中定義的函數(shù)訪問(wèn)這個(gè)對(duì)象的屬性,但沒有使用引用標(biāo)識(shí)符“this”。例如,下面是錯(cuò)誤的:

function myFunction() {var myObject = {objProperty: "some text",objMethod: function() {alert(objProperty);}};myObject.objMethod();}function myFunction() {var myObject = {objProperty: "some text",objMethod: function() {alert(this.objProperty);}};myObject.objMethod();}

有一篇A List Apart文章

用通俗易懂的英文表達(dá)了this綁定的問(wèn)題。

對(duì)this使用最大的陷阱是this在使用過(guò)程中其引用會(huì)發(fā)生改變:

<input type="button" value="Gotcha!" id="MyButton"><script>var MyObject = function () {this.alertMessage = "Javascript rules";this.ClickHandler = function() {alert(this.alertMessage );//返回結(jié)果不是”JavaScript rules”,執(zhí)行MyObject.ClickHandler時(shí),//this的引用實(shí)際上指向的是document.getElementById("theText")的引用}}();document.getElementById(”theText”).onclick =  MyObject.ClickHandler</script>

其解決方案是:

var MyObject = function () {var self = this;this.alertMessage = “Javascript rules”;this.OnClick = function() {alert(self.value);}}();

類似問(wèn)題的更多細(xì)節(jié)和解決方案請(qǐng)看《JavaScript作用域的問(wèn)題》

遺漏的參數(shù)

當(dāng)給函數(shù)增加一個(gè)參數(shù)時(shí),一個(gè)常見的錯(cuò)誤是忘記更新這個(gè)函數(shù)的所有調(diào)用。如果你需要在已經(jīng)被調(diào)用的函數(shù)中增加一個(gè)參數(shù)來(lái)處理一個(gè)特殊情況下的調(diào)用,請(qǐng)給這個(gè)函數(shù)中的這個(gè)參數(shù)設(shè)置默認(rèn)值,以防萬(wàn)一在眾多腳本中的眾多調(diào)用中的一個(gè)忘記更新。

function addressFunction(address, city, state, country){country = country || “US”; //如果沒有傳入country,假設(shè) “US”span>//剩下代碼}

你也能通過(guò)獲取arguments來(lái)解決。但是在這篇文章我們的注意力在陷阱上。同時(shí)在《Javascript風(fēng)格要素(2)》

也介紹了||巧妙應(yīng)用。

for關(guān)鍵字

在JavaScript中關(guān)鍵字for有兩種使用方式,一個(gè)是for語(yǔ)句,一個(gè)是for/in語(yǔ)句。for/in語(yǔ)句將遍歷所有的對(duì)象屬性(attribute),包括方法和屬性(property)。決不能使用for/in來(lái)遍歷數(shù)組:僅在當(dāng)需要遍歷對(duì)象屬性和方法時(shí)才使用for/in。

  1. for(var myVar in myObject)語(yǔ)句用一個(gè)指定變量無(wú)任何規(guī)律地遍歷對(duì)象的所有屬性。如果for/in循環(huán)的主體刪除了一個(gè)還沒有枚舉出的屬性,那么該屬性就不在枚舉。如果循環(huán)主體定義了新屬性,那么循環(huán)是否枚舉該屬性則是由JavaScript的實(shí)現(xiàn)決定。
  2. for(var 1=0; i < myArray.length; i++)語(yǔ)句會(huì)遍歷完一個(gè)數(shù)組的所有元素。

為了解決這個(gè)問(wèn)題,大體上你可以對(duì)對(duì)象使用 for … in,對(duì)數(shù)組使用for循環(huán):

listItems = document.getElementsByTagName('li');for (var listitem in listItems){//這里將遍歷這個(gè)對(duì)象的所有屬性和方法,包括原生的方法和屬性,但不遍歷這個(gè)數(shù)組:出錯(cuò)了!}//因?yàn)槟阋h(huán)的是數(shù)組對(duì)象,所用for循環(huán)for ( var i = 0; i < listItems.length; i++) {//這是真正你想要的}

對(duì)象的有些屬性以相同的方式標(biāo)記成只讀的、永久的或不可列舉的,這些屬性for/in無(wú)法枚舉。實(shí)際上,for/in循環(huán)
會(huì)遍歷所有對(duì)象的所有可能屬性,包括函數(shù)和原型中的屬性。所有修改原型屬性可能對(duì)for/in循環(huán)帶來(lái)致命的危害,所以需要采用hasOwnProperty和typeof做一些必要的過(guò)濾,最好是用for來(lái)代替for/in。

switch語(yǔ)句

Estelle Weyl寫了一篇switch statement quirks

,其要點(diǎn)是:

  1. 沒有數(shù)據(jù)類型轉(zhuǎn)換
  2. 一個(gè)匹配,所有的表達(dá)式都將執(zhí)行直到后面的break或return語(yǔ)句執(zhí)行
  3. 你可以對(duì)一個(gè)單獨(dú)語(yǔ)句塊使用多個(gè)case從句

undefined ≠ null

null是一個(gè)對(duì)象,undefined是一個(gè)屬性、方法或變量。存在null是因?yàn)閷?duì)象被定義。如果對(duì)象沒有被定義,而測(cè)試它是否是null,但因?yàn)闆]有被定義,它無(wú)法測(cè)試到,而且會(huì)拋出錯(cuò)誤。

if(myObject !== null  && typeof(myObject) !== 'undefined') {//如果myObject是undefined,它不能測(cè)試是否為null,而且還會(huì)拋出錯(cuò)誤}if(typeof(myObject) !== 'undefined' && myObject !== null) {//處理myObject的代碼}

Harish Mallipeddi

對(duì)undefined和null有一個(gè)說(shuō)明。

事件處理陷阱

剛接觸事件處理時(shí)最常見的寫法就是類似:

window.onclick = MyOnClickMethod

這種做法不僅非常容易出現(xiàn)后面的window.onclick事件覆蓋掉前面的事件,還可能導(dǎo)致大名頂頂?shù)腎E內(nèi)存泄露問(wèn)題。為了解決類似問(wèn)題,4年前Simon Willison

就寫出了很流行的addLoadEvent():

function addLoadEvent(func) {var oldonload = window.onload;if (typeof window.onload != 'function') {window.onload = func;}else {window.onload = function() {oldonload();unc();}}}addEvent(window,'load',func1,false);addEvent(window,'load',func2,false);addEvent(window,'load',func3,false);

當(dāng)然在JavaScript庫(kù)盛行的現(xiàn)在,使用封裝好的事件處理機(jī)制是一個(gè)很好的選擇,比如在YUI中就可以這樣寫:

YAHOO.util.Event.addListener(window, "click", MyOnClickMethod);
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服