1、函数可以有默认值,默认值的参数排在参数列表的后面
function Point(x = 0 , y = 0) {
this . x = x;
this . y = y ;
}
2、函数默认值和解构赋值的默认值结合使用
function foo({x , y = 5)) {
console . log(x , y);
}
foo ( {}) // undefined, 5
foo ( {x: 1 } ) // 1, s
foo ({x: 1, y: 2 }) // 1, 2
foo() // TypeError: Cannot read property ’ x ’ of undefined
function fetch(url, { body = ”, method = ’ GET ’, headers = {} } ) {
console . log(method);
}
fetch ( ’ http://example.com ’ ,{})
//”GET ”
fetch ( ’ http://example . com ’ )
//报错
3、函数双重默认值:
function fetch(url, { method = ’ GET ’ }={}){
console.log(method) ;
}
fetch ( ’ http://example . com ’ )
// ” GET ”
// 写法-
function ml ( { x = 0 , y = 0} = { } ) {
return [x , y];
}
// 写法二
function m2 ( {x , y} = { χ : O, y : 0 } ) {
return [x, y];
}
上面两种写法都对函数的参数设定了默认值,区别在于,写法一中函数参数的默认值是空
对象,但是设置了对象解构赋值的默认值;写法二中函数参数的默认值是一个有具体属性的函
数,但是没有设置对象解构赋值的默认值。
//函数没有参数的情况
ml ( ) //[ o, o ]
m2 ( ) // [ o , o ]
II x 和y 都有值的情况
ml ( { x: 3, y: 8 l) // [ 3 , 8 ]
m2 ( { x : 3 , y : a } ) // [ 3 , 8 ]
II x 有位, y 元值的情况
ml ( { x: 3 l) // [ 3 , 0 ]
m2({x : 3)) // [3, undefined]
II x 和y 都元,值的情况
ml ( { } ) // [ 0, 0 ] ;
m2({}) // [undefined, undefined]
ml ( { z: 3}) // [ 0, 0 ]
m2 ( { z: 3}) // [undefined, undefined]
4、如果没有默认值参数,那么函数属性length表示函数的参数个数。如果有了默认值参数,那么length的结果会失真,不确定,一般为没有默认值参数的个数。
(fun ct ion (a) {}) . length // 1
(funct i on (a= 5) {} ).length // 0
(function (a , b , c = 5) {}).length // 2
5、拥有默认值的参数,会在函数初始化的时候形成单独的作用域,当函数初始化完成之后作用域就会消失;
6、参数默认值指定参数不可省略,否则抛出一个错误
function throwifMissing() {
throw new Error (’ Missing parameter ’ ) ;
}
functi 。n foo (mustBeProvided = throwifMissing () ) {
return mustBeProvided;
}
foo ()
// Error: Missing parameter
如果调用的时候没有参数,以上代码中的foo 函数就会调用默认值throwifMissing 函
数,从而抛出一个错误。
7、可省略的参数,使用undefined来设置为默认值
function foo (optional = undefined) { · · · }
8、可变参数:rest ...values
function add ( ... values) (
let sum = 0;
for ( v ar val of values) (
sum += val ;
}
return sum;
}
add (2 , 5, 3) // 10
9、name属性: 返回的是函数的函数名,只是函数的名称
10、箭头函数:
ES6 允许使用“箭头”(=>)定义函数。
var f = v => v ;
上面的箭头函数等同于以下代码。
var f = function(v) {
return v;
}
如果箭头函数不需要参数或需要多个参数,就使用圆括号代表参数部分。
var f = () => 5;
//等同于
var f = function () { return 5 };
var sum = (numl , num2) => numl + num2;
//等同于
var sum= function(numl, num2) {
return numl + num2;
}
var sum = (numl, num2) => { return numl + num2; }
由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上
括号。
var getTempitem = id=> ({id: id, name :”Temp ” ));
11、 箭头函数的使用注意事项
1. 函数体内的this 对象就是定义时所在的对象,而不是使用时所在的对象。
2. 不可以当作构造函数。也就是说, 不可以使用new 命令, 否则会抛出一个错误。
3. 不可以使用arguments 对象, 该对象在函数体内不存在。如果要用,可以用rest 参数
代替。
4 . 不可以使用yield 命令,因此箭头函数不能用作G e nerator 函数。
this 指向的固定化并不是因为箭头函数内部有绑定this 的机制,实际原因是箭头函数根
本没有自己的this ,导致内部的this 就是外层代码块的this 。正是因为它没有this ,所
以不能用作构造函数。
箭头函数转成ES5 的代码如下。
// ES6
function foo () {
setTimeout ( () => {
console.log (’ id :’, this . 工d};
} , 100);
}
// ES5
function foo() {
var _this = this ;
setTimeout(function () {
console.log ( ’ id : ’, _this . id};
} , 100);
}
上面的代码中,转换后的ES 5 版本清楚地说明了箭头函数里面根本没有自己的this ,而
是引用外层的this 。
12、尾调用函数:指某个函数的最后一步是调用另一个函数。只有不再用到外层函数的内部变量,内层函数的调用帧才会取代外层函数的调用帧,否则就无法进行“尾调用优化” 。
function f (x) {
return g(x);
}
function addOne(a) {
var one = 1;
function inner(b) {
return b + one ;
}
return inner(a);
}
上面的函数不会进行尾调用优化,因为内层函数inner 用到了外层函数addOne 的内部变
量。ne.
13、尾递归: 尾调用函数调用自身成为尾递归。但对于尾递归来说,由于只存在一个调用帧,所以永远不会发生“枝溢出”错误。
function factorial (n , total) {
if (n === 1) return total ;
return factorial(n - 1 , n *total );
}
factorial(S, 1) // 120