函数总结

定义
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 ({ 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, ...
}

你可能感兴趣的:(函数总结)