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 !
  • 相关阅读:
    完全背包
    01背包
    游戏编程:为什么C++游戏开发比Java更好,其实是因为这两个点!
    VS code搭建 C 和 C++ 环境的完整图文教程!赶紧收藏,这波不亏!
    来自清华计算机系的招聘信息,第一个要求就劝退99%的人!网友:但福利待遇真好!
    C++ 必看书籍清单!从C++ Primer 到 源码剖析,精通真的很难!
    C语言简单编程速成!保姆级入门教程, 目标达成!
    9 名程序员被抓!这次是真的活该.....
    你知道各类开发语言的薪酬差距吗?高薪在于适合,而不在于广度!
    apache common包 CollectionUtils 使用 详解
  • 原文地址:https://www.cnblogs.com/hghrpg/p/4594035.html
Copyright © 2011-2022 走看看