function log(x, y = ‘World‘) { console.log(x, y); } log(‘Hello‘) // Hello World log(‘Hello‘, ‘China‘) // Hello China log(‘Hello‘, ‘‘) // Hello 注意:参数变量是默认声明的,所以不能用let或const再次声明 使用参数默认值时,函数不能有同名参数 // 不报错 function foo(x, x, y) { // ... } // 报错 function foo(x, x, y = 1) { // ... } // SyntaxError: Duplicate parameter name not allowed in this context 参数默认值不是传值的,而是每次都重新计算默认值表达式的值。也就是说,参数默认值是惰性求值的(可以与计算属性进行联想理解) let x = 99; function foo(p = x + 1) { console.log(p); } foo() // 100
//参数P的默认值是x+1,每次调用函数foo,都会重新计算x+1 x = 100; foo() // 101
// 写法一 //参数设置了默认值,但是解构对象设置了默认值 function m1({x = 0, y = 0} = {}) { return [x, y]; } // 写法二 //参数设置了默认值,但是解构对象本身没有设置默认值 function m2({x, y} = { x: 0, y: 0 }) { return [x, y]; }
// 例一 function f(x = 1, y) { return [x, y]; } f() // [1, undefined] f(2) // [2, undefined]) f(, 1) // 报错 f(undefined, 1) // [1, 1] // 例二 function f(x, y = 5, z) { return [x, y, z]; } f() // [undefined, 5, undefined] f(1) // [1, 5, undefined] f(1, ,2) // 报错 f(1, undefined, 2) // [1, 5, 2]
length
属性的含义是,该函数预期传入的参数个数。某个参数指定默认值以后,预期传入的参数个数就不包括这个参数了//似乎和for循环的循环条件和循环体相同,都是不同的作用域,函数调用时,函数体内部的局部变量影响不了默认值变量 //例子1 体现了设置默认值出现单独作用域 var x = 1; function f(x, y = x) { console.log(y);//y在作用域范围内寻找x,找到了值2,就不会在寻找 } f(2) // 2 //例子2 体现了作用域链 let x = 1; function f(y = x) { let x = 2;//y在作用域找,x本身没有定义,所以沿着作用域去上层找 console.log(y); } f() // 1 //例子3 function f(y = x) { let x = 2; console.log(y); //两个不同的作用域,所以会报错 } f() // ReferenceError: x is not defined //例子4 如果x是一个函数,也遵循着同样的道理 var x = 1; function foo(x = x) { // ... //参数x = x形成一个单独作用域。实际执行的是let x = x 暂时性死区,在声明之前使用变量 } foo() // ReferenceError: x is not defined
var x = 1;
function foo(x, y = function() { x = 2; }) { //此时x变量的值都是1
var x = 3; //这个变量x与上面那个变量x不再同一个作用域,所以他们不是同一个变量
y(); //执行y()以后,foo函数体内的变量x不会改变,改变的只有foo参数部分的变量
console.log(x); //如果去除var = 3,那么打印的值就是2.因为匿名函数里面的x与第一个参数的x是同一个作用域,所以是同一个变量
}
foo() // 3
x // 1
//rest 参数(形式为...变量名),rest参数搭配的是一个数组,所以可以使用数组的所以方法 //rest还可以将多余的参数放入到这个数组当中,这样以后就可以不用使用arguments对象了 //tip arguments是个类数组转换: Array.prototype.slice.call(arguments).sort(); function add(...values) { let sum = 0; console.log(values.length) //for (var val of values) { // sum += val; //} // //return sum; } add(2, 5, 3)
name
属性,会返回空字符串,而 ES6 的name
属性会返回实际的函数名var f = v => v; // 等同于 var f = function (v) { return v; }; 1:箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分 var f = () => 5; // 等同于 var f = function () { return 5 }; var sum = (num1, num2) => num1 + num2; // 等同于 var sum = function(num1, num2) { return num1 + num2; }; 2:如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回 var sum = (num1, num2) => { return num1 + num2; } 3:如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错 会将{}里面当做一个代码块去执行,所以报错 // 报错 let getTempItem = id => { id: id, name: "Temp" }; // 不报错 let getTempItem = id => ({ id: id, name: "Temp" }); 4:箭头函数只有一行语句,且不需要返回值 let fn = () => void doesNotReturn(); 注意点: 1:函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。 2:不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误 3:可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。 4:不可以使用yield命令,因此箭头函数不能用作 Generator 函数
待续.....
原文:https://www.cnblogs.com/panrui1994/p/9203051.html