带参数默认值的函数
JS 函数的独特之处是可以接受任意数量的参数,而无视函数声明处的参数数量。
在 ES5 中模拟参数默认值
ES6 中的参数默认值
ES6 能更容易地为参数提供默认值,它使用了初始化形式,以便在参数未被正式传递进来时使用。

参数默认值如何影响 arguments 对象
在 ES5 的非严格模式下, arguments 对象会反映出具名参数的变化。即arguments 对象总是会被更新以反映出具名参数的变化。然而在 ES5 的严格模式下,关于 arguments 对象的这种混乱情况被消除了,它不再反映出具名参数的变化。
在使用 ES6 参数默认值的函数中, arguments 对象的表现总是会与 ES5 的严格模式一致,无论此时函数是否明确运行在严格模式下。
参数默认值表达式
默认值并不要求一定是基本类型的值。
参数默认值的暂时性死区
参数默认值同样有着无法访问特定参数的暂时性死区。与 let 声明相似,函数每个参数都会创建一个新的标识符绑定,它在初始化之前不允许被访问,否则会抛出错误。

使用不具名参数
ES5 中的不具名参数
JS 提供了 arguments 对象用于查看传递给函数的所有参数,这样就不必分别指定每个参数。
剩余参数
剩余参数( rest parameter )由三个点( ... )与一个紧跟着的具名参数指定,它会是包含传递给函数的其余参数的一个数组,名称中的“剩余”也由此而来。
剩余参数的限制条件
剩余参数受到两点限制: 一是函数只能有一个剩余参数,并且它必须被放在最后。第二个限制是剩余参数不能在对象字面量的 setter 属性中使用。对象字面量的 setter 被限定只能使用单个参数;而剩余参数按照定义是不限制参数数量的,因此它在此处不被许可。
剩余参数如何影响 arguments 对象
函数构造器的增强能力
ES6 增强了 Function 构造器的能力,允许使用默认参数以及剩余参数。对于默认参数来说,你只需为参数名称添加等于符号以及默认值。而对剩余参数来说,只需在最后一个参数前添加 ... 即可。
扩展运算符
与剩余参数关联最密切的就是扩展运算符。剩余参数允许你把多个独立的参数合并到一个数组中;而扩展运算符则允许将一个数组分割,并将各个项作为分离的参数传给函数。

ES6 的名称属性
ES6 给所有函数添加了 name 属性。
选择合适的名称
名称属性的特殊情况

明确函数的双重用途
JS 为函数提供了两个不同的内部方法: [[Call]] 与 [[Construct]] 。当函数未使用 new进行调用时, [[call]] 方法会被执行,运行的是代码中显示的函数体。而当函数使用 new进行调用时, [[Construct]] 方法则会被执行,负责创建一个被称为新目标的新的对象,并且使用该新目标作为 this 去执行函数体。拥有 [[Construct]] 方法的函数被称为构造器。
在 ES5 中判断函数如何被调用
在 ES5 中判断函数是不是使用了 new 来调用(即作为构造器),最流行的方式是使用instanceof。但如果调用call()就会失效。
new.target 元属性
元属性指的是“非对象”(例如 new )上的一个属性,并提供关联到它的目标的附加信息。当函数的 [[Construct]] 方法被调用时, new.target 会被填入 new 运算符的作用目标,该目标通常是新创建的对象实例的构造器,并且会成为函数体内部的 this 值。而若 [[Call]] 被执行, new.target 的值则会是undefined 。
块级函数
在严格模式下,ES6允许使用块级函数。
决定何时使用块级函数
块级函数与 let 函数表达式相似,在执行流跳出定义所在的代码块之后,函数定义就会被移除。关键区别在于:块级函数会被提升到所在代码块的顶部;而使用 let 的函数表达式则不会。
非严格模式的块级函数
ES6 在非严格模式下同样允许使用块级函数,但行为有细微不同。块级函数的作用域会被提升到所在函数或全局环境的顶部,而不是代码块的顶部。
箭头函数
箭头函数的行为在很多重要方面与传统的 JS 函数不同:
1、没有 this 、 super 、 arguments ,也没有 new.target 绑定: this 、 super 、arguments 、以及函数内部的 new.target 的值由所在的、最靠近的非箭头函数来决定。
2、不能被使用 new 调用: 箭头函数没有 [[Construct]] 方法,因此不能被用为构造函数,使用 new 调用箭头函数会抛出错误。
3、没有原型: 既然不能对箭头函数使用 new ,那么它也不需要原型,也就是没有prototype 属性。
4、不能更改 this : this 的值在函数内部不能被修改,在函数的整个生命周期内其值会保持不变。
5、没有 arguments 对象: 既然箭头函数没有 arguments 绑定,你必须依赖于具名参数或剩余参数来访问函数的参数。
6、不允许重复的具名参数: 箭头函数不允许拥有重复的具名参数,无论是否在严格模式下;而相对来说,传统函数只有在严格模式下才禁止这种重复。
箭头函数语法
以函数参数为开头,紧跟着的是箭头,再接下来则是函数体。


创建立即调用函数表达式( immediately-invoked function expression , IIFE )

没有 this 绑定
箭头函数没有 this 绑定,意味着箭头函数内部的 this 值只能通过查找作用域链来确定。如果箭头函数被包含在一个非箭头函数内,那么 this 值就会与该函数的相等;否则,this 值就会是全局对象(在浏览器中是 window ,在 nodejs 中是 global )。
箭头函数与数组
没有 arguments 绑定
箭头函数没有自己的 arguments 对象,但仍然能访问包含它的函数的 arguments 对象。
识别箭头函数:箭头函数依然属于函数,并能被照常识别。
尾调用优化
有何不同?
如何控制尾调用
网友评论