Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2015-7-16 7 个必不可少的 JavaScript 函数 (渣译) #38

Open
hjzheng opened this issue Jul 16, 2015 · 0 comments
Open

2015-7-16 7 个必不可少的 JavaScript 函数 (渣译) #38

hjzheng opened this issue Jul 16, 2015 · 0 comments

Comments

@hjzheng
Copy link
Owner

hjzheng commented Jul 16, 2015

7 个必不可少的 JavaScript 函数

原文地址:http://davidwalsh.name/essential-javascript-functions

我记得,早期的 JavaScript ,一个简单的功能,需要知道关于它的一切,因为不同的的浏览器厂商对特性(feature)的实现是不同的,不仅是边缘特性(feature),一些基本特性(feature)也是如此,比如 addEventListenerattachEvent。随着时间的改变,仍然有些函数是每个开发者必须放在他们的武器库里,因为它们具有更好的性能和功能。

debounce

Debounce 函数被称为变革者,当它带来性能提升时候。如果你不和 scroll, resize, key* 等事件一起使用 debounce 函数,那你可能做错了。这里的 debounce 函数会保持你代码的效率:

// Returns a function, 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 函数在每个给定的时间里不允许回调函数被调用超过一次。这是特别重要的,当你给频繁发生的事件注册一个回调函数时。

Poll

正如我提到的 debounce 函数(译者注:前面这句不明白)。有时,你不能接收表示期望状态的结果 -- 如果这个结果不存在,你需要在一段时间内检查你的期望状态:

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
    }
);

Polling 早已在 web 上使用,并将在未来继续发光发热!

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(); // undefined

Once 函数确保一个给定的函数仅被调用一次,因而,可以防止重复初始化!

getAbsoluteUrl

从一个字符串变量得到一个绝对路径的 URL 并不像你想的那么容易。有个 URl 构造函数但是如果你不能提供必要的参数的话(有时候,你确实不能提供参数),它不能正常工作。这里有一个取得绝对路径的奇淫巧计。

译者注: URL 构造函数 参考 MDN URL

var getAbsoluteUrl = (function() {
    var a;

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

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

// Usage
getAbsoluteUrl('/something'); // http://davidwalsh.name/something

isNative

如果你想覆盖一个给定的函数,需要知道它是否原生的,下面的代码可以给你答案:

;(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

这个函数不是很漂亮,但是它能够完成任务!

insertRule

我们都知道我们可以通过一个选择器抓取 NodeList (通过 document.querySelectorAll ) 并为它们添加样式,但是更高效的方式是对选择器直接设置样式:

var sheet = (function() {
    // Create the <style> tag
    var style = document.createElement('style');

    // Add a media (and/or media query) here if you'd like!
    // style.setAttribute('media', 'screen')
    // style.setAttribute('media', 'only screen and (max-width : 1024px)')

    // WebKit hack :(
    style.appendChild(document.createTextNode(''));

    // Add the <style> element to the page
    document.head.appendChild(style);

    return style.sheet;
})();

// Usage
sheet.insertRule("header { float: left; opacity: 0.8; }", 1);

这个函数特别有用,当你工作在一个动态的,重度使用AJAX的网站时。如果你对一个选择器直接设置样式,你就不必为每个匹配该选择器的元素设置样式。

matchesSelector

通常情况下,在进行下一步之前,我们需要验证输入;确保是一个真值,确保表单数据有效。但是我们是否经常确定一个元素合格再进行下一步?你可以使用 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函数放入他们的工具箱中。如果我漏掉一个函数?请分享它!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant