高階函式簡述 js

weixin_33816946發表於2018-10-18

1、簡述

高階函式似乎是一種先進程式設計的的技術。然而,並不是。

高階函式其實就是將函式作為引數或者返回值的函式。其中作為引數的函式一般是回撥函式。

 

2、例子

(1)最簡單的例子

大家都熟悉陣列的sort方法。

<!DOCTYPE html>
<html lang="zh">

    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>高階函式</title>
    </head>

    <body>
        <script type="text/javascript">
            let arr = [1,2,4,3];
            arr.sort((a,b)=>{return a-b})
            console.log(arr)
        </script>
    </body>

</html>

sort方法的引數就是一個函式(回撥函式),這個回撥函式決定了如何比較陣列中的任意兩個元素。

Array的sort方法原始碼實現(使用了插入排序和快速排序):

 

            function ArraySort(comparefn) {
                // 使用款速排序演算法
                // 對於長度小於22的陣列,使用插入排序演算法
                
                //判斷comparefn是不是一個函式
                var custom_compare = IS_FUNCTION(comparefn);

                function Compare(x, y) {
                    // 假設comparefn(若存在的話)是一致的比較函式。
                    // 如果不是,則假設假設comparefn函式是任意的(通過ECMA 15.4.4.11)
                    if(x === y) return 0;
                    if(custom_compare) {
                        // 不要直接呼叫comparefn以避免暴露內建的全域性物件。.
                        return comparefn.call(null, x, y);
                    }
                    x = ToString(x);
                    y = ToString(y);
                    if(x == y) return 0;
                    else return x < y ? -1 : 1;
                };
                
                //插入排序
                function InsertionSort(a, from, to) {
                    for(var i = from + 1; i < to; i++) {
                        var element = a[i];
                        // Pre-convert the element to a string for comparison if we know
                        // it will happen on each compare anyway.
                        var key =
                            (custom_compare || % _IsSmi(element)) ? element : ToString(element);
                        // place element in a[from..i[
                        // binary search
                        var min = from;
                        var max = i;
                        // The search interval is a[min..max[
                        while(min < max) {
                            var mid = min + ((max - min) >> 1);
                            var order = Compare(a[mid], key);
                            if(order == 0) {
                                min = max = mid;
                                break;
                            }
                            if(order < 0) {
                                min = mid + 1;
                            } else {
                                max = mid;
                            }
                        }
                        // place element at position min==max.
                        for(var j = i; j > min; j--) {
                            a[j] = a[j - 1];
                        }
                        a[min] = element;
                    }
                }
                
                //快速排序
                function QuickSort(a, from, to) {
                    // 若陣列長度小於22的話,使用插入排序。
                    if(to - from <= 22) {
                        InsertionSort(a, from, to);
                        return;
                    }
                    var pivot_index = $floor($random() * (to - from)) + from;
                    var pivot = a[pivot_index];
                    // Pre-convert the element to a string for comparison if we know
                    // it will happen on each compare anyway.
                    var pivot_key =
                        (custom_compare || % _IsSmi(pivot)) ? pivot : ToString(pivot);
                    // Issue 95: Keep the pivot element out of the comparisons to avoid
                    // infinite recursion if comparefn(pivot, pivot) != 0.
                    a[pivot_index] = a[from];
                    a[from] = pivot;
                    var low_end = from; // Upper bound of the elements lower than pivot.
                    var high_start = to; // Lower bound of the elements greater than pivot.
                    // From low_end to i are elements equal to pivot.
                    // From i to high_start are elements that haven't been compared yet.
                    for(var i = from + 1; i < high_start;) {
                        var element = a[i];
                        var order = Compare(element, pivot_key);
                        if(order < 0) {
                            a[i] = a[low_end];
                            a[low_end] = element;
                            i++;
                            low_end++;
                        } else if(order > 0) {
                            high_start--;
                            a[i] = a[high_start];
                            a[high_start] = element;
                        } else { // order == 0
                            i++;
                        }
                    }
                    QuickSort(a, from, low_end);
                    QuickSort(a, high_start, to);
                }

                var old_length = ToUint32(this.length);
                if(old_length < 2) return this;

                %
                RemoveArrayHoles(this);

                var length = ToUint32(this.length);

                // 將未定義的元素移動到陣列的末尾.
                for(var i = 0; i < length;) {
                    if(IS_UNDEFINED(this[i])) {
                        length--;
                        this[i] = this[length];
                        this[length] = void 0;
                    } else {
                        i++;
                    }
                }

                QuickSort(this, 0, length);

                //如果this是一個陣列,我們只改變了這個陣列的長度。 如果this不是陣列,則不允許設定此物件的長度,因為這可能會引入新的length屬性。
                if(IS_ARRAY(this)) {
                    this.length = old_length;
                }

                return this;
            }

 

 

 

(2)字元換大寫

實現一:

<!DOCTYPE html>
<html lang="zh">

    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>高階函式</title>
    </head>

    <body>
        <script type="text/javascript">
            let arr = ['abc', 'def'],
                arrNew = [];
            for(let i = 0; i < arr.length; i++) {
                arrNew[i] = arr[i].toUpperCase()
            }
            console.log(arrNew)
        </script>
    </body>

</html>

實現二:

<!DOCTYPE html>
<html lang="zh">

    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>高階函式</title>
    </head>

    <body>
        <script type="text/javascript">
            let arr = ['abc', 'def'],
                arrNew = [];
            arrNew = arr.map(val => {
                return val.toUpperCase()
            })
            console.log(arrNew)
        </script>
    </body>

</html>

(3)高階函式實現

若程式碼中出現重複或者類似的程式碼,就可以使用高階函式。如產生一個包含數字的字串:

<!DOCTYPE html>
<html lang="zh">

    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>高階函式</title>
    </head>

    <body>
        <script type="text/javascript">
            let digits = ''
            for (let i=0;i<10;i++) {
                digits += i
            }
            console.log(digits)
        </script>
    </body>

</html>

使用高階函式實現:

<!DOCTYPE html>
<html lang="zh">

    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>高階函式</title>
    </head>

    <body>
        <script type="text/javascript">
            let digits = ''
            function buildString(n, callback) {
                let val = '';
                for(let i = 0; i < n; i++) {
                    val += callback(i)
                }
                return val
            }
            digits = buildString(10, i => {
                return i
            })
            console.log(digits)
        </script>
    </body>

</html>

 

相關文章