zoukankan      html  css  js  c++  java
  • 第19条:熟练掌握高阶函数

    Higher-order functions used to be a shibboleth of the monks of func-
    tional programming, an esoteric term for what seemed like an
    advanced programming technique. Nothing could be further from the
    truth. Exploiting the concise elegance of functions can often lead to
    simpler and more succinct code. Over the years, scripting languages
    have adopted these techniques and in the process taken much of the
    mystery out of some of the best idioms of functional programming.
    Higher-order functions are nothing more than functions that take
    other functions as arguments or return functions as their result.
    Taking a function as an argument (often referred to as a callback
    function because it is “called back” by the higher-order function) is a
    particularly powerful and expressive idiom, and one that JavaScript
    programs use heavily.
    Consider the standard sort method on arrays. In order to work on all
    possible arrays, the sort method relies on the caller to determine how
    to compare any two elements in an array:

    function compareNumbers(x, y) {
    if (x < y) {
    return -1;
    }
    if (x > y) {
    return 1;
    }
    return 0;
    }
    [3, 1, 4, 1, 5, 9].sort(compareNumbers); // [1, 1, 3, 4, 5, 9]

    The standard library could have required the caller to pass in an
    object with a compare method, but since only one method is required,
    taking a function directly is simpler and more concise. In fact, the
    above example can be simplified further with an anonymous function:

    [3, 1, 4, 1, 5, 9].sort(function(x, y) {
    if (x < y) {
    return -1;
    }
    if (x > y) {
    return 1;
    }
    return 0;
    }); // [1, 1, 3, 4, 5, 9]

    Learning to use higher-order functions can often simplify your code
    and eliminate tedious boilerplate. Many common operations on
    arrays have lovely higher-order abstractions that are worth familiar-
    izing yourself with. Consider the simple act of transforming an array
    of strings. With a loop, we’d write:

    var names = ["Fred", "Wilma", "Pebbles"];
    var upper = [];
    for (var i = 0, n = names.length; i < n; i++) {
    upper[i] = names[i].toUpperCase();
    }
    upper; // ["FRED", "WILMA", "PEBBLES"]

    With the handy map method of arrays (introduced in ES5), we
    can completely eliminate the loop details, implementing just the
    element-by-element transformation with a local function:

    var names = ["Fred", "Wilma", "Pebbles"];
    var upper = names.map(function(name) {
    return name.toUpperCase();
    });
    upper; // ["FRED", "WILMA", "PEBBLES"]

    Once you get the hang of using higher-order functions, you can
    start identifying opportunities to write your own. The telltale sign
    of a higher-order abstraction waiting to happen is duplicate or sim-
    ilar code. For example, imagine we found one part of a program con-
    structing a string with the letters of the alphabet:

    var aIndex = "a".charCodeAt(0); // 97
    var alphabet = "";
    for (var i = 0; i < 26; i++) {
    alphabet += String.fromCharCode(aIndex + i);
    }
    alphabet; // "abcdefghijklmnopqrstuvwxyz"

    Meanwhile, another part of the program generates a string contain-
    ing numeric digits:

    var digits = "";
    for (var i = 0; i < 10; i++) {
    digits += i;
    }
    digits; // "0123456789"

    Still elsewhere, the program creates a random string of characters:

    var random = "";
    for (var i = 0; i < 8; i++) {
    random += String.fromCharCode(Math.floor(Math.random() * 26)
    + aIndex);
    }
    random; // "bdwvfrtp" (different result each time)

    Each example creates a different string, but they all share common
    logic. Each loop creates a string by concatenating the results of some
    computation to create each individual segment. We can extract the
    common parts and move them into a single utility function:

    function buildString(n, callback) {
    var result = "";
    for (var i = 0; i < n; i++) {
    result += callback(i);
    }
    return result;
    }

    Notice how the implementation of buildString contains all the com-
    mon parts of each loop, but uses a parameter in place of the parts
    that vary: The number of loop iterations becomes the variable n ,
    and the construction of each string segment becomes a call to the
    callback function. We can now simplify each of the three examples to
    use buildString :

    var alphabet = buildString(26, function(i) {
    return String.fromCharCode(aIndex + i);
    });
    alphabet; // "abcdefghijklmnopqrstuvwxyz"
    var digits = buildString(10, function(i) { return i; });
    digits; // "0123456789"
    var random = buildString(8, function() {
    return String.fromCharCode(Math.floor(Math.random() * 26)
    + aIndex);
    });
    random; // "ltvisfjr" (different result each time)

    There are many benefits to creating higher-order abstractions. If
    there are tricky parts of the implementation, such as getting the loop
    boundary conditions right, they are localized to the implementation
    of the higher-order function. This allows you to fix any bugs in the
    logic just once, instead of having to hunt for every instance of the cod-
    ing pattern spread throughout your program. If you find you need to
    optimize the efficiency of the operation, you again only have one place
    where you need to change anything. Finally, giving a clear name such
    as buildString to the abstraction makes it clearer to someone reading
    the code what the code does, without having to decode the details of
    the implementation.
    Learning to reach for a higher-order function when you find your-
    self repeatedly writing the same patterns leads to more concise code,
    higher productivity, and improved readability. Keeping an eye out for
    common patterns and moving them into higher-order utility func-
    tions is an important habit to develop.
    Things to Remember
    ✦ Higher-order functions are functions that take other functions as
    arguments or return functions as their result.
    ✦ Familiarize yourself with higher-order functions in existing
    libraries.
    ✦ Learn to detect common coding patterns that can be replaced by
    higher-order functions.

     文章来源于:Effective+Javascript编写高质量JavaScript代码的68个有效方法 英文版

    progress every day !
  • 相关阅读:
    笔记-1、线程基础、线程之间的共享和协作
    token的作用及实现原理
    mybatis+oracle如何批量执行多条update
    java程序员应该熟悉的20个有用的库(转)
    js-textarea文本换行符处理,Java后端以及js前端如何处理
    Spket,eclipse下安装Spket插件,格式化js
    关于equals变量 放在前后的问题
    @Autowired和@Qualifier共用出现提示信息Cannot find bean with qualifier XXXXX
    DOM树简单理解学习
    web.xml 中的listener、 filter、servlet 加载顺序及其详解
  • 原文地址:https://www.cnblogs.com/hghrpg/p/4594035.html
Copyright © 2011-2022 走看看