参考原文:7 Essential JavaScript Functions 以下是意译。
早期,由于浏览器厂商对 JavaScript 实现不同,我们通常需要一些简单的函数来实现某些边缘特性,甚至某些基本特性,比如 addEventListener
和 attachEvent
。现在,虽然时代进步了,但仍有一些函数需要开发者掌握,以便于性能优化和快速开发。
去抖 Debounce
去抖(debounce)函数可以提高某些事件绑定的性能,如果你没有为 scroll
、resize
和 key*
事件使用去抖函数,你的代码很可能是性能低下的,下面是一个 debounce
函数的实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| 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);
|
在给定的时间段内,去抖函数至多只允许回调函数被调用一次,这对于某些频繁触发的事件回调特别有用。
深入阅读
轮询 Poll
有时你需要在指定状态时才触发某些事件,而当前状态很可能不是你所需要的,所以我们需要在一定时间间隔内来轮询当前状态:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| 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 () { } );
|
轮询函数在 Web 开发中一直都非常实用,将来也一样。
深入阅读
只触发一次 Once
某些时候,你希望一个函数只被调用一次,比如 onload
事件的回调函数,那么下面代码是你需要的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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(); canOnlyFireOnce();
|
once
函数确保给定的函数只被调用一次,以防止重复初始化。
深入阅读
获取绝对路径 getAbsoluteUrl
从一个字符串变量中获取绝对 URL 地址并不是想象的那么简单,这里有一个巧妙的实现来从一个字符串获取绝对 URL:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| var getAbsoluteUrl = (function () { var a; return function (url) { if (!a) { a = document.createElement('a'); } a.href = url; return a.href; }; })(); getAbsoluteUrl('/something');
|
元素 a
的 href
属性给你带来了简单的实现,并返回一个可靠的绝对 URL。
深入阅读
判断是否是原生函数 isNative
当你想要重写一个函数时,很有必要知道该函数是否是引擎的原生函数,下面的代码将能判断一个函数是否是原生函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| ;(function () { var toString = Object.prototype.toString; var fnToString = Function.prototype.toString; var reHostCtor = /^\[object .+?Constructor\]$/; var reNative = RegExp('^' + String(toString) .replace(/[.*+?^${}()|[\]\/\\]/g, '\\$&') .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' ); function isNative(value) { var type = typeof value; return type == 'function' ? reNative.test(fnToString.call(value)) : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false; } module.exports = isNative; }()); isNative(alert); isNative(myCustomFunction);
|
上面代码看上去并不那么优雅,但最终实现了我们想要的功能。
深入阅读
插入样式规则 insertRule
我们可以通过 document.querySelectorAll
来获取到一些节点,然后依次为这些节点设置样式,但更有效的方法在样式表中是通过选择器来设置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| var sheet = (function () { var style = document.createElement('style'); style.appendChild(document.createTextNode('')); document.head.appendChild(style); return style.sheet; })(); sheet.insertRule("header { float: left; opacity: 0.8; }", 1);
|
对于一些动态的重度 AJAX 的网站来说,这个函数非常有用,通过选择器来设置样式,你就不再需要为符合这个选择器的每个元素单独设置(现在不要这样做,将来更不要)。
深入阅读
元素匹配 matchesSelector
通常,我们在进一步操作之前都需要验证输入的合法性,以确保数据的有效性和真实性等。但我们如何验证一个给定的元素是否满足指定的选择器呢?看下面的 matchesSelector
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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); } matchesSelector(document.getElementById('myDiv'), 'div.someSelector[some-attribute=true]');
|
深入阅读
生成随机数 random
在 min
和 max
之间生成一个随机数,如果 integer
为 true
那么将生成随机整数。
1 2 3 4 5 6
| function rand(min, max, integer) { var r = Math.random() * (max - min) + min; return integer ? r|0 : r; } console.log(rand(2,5)); console.log(rand(1,100,true));
|