「譯」 JavaScript 開發者經常忽略或誤用的七個基礎知識點

JavaScript, at its base, is a simple language that we continue to evolve with intelligent, flexible patterns. We've used those patterns in JavaScript frameworks which fuel our web applications today. Lost in JavaScript framework usage, which many new developers are thrust right into, are some of the very useful JavaScript techniques that make basic tasks possible. Here are seven of those basics:

JavaScript 本身可以算是一門簡單的語言,但我們也不斷用智慧和靈活的模式來改進它。昨天我們將這些模式應用到了 JavaScript 框架中,今天這些框架又驅動了我們的 Web 應用程序。很多新手開發者被各種強大的 JavaScript 框架吸引進來,但他們卻忽略了框架身後浩如星海的 JavaScript 實用技巧。本文將為你呈獻其中七個基礎知識點:

1. String.prototype.replace: /g and /i Flags

1. 在 String.prototype.replace 方法中使用 /g 和 /i 標誌位

One surprise to many JavaScript newbies is that String's replace method doesn't replace all occurrences of the needle -- just the first occurrence. Of course seasoned JavaScript vets know that a regular expression and the global flag (/g) need to be used:

令很多 JavaScript 初學者意外的是,字符串的 replace 方法並不會 替換所有匹配的子串——而僅僅替換第一次匹配。當然 JavaScript 老手們都知道這裡可以使用正則表達式,並且需要加上一個全局標誌位(/g):

// Mistake
// 踩到坑了
var str = "David is an Arsenal fan, which means David is great";
str.replace("David", "Darren"); // "Darren is an Arsenal fan, which means David is great"
// Desired
// 符合預期
str.replace(/David/g, "Darren"); // "Darren is an Arsenal fan, which means Darren is great"

Another basic logical mistake is not ignoring case when case is not critical to the validation (letters may be uppercase or lowercase), so the /i flag is also useful:

另一個基本的邏輯錯誤就是在大小寫不敏感的校驗場合(字母可大寫可小寫)沒有忽略大小寫,此時 /i標誌位就很實用:

str.replace(/david/gi, "Darren"); // "Darren will always be an Arsenal fan, which means Darren will always be great"

(譯註:上面這段例程我沒有看懂用意,可能是註釋有誤吧……)

Every JavaScript developer has been bitten by each of the flags in the past -- so be sure to use them when when appropriate!

每個 JavaScript 開發者都曾踩過這兩個標誌位的坑——因此別忘了在適當的時候用上它們!

2. Array-Like Objects and Array.prototype.slice

2. 類數組對象和 Array.prototype.slice 方法

Array's slice method is principally for grabbing segments of an array. What many developers don't know is that slice can be used to covert Array-like objects like arguments, NodeLists, and attributes into true arrays of data:

數組的 slice 方法通常用來從一個數組中抽取片斷。但很多開發者不瞭解的是,這個方法還可以用來將“類數組”元素(比如 arguments 參數列表、節點列表和屬性列表)轉換成真正的數組:(譯註:DOM 元素的屬性列表通過 attributes 屬性獲取,比如 document.body.attributes。)

var nodesArr = Array.prototype.slice.call(document.querySelectorAll("div"));
// "true" array of DIVs
// 得到一個由 div 元素組成的“真正的”數組
var argsArr = Array.prototype.slice.call(arguments);
// changes arguments to "true" array
// 把 arguments 轉換成一個“真正的”數組

You can even clone an array using a simple slice call:

你還可以使用一次簡單的 slice 調用來克隆一個數組:

var clone = myArray.slice(0); // naive clone
 // 淺克隆

(譯註:這裡的參數 0 也可以省略,我估計 undefined 被 slice 方法自動轉換為 0 了吧。)

Array.prototype.slice is an absolute gem in the world of JavaScript, one that even novice JavaScript developers don't know the full potential of.

Array.prototype.slice 絕對是 JavaScript 世界中的一玫珍寶,但 JavaScript 初學者們顯然還沒有意識到它的全部潛力。

3. Array.prototype.sort

3. Array.prototype.sort 方法

The Array sort method is vastly underused and probably a bit more powerful than most developers believe. Many developers would assume sort would do something like this:

數組的 sort 方法 遠遠沒有被充分利用,而且可能比開發者們想像的更加強大。很多開發者可能覺得 sort 方法可以用來做這種事情:

[1, 3, 9, 2].sort();
 // Returns: [1, 2, 3, 9]
 // 返回 [1, 2, 3, 9]

...which is true, but sort has more powerful uses, like this:

……這沒錯,但它還有更強大的用法,比如這樣:

[
 { name: "Robin Van PurseStrings", age: 30 },
 { name: "Theo Walcott", age: 24 },
 { name: "Bacary Sagna", age: 28 }
].sort(function(obj1, obj2) {
 // Ascending: first age less than the previous
 // 實現增序排列:前者的 age 小於後者
 return obj1.age - obj2.age;
});
 // Returns: 
 // [
 // { name: "Theo Walcott", age: 24 },
 // { name: "Bacary Sagna", age: 28 },
 // { name: "Robin Van PurseStrings", age: 30 }
 // ]

You can sort objects by property, not just simple basic items. In the event that JSON is sent down from the server and objects need to be sorted, keep this in mind!

你不僅可以對簡單類型的數組項進行排序,可以通過屬性來排序對象。如果哪天服務器端發來一段 JSON 數據,而且其中的對象需要排序,你可別忘了這一招!

4. Array Length for Truncation

4. 用 length 屬性來截斷數組

There's not a developer out there that hasn't been bitten by JavaScript's pass-objects-by-reference nature. Oftentimes developers will attempt to empty an array but mistakenly create a new one instead:

幾乎所有開發者都踩過 JavaScript 的這個坑——“傳對象只是傳引用”。開發者們經常會試圖 把一個數組清空,但實際上卻錯誤地創建了一個新數組。

var myArray = yourArray = [1, 2, 3];
// :(
// 囧
myArray = []; // `yourArray` is still [1, 2, 3]
 // `yourArray` 仍然是 [1, 2, 3]
// The right way, keeping reference
// 正確的方法是保持引用
myArray.length = 0; // `yourArray` and `myArray` both []
 // `yourArray` 和 `myArray`(以及其它所有對這個數組的引用)都變成 [] 了

What these developers probably realize is that objects are passed by reference, so while setting myArray to [] does create a new array, other references stay the same! Big mistake! Use array truncation instead.

坑裡的人們終於明白,原來傳對象只是在傳引用。因此當我把 myArray 重新賦值為 [] 時,確實會創建出一個新的空數組,但其它對老數組的引用仍然沒變!大坑啊!還是換用截斷的方法吧,少年。

5. Array Merging with push

5. 使用 push 來合併數組

I showed in point 2 that Array's slice and apply can do some cool stuff, so it shouldn't surprise you that other Array methods can do the same trickery. This time we can merge arrays with the push method:

在上面的第 2 節裡,我展示了數組的 slice 和 apply 方法所能組合出的幾個小妙招,所以對於數組方法的其它技巧,你應該已經做好心理準備了吧。這次我們使用 push 方法來合併數組:

var mergeTo = [4,5,6];
var mergeFrom = [7,8,9];
Array.prototype.push.apply(mergeTo, mergeFrom);
mergeTo; // is: [4, 5, 6, 7, 8, 9]

A wonderful example of a lessor-known, simple native method for completing the basic task of array merging.

這是一項不為人知的小技巧,簡單的原生方法就可以實現數組合並這樣的常見任務。

(譯註:這個方法的巧妙之處不僅在於 push 方法可以接收多個參數,還涉及到 apply 方法的第二個參數的用法。)

6. Efficient Feature/Object Property Detection

6. 高效探測功能特性和對象屬性

Oftentimes developers will use the following technique to detect a browser feature:

很多時候開發者們會像下面這樣來探測瀏覽器的某個特性:

if(navigator.geolocation) {
 // Do some stuff
 // 在這裡乾點事情
}

While that works correctly, it isn't always efficient, as that method of object detection can initialize resources in the browser. In the past, the snippet above caused memory leaks in some browsers. The better and more efficient route is checking for a key within an object:

當然這可以正常工作,但它並不一定有很好的效率。因為這個對象探測方法會在瀏覽器中初始化資源。在過去,上面的代碼片斷可能會在某些瀏覽器下導致內存洩露。更好、更快的方法是檢查對象是否包含某個鍵名:

if("geolocation" in navigator) {
 // Do some stuff
 // 在這裡乾點事情
}

This key check is as simple as it gets and may avoid memory problems. Also note that if the value of a property is falsy, your check will fail despite the key being present.

鍵名檢查十分簡單,而且可以避免內存洩露。另外請注意,如果這個屬性的值是假值,那麼前一種探測方式將會得到“否”的結果,並不能真正探測出這個鍵名是否存在。

7. Event preventDefault and stopPropagation

7. 事件對象的 preventDefault 和 stopPropagation 方法

Oftentimes we trigger functionality when action elements like links are clicked. Obviously we don't want the browser to follow the link upon click, so we use our handy JavaScript library's Event.stop method:

很多時候,當一個動作元素(比如鏈接)被點擊時,會觸發某個功能。顯然我們並不希望點擊鏈接時瀏覽器順著這個鏈接跳轉,於是我們會習慣性地使用 JavaScript 類庫的 Event.stop 方法:

$("a.trigger").on("click", function(e) {
 e.stop();
 // Do more stuff
 // 在這裡乾點事情
});

(譯註:不知道哪個類庫有這個方法,估計其作用相當於 return false; 吧。語法看起來像 jQuery,但 jQuery 並沒有這個方法,而且 jQuery 是支持 e.preventDefault 和 e.stopPropagation 方法的。)

The problem with this lazy method of stopping the event is that not only does it prevent the default action, but it stops propagation of the event, meaning other event listeners for the elements wont fire because they don't know about the event. It's best to simply use preventDefault!

這個懶方法有一個問題,它不僅阻止了瀏覽器的默認動作,同時也阻止了事件繼續冒泡。這意味著元素上綁定的其它事件監聽器將不會被觸發,因為它們根本就不知道有事件發生。此時不妨使用 preventDefault 吧!

Seasoned JavaScript developers will see this post and say "I knew those," but at one point or another, they got tripped up on some of these points. Be mindful of the little things in JavaScript because they can make a big difference.

JavaScript 老鳥們看到這篇文章可能會說“我早知道了”,但說不定什麼時候,他們就會在某一點上栽跟頭。提醒大家留意 JavaScript 中的各種小細節,失之毫厘謬以千里啊!

希望本文能幫助到您!

點贊+轉發,讓更多的人也能看到這篇內容(收藏不點贊,都是耍流氓-_-)

關注 {我},享受文章首發體驗!

每週重點攻克一個前端技術難點。更多精彩前端內容私信 我 回覆“教程”

原文鏈接:https://github.com/cssmagic/blog/issues/21


分享到:


相關文章: