歡迎光臨
每天分享高質量文章

7 個基本的 JS 函式

我記得早期的 JavaScript ,要完成任何事情幾乎都繞不開一些簡單的函式,因為瀏覽器提供商實現功能有所差異,而且不只是邊緣功能,基礎功能也一樣,如 addEventListener 和 attachEvent。雖然時代變了,但仍有一些函式是每個開發者都應該掌握的,以便於完成某些功能和提高效能。

debounce

對於高耗能事件,debounce 函式是一種不錯解決方案。如果你不對 scroll、resize、和 key* 事件使用 debounce 函式,那麼你幾乎等同於犯了錯誤。下麵的 debounce 函式能讓你的程式碼保持高效:

// 傳回一個函式,如果它被不間斷地呼叫,它將不會得到執行。該函式在停止呼叫 N 毫秒後,再次呼叫它才會得到執行。如果有傳遞 ‘immediate’ 引數,會馬上將函式安排到執行佇列中,而不會延遲。

function debounce(func, wait, immediate) {

var timeout;

return function() {

var context = this, args = arguments;

var later = function() {

timeout = null;

if (!immediate) func.apply(context, args);

};

var callNow = immediate && !timeout;

clearTimeout(timeout);

timeout = setTimeout(later, wait);

if (callNow) func.apply(context, args);

};

};

// 用法

var myEfficientFn = debounce(function() {

// 所有繁重的操作

}, 250);

window.addEventListener(‘resize’, myEfficientFn);

debounce 函式不允許回呼函式在指定時間內執行多於一次。當為一個會頻繁觸發的事件分配一個回呼函式時,該函式顯得尤為重要。

poll

儘管上面我提及了 debounce 函式,但如果事件不存在時,你就不能插入一個事件以判斷所需的狀態,那麼就需要每隔一段時間去檢查狀態是否達到你的要求。

function poll(fn, callback, errback, timeout, interval) {

var endTime = Number(new Date()) + (timeout || 2000);

interval = interval || 100;

(function p() {

// 如果條件滿足,則執行!

if(fn()) {

callback();

}

// 如果條件不滿足,但並未超時,再來一次

else if (Number(new Date()) < endTime) {

setTimeout(p, interval);

}

// 不匹配且時間消耗過長,則拒絕!

else {

errback(new Error(‘timed out for ‘ + fn + ‘: ‘ + arguments));

}

})();

}

// 用法:確保元素可見

poll(

function() {

return document.getElementById(‘lightbox’).offsetWidth > 0;

},

function() {

// 執行,成功的回呼函式

},

function() {

// 錯誤,失敗的回呼函式

}

);

Polling 在 web 中已被應用很長時間了,併在將來仍會被使用。

once

有時候,你想讓一個給定的功能只發生一次,類似於 onload 事件。下麵的程式碼提供了你所說的功能:

function once(fn, context) {

var result;

return function() {

if(fn) {

result = fn.apply(context || this, arguments);

fn = null;

}

return result;

};

}

// 用法

var canOnlyFireOnce = once(function() {

console.log(‘Fired!’);

});

canOnlyFireOnce();

// “Fired!”

canOnlyFireOnce();

// 沒有執行指定函式

once 函式確保給定函式只能被呼叫一次,從而防止重覆初始化!

getAbsoluteUrl

從一個字串變數得到一個絕對 URL,並不是你想象中這麼簡單。對於某些 URL 建構式,如果你不提供必要的引數就會出問題(而有時候你真的不知道提供什麼引數)。下麵有一個優雅的技巧,只需要你傳遞一個字串就能得到相應的絕對 URL。

var getAbsoluteUrl = (function() {

var a;

return function(url) {

if(!a) a = document.createElement(‘a’);

a.href = url;

return a.href;

};

})();

// 用法

getAbsoluteUrl(‘/something’);

// http://davidwalsh.name/something

a 元素的 href 處理和 url 處理看似無意義,而 return 陳述句傳回了一個可靠的絕對 URL。

isNative

如果你想知道一個指定函式是否是原生的,或者能不能透過宣告來改寫它。下麵這段便於使用的程式碼能給你答案:

;(function() {

// 用於處理傳入引數 value 的內部 `[[Class]]`

var toString = Object.prototype.toString;

// 用於解析函式的反編譯程式碼

var fnToString = Function.prototype.toString;

// 用於檢測宿主建構式 (Safari > 4 ;真的輸出特定的陣列)

var reHostCtor = /^[object .+?Constructor]$/;

// 用一個標準的原生方法作為模板,編譯一個正則運算式。

// 我們選擇 ‘Object#toString’ 因為它一般不會被汙染。

var reNative = RegExp(‘^’ +

// 將 ‘Object#toString’ 強制轉為字串

String(toString)

// 轉義所有指定的正則運算式字元

.replace(/[.*+?^${}()|[]/]/g, ‘$&’)

// 用 ‘.*?’ 替換提及的 ‘toString’ ,以保持模板的通用性。

// 將 ‘for …’ 之類的字元替換掉,以相容 Rhino 等環境,因為這些環境添加了額外的資訊,如方法引數數量。

.replace(/toString|(function).*?(?=()| for .+?(?=])/g, ‘$1.*?’) + ‘$’

);

function isNative(value) {

var type = typeof value;

return type == ‘function’

// 用 ‘Function#toString’ (fnToString)繞過了值(value)本身的 ‘toString’ 方法,以免被偽造所欺騙。

? reNative.test(fnToString.call(value))

// 回退到宿主物件的檢查,因為某些環境(瀏覽器)將型別陣列(typed arrays)之類的東西當作 DOM 方法,此時可能不遵循標準的原生正則運算式。

: (value && type == ‘object’ && reHostCtor.test(toString.call(value))) || false;

}

// 匯出函式

module.exports = isNative;

}());

// 用法

isNative(alert);

// true

isNative(myCustomFunction);

// false

這個函式雖不完美,但它能完成任務!

insertRule

我們都知道能透過選擇器(透過 document.querySelectorAll )獲取一個 NodeList ,並可為每個元素設定樣式,但有什麼更高效的方法為選擇器設定樣式呢(例如你可以在樣式表裡完成):

var sheet = (function() {

// 建立

贊(0)

分享創造快樂