撩一下一些必要的js工具函数

asule216 8年前
   <p>不管是什么项目,总有一些基本的功能函数默默的躺在你的工具库中,为你遮挡bug,提升性能,一起来复习下!</p>    <h2>debounce</h2>    <p>当监听一些scroll,resize事件时,如果我们什么都不限制,srcoll事件在滚动过程中会一直触发,极大的影响性能,这个时候,就需要节流函数debounce。debounce函数返回一个函数,在给定的时间间隔下,连续被调用将不会触发。</p>    <pre>  <code class="language-javascript">/* 事件停止被触发N秒后才会再次触发回调 * @param {Function} func - 回调执行函数 * @param {String} wait - 触发间隔 * @param {Boolean} 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);      };  };    // Usage  var myEfficientFn = debounce(function() {      // todo  }, 250);  window.addEventListener('resize', myEfficientFn);  </code></pre>    <h2>poll</h2>    <p>很多时候,我们需要了解某个函数的执行状态,并根据状态执行相应的处理。在没有事件通知时,需要以一定的时间间隔轮询执行状态。</p>    <pre>  <code class="language-javascript">/* 轮询条件函数,根据状态执行相应回调 * @param {Function} fn- 条件函数 * @param {Function} callback - 成功回调 * @param {Function} errback - 失败回调 * @param {int} timeout - 超时间隔 * @param {int} interval - 轮询间隔 */  function poll(fn, callback, errback, timeout, interval) {      var endTime = Number(new Date()) + (timeout || 2000);      interval = interval || 100;        (function p() {              // If the condition is met, we're done!               if(fn()) {                  callback();              }              // If the condition isn't met but the timeout hasn't elapsed, go again              else if (Number(new Date()) < endTime) {                  setTimeout(p, interval);              }              // Didn't match and too much time, reject!              else {                  errback(new Error('timed out for ' + fn + ': ' + arguments));              }      })();  }    // Usage: ensure element is visible  poll(      function() {          return document.getElementById('lightbox').offsetWidth > 0;      },      function() {          // Done, success callback      },      function() {          // Error, failure callback      }  );  </code></pre>    <h2>once</h2>    <p>实用的执行一次函数,不用多解释。虽然很简单的函数,但是防止重复加载或者初始化的习惯必须养成。</p>    <pre>  <code class="language-javascript">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!');  });  </code></pre>    <h2>getAbsoluteUrl</h2>    <p>从字符串变量中获取绝对url路径并没有那么容易,URL构造函数必须提供必要的参数,getAbsoluteUrl函数可以单纯的从字符串输入中得到绝对路径。</p>    <pre>  <code class="language-javascript">var getAbsoluteUrl = (function() {      var a;        return function(url) {          if(!a) a = document.createElement('a');          a.href = url;            return a.href;      };  })();    // Usage  getAbsoluteUrl('/shirlyzhang');  // "http://imweb.io/shirlyzhang"  </code></pre>    <h2>isNative</h2>    <p>当需要重写某个函数时,必须先确定其是否是原生函数。</p>    <pre>  <code class="language-javascript">(function() {    var toString = Object.prototype.toString;    var fnToString = Function.prototype.toString;    // 构造函数,数组    var reHostCtor = /^\[object .+?Constructor\]$/;      var reNative = RegExp('^' +      // 强制转换(Object-toString)为字符串      String(toString)      // 转移特殊字符      .replace(/[.*+?^${}()|[\]\/\\]/g, '\\$&')      // 替换 `toString` 为 `.*?`, 保持模板通用      // 替换 `for ...` 等字符来支持添加了额外信息的环境      .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'    );      function isNative(value) {      var type = typeof value;      return type == 'function'        // 使用 `Function#toString` 来绕过value原生的 `toString` 方法,避免误判        ? reNative.test(fnToString.call(value))        // 回退到宿主对象检查。因为某些环境中,会将类型数组当做DOM方法。        : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false;    }      module.exports = isNative;  }());    // Usage  isNative(alert); // true  isNative(myCustomFunction); // false  </code></pre>    <h2>insertRule</h2>    <p>使用css选择器来选取节点修改样式不太高效,可以选择用js新建一段css样式规则插入。</p>    <pre>  <code class="language-javascript">var sheet = (function() {      var style = document.createElement('style');        // WebKit 兼容      style.appendChild(document.createTextNode(''));        document.head.appendChild(style);      return style.sheet;  })();    // Usage  sheet.insertRule("header { float: left; opacity: 0.8; }", 1);  </code></pre>    <h2>matchesSelector</h2>    <p>判断页面内的元素是否具有某些属性值。</p>    <pre>  <code class="language-javascript">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]')  </code></pre>    <p>来自: <a href="/misc/goto?guid=4959669985671305949" rel="nofollow">http://imweb.io/topic/5704a23a06f2400432c1397f</a></p>