WEB開發者必備的7個JavaScript函式

webhek發表於2016-02-29

  我記得數年前,只要我們編寫JavaScript,都必須用到幾個常用的函式,比如,addEventListener 和 attachEvent,並不是為了很超前的技術和功能,只是一些基本的任務,原因是各種瀏覽器之間的差異造成的。時間過去了這麼久,技術在不斷的進步,仍然有一些JavaScript函式是幾乎所有Web程式設計師必備的,或為了效能,或為了功能。

 防止高頻呼叫的debounce函式

  這個 debounce 函式對於那些執行事件驅動的任務來說是必不可少的提高效能的函式。如果你在使用scroll, resize, key*等事件觸發執行任務時不使用降頻函式,也行你就犯了重大的錯誤。下面這個降頻函式 debounce 能讓你的程式碼變的高效:

// 返回一個函式,that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
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);
	};
};

// Usage
var myEfficientFn = debounce(function() {
	// All the taxing stuff you do
}, 250);
window.addEventListener('resize', myEfficientFn);

  這個 debounce 函式在給定的時間間隔內只允許你提供的回撥函式執行一次,以此降低它的執行頻率。當遇到高頻觸發的事件時,這樣的限制顯得尤為重要。

 設定時間/頻率迴圈檢測函式

  上面提到的 debounce 函式是藉助於某個事件的觸發。但有時候並沒有這樣的事件可用,那我們只能自己寫一個函式來每隔一段時間檢查一次。

function poll (fn, callback, err, timeout, interval) {
    var startTime = (new Date()).getTime();
    var pi = window.setInterval(function(){
        if (Math.floor(((new Date).getTime() - startTime) / 1000) <= timeout) {
            if (fn()) {
                callback();
            }
        } else {
            window.clearInterval(pi);
            err();
        }
    }, interval)
}

 禁止重複呼叫、只允許執行一次的once 函式

  很多時候,我們只希望某種動作只能執行一次,就像是我們使用 onload 來限定只在載入完成時執行一次。下面這個函式就能讓你的操作執行一次後就不會再重複執行。

function once(fn, context) { 
	var result;

	return function() { 
		if(fn) {
			result = fn.apply(context || this, arguments);
			fn = null;
		}

		return result;
	};
}

// Usage
var canOnlyFireOnce = once(function() {
	console.log('Fired!');
});

canOnlyFireOnce(); // "Fired!"
canOnlyFireOnce(); // nada

  這個 once 函式能夠保證你提供的函式只執行唯一的一次,防止重複執行。

 獲取一個連結的絕對地址 getAbsoluteUrl

  獲取連結的絕對地址並不像你想象的那麼簡單。下面就是一個非常實用的函式,能根據你輸入的相對地址,獲取絕對地址:

var getAbsoluteUrl = (function() {
	var a;

	return function(url) {
		if(!a) a = document.createElement('a');
		a.href = url;

		return a.href;
	};
})();

// Usage
getAbsoluteUrl('/something'); // http://www.webhek.com/something

  這裡使用了 a 標籤 href 來生成完整的絕對URL,十分的可靠。

 判斷一個JavaScript函式是否是系統原生函式 isNative

  很多第三方js指令碼都會在全域性變數裡引入新的函式,有些甚至會覆蓋掉系統的原生函式,下面這個方法就是來檢查是不是原生函式的:

;(function() {

  // Used to resolve the internal `[[Class]]` of values
  var toString = Object.prototype.toString;
  
  // Used to resolve the decompiled source of functions
  var fnToString = Function.prototype.toString;
  
  // Used to detect host constructors (Safari > 4; really typed array specific)
  var reHostCtor = /^\[object .+?Constructor\]$/;

  // Compile a regexp using a common native method as a template.
  // We chose `Object#toString` because there's a good chance it is not being mucked with.
  var reNative = RegExp('^' +
    // Coerce `Object#toString` to a string
    String(toString)
    // Escape any special regexp characters
    .replace(/[.*+?^${}()|[\]\/\\]/g, '\\$&')
    // Replace mentions of `toString` with `.*?` to keep the template generic.
    // Replace thing like `for ...` to support environments like Rhino which add extra info
    // such as method arity.
    .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
  );
  
  function isNative(value) {
    var type = typeof value;
    return type == 'function'
      // Use `Function#toString` to bypass the value's own `toString` method
      // and avoid being faked out.
      ? reNative.test(fnToString.call(value))
      // Fallback to a host object check because some environments will represent
      // things like typed arrays as DOM methods which may not conform to the
      // normal native pattern.
      : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false;
  }
  
  // export however you want
  module.exports = isNative;
}());

// Usage
isNative(alert); // true
isNative(myCustomFunction); // false

  這個方法雖然不是那麼的簡潔,但還是可以完成任務的!

 用JavaScript建立新的CSS規則 insertRule

  有時候我們會使用一個CSS選擇器(比如 document.querySelectorAll)來獲取一個 NodeList ,然後給它們每個依次修改樣式。其實這並不是一種高效的做法,高效的做法是用JavaScript新建一段CSS樣式規則:

// Build a better Sheet object 
Sheet = (function() {
	// Build style
	var style = document.createElement('style');
	style.setAttribute('media', 'screen');
	style.appendChild(document.createTextNode(''));
	document.head.appendChild(style);

	// Build and return a single function
	return function(rule){ style.sheet.insertRule( rule, style.sheet.cssRules.length ); } ;
})();

// Then call as a function
Sheet(".stats { position: relative ; top: 0px }") ;

  這些做法的效率非常高,在一些場景中,比如使用ajax新載入一段html時,使用上面這個方法,你不需要操作新載入的html內容。

 判斷網頁元素是否具有某種屬性和樣式 matchesSelector

function matchesSelector(el, selector) {
	var p = Element.prototype;
	var f = p.matches || p.webkitMatchesSelector || p.mozMatchesSelector || p.msMatchesSelector || function(s) {
		return [].indexOf.call(document.querySelectorAll(s), this) !== -1;
	};
	return f.call(el, selector);
}

// Usage
matchesSelector(document.getElementById('myDiv'), 'div.someSelector[some-attribute=true]')

  就是這7個JavaScript函式,每個Web程式設計師都應該知道怎麼用它們。你可以在評論裡寫出其它你認為必備的函式,分享出來,謝謝。

相關文章