函数的扩展
-
箭头函数和普通函数区别
- 箭头函数没有this对象,箭头函数的里的this始终指向定义时所在对象,普通函数指向使用时所在对象
- 箭头函数没有this,没有constructor,不可以当做构造函数,不能使用new命令
- 箭头函数没有this,所以bind,apply,call等改变this指向的函数第一个参数无效
- 箭头函数没有arguments对象,可以通过rest参数来代替
- 箭头函数没有原型prototype
- 不可以使用yield命令
- Generator函数是在function关键字定义函数时进行拓展的,而没有做箭头函数的处理,所以箭头函数不能用作Generator函数
函数的length属性是去除rest和设置默认值之后的参数个数
-
函数的name属性
- 具名函数指向声明时的名字
- 匿名函数指向首次赋给的变量的名字
(new Function).name === 'anonymous'
func.bind({}).name === 'bound func'
-
双冒号运算符相当于bind,
-
foo::bar
等同bar.bind(foo)
-
foo::bar(a,b)
等同bar.call(foo,a,b)
-
::foo.bar
等同foo.bar.bind(foo)
-
tips
- 函数作用域
//TODO //函数参数和函数体作用域关系 function foo1(x, y = function() { x = 2; }) { var x = 3; y(); console.log(x); } function foo2(x, y = function() { x = 2; }) { let x = 3; y(); console.log(x); } function foo3(x, y = function() { x = 2; }) { x = 3; y(); console.log(x); } foo1() //3 foo2() //Error foo3() //2
- 函数内部的严格模式适用于函数体和函数参数,但是函数参数声明先于函数体执行,所以对于默认值、解构赋值、扩展运算符,会先执行再校验是否符合严格模式,不合理,所以在使用默认值、解构赋值、扩展运算符的函数里不能指定严格模式
- 尾递归优化
/*尾递归优化函数,将递归转化为循环*/ var tco = fn=>{ let active let value let argsArr =[] return (...args)=>{ argsArr.push(args) if(!active){ active =true while(argsArr.length){ value = fn.apply(null,argsArr.shift()) } active =false return value } } } /*自然数求和尾递归*/ var sum = (n,total = 0)=>{ if(n){ return sum(n-1,total+n) }else{ return total } } /*优化后的尾递归*/ var sum = tco((n,total = 0)=>{ if(n){ return sum(n-1,total+n) }else{ return total } })