9個Javascript的知識點 (9 JavaScript Tips You May Not Know)

文章有代碼部分,如果有閱讀困難,請到原文閱讀:https://blog.jing.do/4212

前言:本篇文章是我在查詢時偶然間發現的,雖然年代久遠但是依舊非常適合入門學習,特此翻譯下分享給大家,順便給大家加了一些備注方便閱讀(特意加粗刷存在感)。原文全文和鏈接在最后

———————-以下是正文———————-

備注:本篇文章是34歲的程序員Ayman Hourieh在2006年發布的。我找到了他網站的鏈接,但是網站已經不存在了。我用Wayback Machine找到了文章的鏡像。為了讓更多人看到把他摘錄分享出來。我只做了一些鏈接的修改。

JavaScript是一個功能強大的面向對象語言。表面上看他他和JAVA和C非常相似,但是他卻截然不同,其核心在于JavaScript更像一個功能性語言。本篇文章是一些JavaScript的小提示,一部分提供一些類C語言的功能模擬,另一部分是想要提高性能并探討下腳本語言中一些比較難懂的東西。索引如下:

多用途的Array

隊列

二叉樹

String Concatenation 對比 Array.join

給對象綁定方法

使用自定義排序

Assertion

靜態局部變量

null, undefined, and delete

深層嵌套

使用Firebug

$ 和 $$

console.log(format, obj1, …)

console.trace()

inspect(obj)

多用途的Array

盡管JavaScript在數據結構方面看起來很奇特,他的Array比其他編程語言(如C ++或Java)用途更加廣泛。 它通常用作數組或關聯數組,后面將演示如何將其用作堆棧,隊列和二叉樹。 復用Array而不是編寫其他的數據結構有兩個好處:首先,不用浪費時間去重寫已經存在的功能,其次,內置瀏覽器對JavaScript的運行將更高效。

大家都知道棧是后進先出:最后插入的會被最先移除。array有兩個方法來實現棧的功能。他們是push()和pop()。push()用于插入item到array的尾部,而pop()則用于移除并返回最后一個item。以下是代碼的實例:

varstack=[];stack.push(2);// 當前棧是 [2]stack.push(5);// 當前棧是 [2, 5]vari=stack.pop();// 當前棧是 [2]alert(i);// 顯示 5

隊列

隊列是先進先出的:現行插入的將會被最先移除。array可以用push()和shift()來實現隊列。push()用于插入item到尾部,shift()用于移除第一個item。案例如下:

varqueue=[];queue.push(2);// 現在的隊列 [2]queue.push(5);// 現在的隊列 [2, 5]vari=queue.shift();// 現在的隊列 [5]alert(i);// 顯示 2

值得注意的是,array還有一個unshift()的函數。這個函數用于將item放到array的頭部。所以棧也可以使用unshift()/shift(),而隊列可以用unshift()/pop()。

如果這些函數名稱讓你迷茫了(譯者注:因為unshift()是處理頭部,所以相對應的棧需要從頭部出去,隊列需要換到尾部),你可以給他們取個別名,比如,創建隊列的方法名為add和remove:

varqueue=[];queue.add=queue.push;queue.remove=queue.shift;queue.add(1);vari=queue.remove();alert(i);

二叉樹

二叉樹是在樹的節點表示數據。每個節點有一個數據并且有兩個子節點(左叉樹和右叉樹)。在C語言里,這種數據結構通常使用指針來實現。這種實現方法也可以在JavaScript中使用對象和引用來實現。然而,對于一些小的二叉樹,有一種更簡單便捷的方法,array的第一個item作為樹的頭。 如果可以使用以下公式計算節點i,則索引左右節點:

leftChild(i)=2i+1rightChild(i)=2i+2

這張圖揭示了這個算法: (來自于Wikipedia):

正如你所看到的,這種方法并不是JavaScript的獨有之處,但是在處理小的二叉樹時非常有用。 例如,您可以編寫自己的函數來獲取和設置節點的值或子節點,并遍歷二叉樹,這些方法與做計算或for循環一樣簡單。但是,這種方法的缺點是隨著樹的深度增加,浪費的存儲空間越來越多。

String Concatenation 對比 Array.join

大家都知道,如果做太多的字符串鏈接會讓性能下降(譯者注:不知道的去補課),并且這個非常容易避免。如果你想要用各個字符來組成一個字符串,最差的方法是使用+把所有的字符結合到一起:

str='';for(/* each piece */){str+=piece;// bad for performance!}returnstr;

這種方法將使用太多的字符串鏈接,會讓性能枯竭。

在JavaScript中有個更好的辦法,就是Array.join(),他可以讓所有array內的元素連接成一個字符串:

vartmp=[];for(/* each piece */){tmp.push(piece);}str=tmp.join(' ');// 用空格作為分隔符returnstr;

該方法不會受到額外的字符串對象的影響,通常執行的非常高效

給對象綁定方法

任何使用JavaScript事件的人都可能遇到了一種情況,他們需要將對象的方法分配給事件處理程序。 這里的問題是事件處理程序會被HTML調用,即使它們最初被綁定到另一個對象。 為了解決這個問題,我用一個函數將對象和方法綁定; 它他會運行對象和方法,并返回一個在該對象調用該方法的函數。 我在Prototype中找到了一個竅門,并且寫了以下函數來在不包含Prototype的項目中使用它:

functionbind(obj,method){returnfunction(){returnmethod.apply(obj,arguments);}}

如何使用:

varobj={msg:'Name is',buildMessage:function(name){returnthis.msg+' '+name;}}alert(obj.buildMessage('John'));// displays: Name is Johnf=obj.buildMessage;alert(f('Smith'));// displays: undefined Smithg=bind(obj,obj.buildMessage);alert(g('Smith'));// displays: Name is Smith

使用自定義排序

排序是一個常見的工作。 JavaScript提供了一種排序數組的方法。 但是,該方法默認按字母順序排列 —— 非字符串元素在排序之前被強制轉換為字符串,這個使得數字排序會有意想不到的結果:

varlist=[5,10,2,1];list.sort()// list is now: [1, 10, 2, 5]

這個解釋很容易: 數字被強制轉換成了字符串,所以10編程了’10’而2變成了’2’,那么JavaScript對比兩個字符串的時候,先對比第一個字符。如果str1的第一個字符出現在字符集中的第一個字符之前,則str1被認為是“小于”str2。 在我們的情況下,’1’在’2’之前,所以’10’小于’2’。

幸運的是,JavaScript提供一個重寫機制,讓我們可以自定義如何排序,我們用a和b兩個元素最為例子:

如果a

如果a=b,返回0

如果a>b,返回大于0

寫這樣的程序比較容易:

functioncmp(a,b){returna-b;}

我們現在可以使用這個方法來做排序:

varlist=[5,10,2,1];list.sort(cmp);//listisnow:[1,2,5,10]

Array.sort()牛逼的地方是允許更復雜的排序。 假設你有一個論壇帖子,每個帖子看起來像:

varpost={id:1,author:'...',title:'...',body:'...'}

如果你想用id排序,只需要創建以下函數:

functionpostCmp(a,b){returna.id-b.id;}

可以說,使用瀏覽器的方法進行排序將比在JavaScript中實現排序函數更有效。 但是,數據應該在服務器端進行排序。所以,除非必要,否則不應該讓數據在客戶端排序。

Assertion

Assertion是一種常用的調試技術,它用于確保表達式在執行期間計算為真。 如果表達式計算為假,則表示代碼中可能出現的錯誤。 JavaScript缺少一個內置的Assertion功能,但幸運的是,它很容易編寫一個。 如果傳遞的表達式的計算結果為假,以下實現會拋出AssertException類型的異常:

functionAssertException(message){this.message=message;}AssertException.prototype.toString=function(){return'AssertException: '+this.message;}functionassert(exp,message){if(!exp){thrownewAssertException(message);}}

自己拋出異常并不是非常有用,但是當與有用的錯誤消息或調試工具結合使用時,您可以檢測到有問題的部分。

您還可以使用以下代碼段檢查異常是否為Assertion異常:

try{// ...}catch(e){if(einstanceofAssertException){// ...}}

該函數的使用類似于C或Java:

assert(obj!=null,'Object is null');

如果obj碰巧為null,Firefox將在JavaScript控制臺中打印以下消息:

uncaughtexception:AssertException:Objectisnull

Static Local Variables

大家知道,一些語言像C ++,他們有靜態變量的概念,用于函數調用。 JavaScript并不支持此技術。 然而,“功能也是對象”讓這個功能成為可能。 方法是:將靜態變量變為函數的屬性。 假設我們要創建一個計數器函數:

functioncount(){if(typeofcount.i=='undefined'){count.i=0;}returncount.i++;}

當第一次調用count時,count.i是未定義的,所以if條件為true,count.i為0。因為我們將變量存儲為一個函數屬性,它將在函數調用之間保留它的值, 因此它可以被認為是一個靜態變量。

這里有個性能提升小技巧:

functioncount(){returncount.i++;}count.i=0;

雖然第一個例子將Count的所有邏輯封裝在主體中,但第二個例子更為有效。

null, undefined, and delete

因為JavaScript有undefined和null所以他不同于其他語言。null是一個特別的數值,他表示沒有數值。null會被認為一個特別的對象,因為typeof null會返回null。

undefined表示變量沒有被定義,或者定義了但沒有給數值。以下情況都會顯示undefined:

// i is not declared anywhere in codealert(typeofi);vari;alert(typeofi);

雖然undefined和null是兩個不同的類型,但是如果使用 == ,會被判定為相等,但是如果是 === 則不等。

JavaScript還有一個刪除操作符,”undefines”一個屬性,可以將其應用于對象屬性和數組成員,使用var聲明的變量不能被刪除,而是隱式聲明(implicitly declared )的變量可以:

varobj={val:'Some string'}alert(obj.val);// displays 'Some string'deleteobj.val;alert(obj.val);// displays 'undefined'

深層嵌套

如果您需要在深層嵌套對象上執行多個操作,最好將其引用到臨時變量中,而不是每次對其進行解引用。 例如,假設您想在文本字段上執行一系列操作:

document.forms[0].elements[0]

建議您存儲到變量中,并使用此變量而不是以上構造:

varfield=document.forms[0].elements[0];// Use field in loop

每個點都導致一個操作來檢索一個屬性,在一個循環中,這些操作是相加的,所以最好做一次,將對象存儲在變量中并重新使用它。

Using Firebug

Firefox有一個非常棒的擴展,用于調試名為Firebug的JavaScript代碼。 它提供一個具有斷點和堆棧視圖的調試器,以及一個JavaScript控制臺。 它還可以監視Ajax請求。 此外,擴展提供了一組JavaScript函數和對象來簡化調試。 您可以在Firebug的文檔頁面中詳細研究它們。 這里有一些我覺得有用的:

$ and $$

熟悉Prototype的人馬上就認出他們了,

$() 接受一個字符串參數,并返回其ID是傳遞的字符串的DOM元素。(譯者注:Jquery

$('nav')// returns the element whose id is #nav.

$$()返回DOM的數組

$$('div li.menu')// returns an array of li elements that are// located inside a div and has the .menu class

console.log(format, obj1, …)

console對象提供顯示log消息的方法,這個將比alert更加好用,console.log()有點像C里面的printf,他會將輸入轉化為字符串在console中展示:

vari=1;console.log('i value is %d',i);// prints:// i value is 3

console.trace()

此方法打印一個堆棧跟蹤調用它。 它不需要輸入參數

inspect(obj)

該功能需要一個參數。 它切換到檢查選項卡并檢查傳遞的對象。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,196評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,688評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,456評論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,955評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,195評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,725評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,608評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,802評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,048評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,424評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,762評論 2 372

推薦閱讀更多精彩內容

  • 第5章 引用類型(返回首頁) 本章內容 使用對象 創建并操作數組 理解基本的JavaScript類型 使用基本類型...
    大學一百閱讀 3,261評論 0 4
  • 原文: https://github.com/ecomfe/spec/blob/master/javascript...
    zock閱讀 3,388評論 2 36
  • Repo是干什么的? 用來統一管理Android源代碼的工具 Repo命令 核心形式:repo 列如: re...
    wusp閱讀 1,327評論 0 0
  • 今天我們一起來學習一本書叫《正向力》。 激發個人正向力,提升團隊戰斗力,也就是怎樣通過培養正向力,來提升一個人的幸...
    聽雨廖哥閱讀 254評論 0 0
  • 不知道刪除了多少文字 更不知道為什么亂七八糟 我覺得好像 寫了我的出生 回憶的我的成長 記錄的愛情 感受了親情 都...
    窮奇閱讀 191評論 2 1