带参数默认值的函数

函数的参数数量不受声明时指定的参数个数影响,可以有任意多个。

函数声明时使用参数默认值直接在形参后面添加 '= defaultValue' 即可。可以给任意位置的参数添加默认值,只有当没有给这个位置的参数传值或者传的值为 undefined 时该参数使用默认值。

在使用参数默认值时,该位置的值不会存储在 arguments 对象中,同时 arguments 对象只存储调用函数时传递的值,当在函数内部改变参数的值时,arguments 对象中的值不变,依然是传递给函数的值。

参数默认值可以是字面量、变量、表达式或者返回值的函数。当调用函数且没有传值给具有默认值的参数时,此时对应参数使用默认值。默认值为有返回值的函数时,仅当需要默认值时,才会调用该函数产生值。也可以将函数前面的参数作为后面参数的默认值,反之不行。原因是当调用函数时,函数参数是按照声明顺序进行初始化的,如果用后面的参数作为前面参数的默认值,前面的参数使用默认值初始化时,后面的参数还没有值,无法初始化。

不具名参数

剩余参数由 '...' 紧跟一个参数名表示,这个参数接收由剩余参数组成的数组。剩余参数必须位于函数声明中最后一个参数位置上,且只能有一个。另外,剩余参数不能在对象字面量的 setter 属性中使用。

arguments 对象存储调用函数时传递给函数的所有参数。

函数构造器

函数构造器 Function 创建并返回一个函数,传递给构造器的参数都是字符串,其中除了最后一个参数都是创建的新函数的参数,最后一个参数是新函数的执行语句。可以在函数构造器中使用默认参数值和剩余参数,用法与前述一致。为参数添加等于号和默认值,在函数的最后一个参数前面添加三个点。

扩展运算符

扩展运算符 '...' 放在数组名前面使用时会拆解该数组,数组的每个元素作为一个参数,需要将数组中的元素作为参数传递给函数时使用。

名称属性

所有函数都有一个 name 属性存储函数的名称。即使是匿名函数,也保存了引用该函数的变量名称。

一个变量引用一个具名函数时,变量的 name 属性存储的是函数声明时的名称。getter 和 setter 函数的 name 属性存储的名称为 'get [funName]' 和 'set [funName]'; bind() 方法创建的函数 name 属性为 'bound [funName]';使用 Function 创建的函数 name 属性为 'anonymous [funName]'。

name 属性主要用于调试。

函数的双重用途

函数有两个内部方法 [[Call]] 和 [[Construct]]。没有使用 new 调用函数时,执行 [[call]] 方法,执行的是函数体;使用 new 调用函数时,执行 [[Construct]] 方法,此时创建一个新对象并将该对象赋值给 this 去执行函数体。具有 [[Construct]] 方法的函数称为构造器。

元属性是指对象实例不具有的属性。当 [[Construct]] 方法被调用时,new.target 元属性存放 new 操作符作用的目标,一般为构造对象的构造器。当 [[Call]] 方法被调用时,new.target 的值为 undefined。通过判断 new.target 的值可以确定函数是否使用了 new 调用。只能在函数内部使用 new.target。

块级函数

严格模式下,在某个代码块内部任意位置定义一个函数,允许使用这个函数的范围为从这个代码块的起始位置直到代码块结束。

非严格模式下,在某个代码块内部任意位置定义一个函数,允许访问这个函数的范围要么是某个函数的作用域要么是全局作用域。

箭头函数

箭头函数的箭头左边可以没有参数、有一个参数、多个参数,此时用小括号、单个参数、用小括号括起来的逗号分隔的多个参数表示。箭头右边可以为空、一个表达式、多条语句,此时用空大括号、一个表达式、普通函数的函数体表示。若只有一个表达式,则箭头函数返回该表达式的值。如果箭头函数使用一个表达式返回一个对象字面量,则该对象字面量需要使用小括号括起来。

立即调用箭头函数的表达式为:'(() => {})();'。

箭头函数中的 this 根据作用域链查找确定,要么指某个对象要么指全局对象。不能使用 new 调用箭头函数,有 name 属性,this 值不能变更。

箭头函数没有自己的 arguments 对象,但是可以访问包含自身的函数的 arguments 对象。

尾调用优化

尾调用指在一个函数中最后一条语句调用了另一个函数。一般情况下需要新增一个栈帧来保存新函数的变量。在严格模式下,满足如下条件时,尾调用优化会清除当前函数使用的栈帧重复利用该空间。

  • 尾调用不能引用当前栈帧中的变量。
  • 进行尾调用的函数在尾调用返回结果后不能做额外操作。
  • 尾调用的结果作为当前函数的结果返回。

参考

[1] Zakas, Understanding ECMAScript 6, 2017.

 posted on 2024-04-28 20:04  x-yun  阅读(4)  评论(0编辑  收藏  举报