函数对象的属性
我们知道JavaScript中函数也是一个对象,那么对象中就可以有属性和方法。
属性name:一个函数的名词我们可以通过name来访问;
属性length:属性length用于返回函数参数的个数;
注意:rest参数是不参与参数的个数的;
认识arguments
arguments 是一个 对应于 传递给函数的参数 的 类数组(array-like)对象。
array-like意味着它不是一个数组类型,而是一个对象类型:
但是它却拥有数组的一些特性,比如说length,比如可以通过index索引来访问;
但是它却没有数组的一些方法,比如filter、map等;
1 2 3 4 5 6 function foo (m, n ) { console .log (arguments ) } foo (10 , 25 , 32 , 41 )
arguments 遍历和转换成数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function foo (m, n ) { console .log (arguments [0 ]) console .log (arguments [1 ]) for (var i = 0 ; i < arguments .length ; i++) { console .log (arguments [i]) } for (var arg of arguments ) { console .log (arg) } } foo (10 , 25 , 32 , 41 )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 function foo (m, n) { for (var arg of arguments ) { if (arg % 2 === 0 ) { console .log (arg) } } console .log ("----------" ) var newArguments = [] for (var arg of arguments ) { newArguments.push (arg) } console .log (newArguments) console .log ("----------" ) var newArgs1 = Array .from (arguments ) console .log (newArgs1) var newArgs2 = [...arguments ] console .log (newArgs2) console .log ("----------" ) var newArgs = [].slice .apply (arguments ) console .log (newArgs) } foo (10 , 25 , 32 , 41 )
箭头函数不绑定arguments 箭头函数是不绑定arguments的,所以我们在箭头函数中使用arguments会去上层作用域查找:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function foo () { var bar = ( ) => { console .log (arguments ) } bar () } foo (111 , 222 )
函数的剩余(rest)参数
ES6中引用了rest parameter,可以将不定数量的参数放入到一个数组中:
如果最后一个参数是 … 为前缀的,那么它会将剩余的参数放到该参数中,并且作为一个数组;
那么剩余参数和arguments有什么区别呢?
剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参;
arguments对象不是一个真正的数组,而rest参数是一个真正的数组,可以进行数组的所有操作;
arguments是早期的ECMAScript中为了方便去获取所有的参数提供的一个数据结构,而rest参数是ES6中提供并且希望以此 来替代arguments的;
剩余参数必须放到最后一个位置,否则会报错 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function foo (num1, num2, ...otherNums ) { console .log (otherNums) } foo (20 , 30 , 111 , 222 , 333 ) function bar (...args ) { console .log (args) } bar ("abc" , 123 , "cba" , 321 )
理解JavaScript纯函数
函数式编程中有一个非常重要的概念叫纯函数,JavaScript符合函数式编程的范式,所以也有纯函数的概念;
在react开发中纯函数是被多次提及的;
比如react中组件就被要求像是一个纯函数(为什么是像,因为还有class组件),redux中有一个reducer的概念,也是要求 必须是一个纯函数;
所以掌握纯函数对于理解很多框架的设计是非常有帮助的;
纯函数的简单总结:
确定的输入,一定会产生确定的输出;
函数在执行过程中,不能产生副作用;
纯函数的案例 slice
我们来看一个对数组操作的两个函数:
slice:slice截取数组时不会对原数组进行任何操作,而是生成一个新的数组;
splice:splice截取数组, 会返回一个新的数组, 也会对原数组进行修改;
slice就是一个纯函数,不会修改数组本身,而splice函数不是一个纯函数;
柯里化 只传递给函数一部分参数来调用它,让它返回一个函数去处理剩余的参数;这个过程就称之为柯里化;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 function foo1 (x, y, z ) { console .log (x + y + z) } function foo2 (x ) { return function (y ) { return function (z ) { console .log (x + y + z) } } } foo2 (10 )(20 )(30 ) foo2 (20 )(33 )(55 ) var foo3 = x => y => z => { console .log (x + y + z) } foo3 (10 )(20 )(30 )
组合函数
组合(Compose)函数是在JavaScript开发过程中一种对函数的使用技巧、模式:
比如我们现在需要对某一个数据进行函数的调用,执行两个函数fn1和fn2,这两个函数是依次执行的;
那么如果每次我们都需要进行两个函数的调用,操作上就会显得重复;
那么是否可以将这两个函数组合起来,自动依次调用呢?
这个过程就是对函数的组合,我们称之为 组合函数;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 function double (num ) { return num * 2 } function pow (num ) { return num ** 2 } function composeFn (...fns ) { var length = fns.length if (length <= 0 ) return for (var i = 0 ; i < length; i++) { var fn = fns[i] if (typeof fn !== "function" ) { throw new Error (`index position ${i} must be function` ) } } return function (...args ) { var result = fns[0 ].apply (this , args) for (var i = 1 ; i < length; i++) { var fn = fns[i] result = fn.apply (this , [result]) } return result } } var newFn = composeFn (double, pow, console .log ) newFn (100 ) newFn (55 ) newFn (22 )
eval函数