10.1 箭头函数
    vECMAScript 6新增了使用胖箭头(=>)语法 定义函数表达式的能力。
    很大程度上,箭头函数实例化的函数对象,与正式的函数表达式创建的函数对象行为,是相同的。
    任何可以使用函数表达式的地方,都可以使用箭头函数
    箭头函数简洁的语法非常适合嵌入函数的场景

    1. let ints = [1,2,3];
    2. console.log(ints.map(function(i) {return i+1})); //[2,3,4]
    3. console.log(ints.map((i) => {return i})) // [1,2,3]

    如果只有一个参数,可以不用括号。只有没有参数,或者多个参数的情况下,才需要使用括号
    箭头函数也可以不用大括号,但这样会改变函数的行为。使用大括号就说明包含“函数体”,可以在一个函数中包含多条语句,跟常规的函数一样。
    如果不使用大括号,那么箭头后面就只能有一行代码,比如一个赋值操作,或者一个表达式。
    而且,省略大括号会隐式返回这行代码的值:

    1. // 以下这两种写法都有效,而且返回相应的值
    2. let double = (x) => { return 2 * x };
    3. let triple = (x) => 3 * x ;
    4. // 可以赋值
    5. let value = {};
    6. let setName = (x) => x.name = 'Jack';
    7. setName(value);
    8. // 无效写法
    9. let multiply = (a,b) => return a * b;
    10. // Uncaught SyntaxError: Unexpected token 'return'

    缺点:
    箭头函数虽然语法简洁,但也有很多场合不适用。
    箭头函数不能使用arguments、super和new.target,也不能用作构造函数。
    此外,箭头函数也没有prototype属性。
    10.2 函数名
    因为函数名就是指向函数的指针,所以它们跟其他包含对象指针的变量具有相同的行为。这意味着一个函数可以有多个名称,如下所示:

    1. function sum (num1, num2) {
    2. return num1+num2;
    3. }
    4. console.log(sum(10,10)); // 20
    5. let anotherSum = sum;
    6. console.log(sum(10,10)); // 20
    7. sum = null;
    8. console.log(anotherSum(10,10)); // 20

    定义了一个名为sum()的函数,用于求两个数之和。
    然后又声明了一个变量anotherSum,并将它的值设置为等于sum。
    注意,使用不带括号的函数名会访问函数指针,而不会执行函数。
    此时,anotherSum和sum都指向同一个函数。
    调用anotherSum()也可以返回结果。
    把sum设置为null之后,就切断了它与函数之间的关联。
    而anotherSum()可以照常调用,没有问题。
    ECMAScript 6的所有函数对象都会暴露一个只读的name属性,其中包含关于函数的信息。
    多数情况下,这个属性中保存的就是一个函数标识符,或者说是一个字符串化的变量名。
    即使函数没有名称,也会如实显示成空字符串。
    如果它是使用Function构造函数创建的,则会标识成”anonymous”:

    1. function foo() {};
    2. let bar = function() {};
    3. let baz = () => {};
    4. console.log(foo.name); // foo
    5. console.log(bar.name); // bar
    6. console.log(baz.name); // baz
    7. console.log((() => {}).name); // 空
    8. console.log((new Function()).name); // anonymous

    如果函数是一个获取函数、设置函数,或者使用bind()实例化,那么标识符前面会加上一个前缀
    10.3 理解参数
    ECMAScript函数既不关心传入的参数个数,和数据类型。
    定义函数时要接收两个参数,并不意味着调用时就传两个参数,解释器不会报错。
    原因:
    ECMAScript函数的参数在内部表现为一个数组。函数被调用时总会接收一个数组,并不关心这个数组中包含什么。
    如果数组中什么也没有,或数组的元素超出了要求,都没问题。
    事实上,在使用function关键字定义(非箭头)函数时,可以在函数内部访问arguments对象,从中取得传进来的每个参数值。
    arguments对象是一个类数组对象(但不是Array的实例),因此可以使用中括号语法访问其中的元素(第一个参数是arguments[0],第二个参数是arguments[1])。
    要确定传进来多少个参数,可以访问arguments.length属性。
    arguments对象,它的值始终会与对应的命名参数同步。
    但这并不意味着它们都访问同一个内存地址,它们在内存中还是分开的,只不过会保持同步而已。
    并且:如果只传了一个参数,然后把arguments[1]设置为某个值,那么这个值并不会反映到第二个命名参数。这是因为:arguments对象的长度是根据传入的参数个数,而非定义函数时给出的命名参数个数确定的。
    对于命名参数而言,如果调用函数时没有传这个参数,那么它的值就是undefined。这就类似于定义了变量而没有初始化。
    严格模式下,arguments会有一些变化。首先,像前面那样给arguments[1]赋值不会再影响num2的值。就算把arguments[1]设置为10, num2的值仍然还是传入的值。其次,在函数中尝试重写arguments对象会导致语法错误。(代码也不会执行。)
    箭头函数中的参数
    如果函数是使用箭头语法定义的,那么传给函数的参数将不能使用arguments关键字访问,而只能通过定义的命名参数访问。

    1. function foo() {
    2. console.log(arguments[0]);
    3. }
    4. foo(5); // 5
    5. let bar = () => {
    6. console.log(arguments[0]);
    7. };
    8. bar(5); // Uncaught ReferenceError: arguments is not defined at bar

    注:ECMAScript中的所有参数都按值传递的。不可能按引用传递参数。如果把对象作为参数传递,那么传递的值是这个对象的引用。
    10.4 没有重载
    ECMAScript函数不能像传统编程那样重载。
    ECMAScript函数没有签名,因为参数是由包含零个或多个值的数组表示的。没有函数签名,自然也就没有重载。
    如果在ECMAScript中定义了两个同名函数,则后定义的会覆盖先定义的
    把函数名当成指针也有助于理解为什么ECMAScript没有函数重载。定义两个同名的函数,显然会导致,后定义的重写先定义的。