美文网首页
函数总结

函数总结

作者: 磁针石 | 来源:发表于2018-05-11 16:42 被阅读3次
    定义
    function abs(x)
    {
    //argument 所有参数的数组;rest是剩余参数数组
      ...
    }
    函数是一个对象,匿名函数赋值 `abs` 对象 可定义为:
    var abs = function(x)
    {
      ...
    };
    
    
    • JavaScript允许传入任意个参数而不影响调用,因此传入的参数比定义的参数多也没有问题。
    • ES6引入了新的关键字let,用let替代var可以申明一个块级作用域的变量。
    • 由于var和let申明的是变量,如果要申明一个常量,在ES6之前是不行的,我们通常用全部大写的变量来表示“这是一个常量,不要修改它的值”,ES6标准引入了新的关键字const来定义常量,constlet都具有块级作用域:
    'use strict';
    
    const PI = 3.14;
    PI = 3; // 某些浏览器不报错,但是无效果!
    PI; // 3.14
    
    • 从ES6开始,JavaScript引入了解构赋值,可以同时对一组变量进行赋值。对数组元素进行解构赋值时,多个变量要用 [...]括起来。

    var [x, y, z] = ['hello', 'JavaScript', 'ES6'];
    如果数组本身还有嵌套注意嵌套层次和位置要保持一致:let [x, [y, z]] = ['hello', ['JavaScript', 'ES6']];
    解构赋值还可以忽略某些元素:let [, , z] = ['hello', 'JavaScript', 'ES6']; // 忽略前两个元素,只对z赋值第三个元素
    如果需要从一个对象中取出若干属性,也可以使用解构赋值,便于快速获取对象的指定属性,变量名和属性名应保持一致,如果不一致,使用{属性名:变量名} = 对象

    var person = {
        name: '小明',
        age: 20,
        gender: 'male',
        passport: 'G-12345678',
        school: 'No.4 middle school'
    };
    
    // 把passport属性赋值给变量id:
    let {name, passport:id} = person;
    name; // '小明'
    id; // 'G-12345678'
    // 注意: passport不是变量,而是为了让变量id获得passport属性:
    passport; // Uncaught ReferenceError: passport is not defined
    // 如果person对象没有single属性,默认赋值为true:
    var {name, single=true} = person;
    
    交换变量值
    var x=1, y=2;
    [x, y] = [y, x]
    
    高阶函数可把函数作为一个参数,还可以把函数作为结果值返回
    • map map()方法定义在JavaScript的Array中,我们调用Array的map()方法,传入我们自己的函数,就得到了一个新的Array作为结果
    'use strict';
    
    function pow(x) {
        return x * x;
    }
    var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    var results = arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81]
    console.log(results);
    
    • reduce Array的reduce()把一个函数作用在这个Array的[x1, x2, x3...]上,这个函数必须接收两个参数,reduce()把结果继续和序列的下一个元素做累积计算,其效果就是:[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)
    • filter 和map()类似,Array的filter()也接收一个函数。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。把一个Array中的空字符串删掉,可以这么写:
    var arr = ['A', '', 'B', null, undefined, 'C', '  '];
    var r = arr.filter(function (s) {
        return s && s.trim(); // 注意:IE9以下的版本没有trim()方法
    });
    r; // ['A', 'B', 'C']
    数组去重
    r = arr.filter(function (element, index, self) {
        return self.indexOf(element) === index;
    });
    
    • sort JavaScript的Array的sort()方法就是用于排序的,字符串根据ASCII码进行排序
    • 闭包 定义在一个函数内部的函数,就是能够读取其他函数内部变量的函数。将函数内部和函数外部连接起来的桥梁。
    function sum(arr) {
        return arr.reduce(function (x, y) {
            return x + y;
        });
    }
    
    sum([1, 2, 3, 4, 5]); // 15
    
    但是,如果不需要立刻求和,而是在后面的代码中,根据需要再计算怎么办?可以不返回求和的结果,而是返回求和的函数!
    function lazy_sum(arr) {
        var sum = function () {
            return arr.reduce(function (x, y) {
                return x + y;
            });
        }
        return sum;
    }
    var f = lazy_sum([1, 2, 3, 4, 5]); // function sum()
    f(); //15调用函数f时,才真正计算求和的结果
    
    我们调用lazy_sum()时,每次调用都会返回一个新的函数,即使传入相同的参数
    var f1 = lazy_sum([1, 2, 3, 4, 5]);
    var f2 = lazy_sum([1, 2, 3, 4, 5]);
    f1 === f2; // false
    
    注意到返回的函数在其定义内部引用了局部变量arr,
    所以,当一个函数返回了一个函数后,其内部的局部变量还被新函数引用。
    返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
    function count() {
        var arr = [];
        for (var i=1; i<=3; i++) {
            arr.push(function () {
                return i * i;
            });
        }
        return arr;
    }
    
    var results = count();
    var f1 = results[0];
    var f2 = results[1];
    var f3 = results[2];
    f1(); // 16
    f2(); // 16
    f3(); // 16
    改进版:
    function count() {
        var arr = [];
        for (var i=1; i<=3; i++) {
            arr.push((function (n) {
                return function () {
                    return n * n;
                }
            })(i));
        }
        return arr;
    }
    
    var results = count();
    var f1 = results[0];
    var f2 = results[1];
    var f3 = results[2];
    
    f1(); // 1
    f2(); // 4
    f3(); // 9
    注意这里用了一个“创建一个匿名函数并立刻执行”的语法:
    (function (x) {
        return x * x;
    })(3); // 9
    Java和C++,要在对象内部封装一个私有变量,可以用private修饰一个成员变量。
    在没有class机制,只有函数的语言里,借助闭包,同样可以封装一个私有变量。我们用JavaScript创建一个计数器:
    function create_counter(initial) {
        var x = initial || 0;
        return {
            inc: function () {
                x += 1;
                return x;
            }
        }
    }
    var c1 = create_counter();
    c1.inc(); // 1
    c1.inc(); // 2
    c1.inc(); // 3
    
    • Arrow Function(箭头函数)相当于匿名函数,并且简化了函数定义:x => x * x相当于:function (x) { return x * x; }还有一种可以包含多条语句,这时候就不能省略{ ... }return,如果参数不是一个,就需要用括号()括起来:
    // 两个参数:
    (x, y) => x * x + y * y
    
    // 无参数:
    () => 3.14
    
    // 可变参数:
    (x, y, ...rest) => {
       var i, sum = x + y;
       for (i=0; i<rest.length; i++) {
           sum += rest[i];
       }
       return sum;
    }
    如果要返回一个对象`x => ({ foo: x })`
    箭头函数内部的this是词法作用域,由上下文确定。
    
    • generator 看上去像一个函数,但可以返回多次,generatorfunction*定义(注意多出的*号),并且,除了return语句,还可以用yield返回多次。
    function* fib(max) {
        var
            t,
            a = 0,
            b = 1,
            n = 0;
        while (n < max) {
            yield a;
            [a, b] = [b, a + b];
            n ++;
        }
        return;
    }
    var f = fib(5);
    f.next(); // {value: 0, done: false}
    f.next(); // {value: 1, done: false}
    f.next(); // {value: 1, done: false}
    f.next(); // {value: 2, done: false}
    f.next(); // {value: 3, done: false}
    f.next(); // {value: undefined, done: true}
    `fib(5)`仅仅是创建了一个`generator`对象,还没有去执行它
    调用generator对象有两个方法,一是不断地调用generator对象的next()方法,next()方法会执行generator的代码,
    每次遇到yield x;就返回一个对象{value: x, done: true/false},
    然后“暂停”。返回的value就是yield的返回值,done表示这个generator是否已经执行结束了.
    第二个方法是直接用for ... of循环迭代generator对象,这种方式不需要我们自己判断done:
    for (var x of fib(10)) {
        console.log(x); // 依次输出0, 1, 1, 2, 3, ...
    }
    
    

    相关文章

      网友评论

          本文标题:函数总结

          本文链接:https://www.haomeiwen.com/subject/osqfdftx.html