安卓优化神器网站seo综合查询
文章目录
- 函数的扩展
- 1.函数参数的默认值
- 1.1 基本用法
- -- 参数变量是默认声明的,所以不能用 let或const 再次声明
- -- 使用参数默认值时,函数不能有同名参数
- 1.2 与解构赋值默认值结合使用
- ☆☆☆ 函数参数的默认值生效以后,参数解构赋值依然会进行
- 1.3 参数默认值的位置
函数的扩展
1.函数参数的默认值
1.1 基本用法
ES6 之前,不能直接为函数的参数指定默认值,只能采用变通的方法。
…
ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面。
function log(x, y = 'World') { // lz:相当于是默认参数直接赋值了console.log(x, y);
}log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello
可以看到,ES6 的写法比 ES5 简洁许多,而且非常自然。下面是另一个例子。
function Point(x = 0, y = 0) { // js这个默认参数写在()中,思路很好!this.x = x;this.y = y;
}const p = new Point();
p // { x: 0, y: 0 }
除了简洁,ES6 的写法还有两个好处:首先,阅读代码的人,可以立刻意识到哪些参数是可以省略的,不用查看函数体或文档;其次,有利于将来的代码优化,即使未来的版本在对外接口中,彻底拿掉这个参数,也不会导致以前的代码无法运行。
————
– 参数变量是默认声明的,所以不能用 let或const 再次声明
function foo(x = 5) {let x = 1; // errorconst x = 2; // error
}
————
– 使用参数默认值时,函数不能有同名参数
// 不报错,因为没有使用默认参数
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() // 100x = 100;
foo() // 101
上面代码中,参数p的默认值是 x + 1
。这时,每次调用函数 foo()
,都会重新计算x + 1
,而不是默认p
等于 100
。
1.2 与解构赋值默认值结合使用
参数默认值可以与解构赋值的默认值,结合起来使用。
(讲解解构赋值的地方也涉及到函数)
function foo({x, y = 5}) {console.log(x, y);
}foo({}) // undefined 5 // 提供一个空对象作为参数,不报错
foo({x: 1}) // 1 5
foo({x: 1, y: 2}) // 1 2
foo() // TypeError: Cannot read property 'x' of undefined // 没有提供参数用于解构赋值!所以报错!
上面代码只使用了对象的解构赋值默认值,没有使用函数参数的默认值。只有当函数foo()
的参数是一个对象时,变量x
和y
才会通过解构赋值生成。
如果函数foo()
调用时没提供参数,变量x
和y
就不会生成,从而报错。通过提供函数参数的默认值,就可以避免这种情况。
参考解构赋值:☆☆☆ 函数参数解构的默认值
// 为变量x和y指定默认值
function foo({x, y = 5} = {}) { // 对象的默认值console.log(x, y);
}foo() // undefined 5
上面代码指定,如果没有提供参数,函数foo
的参数默认为一个空对象。
————
下面是另一个解构赋值默认值的例子。
function fetch(url, { body = '', method = 'GET', headers = {} }) { console.log(method); // 以上存在危险写法!
}fetch('http://example.com', {})
// "GET"fetch('http://example.com')
// 报错
上面代码中,如果函数fetch()
的第二个参数是一个对象,就可以为它的三个属性设置默认值。
这种写法不能省略第二个参数,如果结合函数参数的默认值,就可以省略第二个参数。这时,就出现了双重默认值。
function fetch(url, { body = '', method = 'GET', headers = {} } = {}) {console.log(method);
}fetch('http://example.com')
// "GET"
上面代码中,函数fetch
没有第二个参数时,函数参数的默认值就会生效,然后才是解构赋值的默认值生效,变量method
才会取到默认值GET
。
☆☆☆ 函数参数的默认值生效以后,参数解构赋值依然会进行
function f({ a, b = 'world' } = { a: 'hello' }) {console.log(b);
}f() // world
上面示例中,函数f()
调用时没有参数,所以参数默认值{ a: 'hello' }
生效,然后再对这个默认值进行解构赋值,从而触发参数变量b
的默认值生效。
————
作为练习,大家可以思考一下,下面两种函数写法有什么差别?
// 写法一
function m1({x = 0, y = 0} = {}) {return [x, y];
}// 写法二
function m2({x, y} = { x: 0, y: 0 }) {return [x, y];
}// 函数没有参数的情况
m1() // [0, 0]
m2() // [0, 0]// x 和 y 都有值的情况
m1({x: 3, y: 8}) // [3, 8]
m2({x: 3, y: 8}) // [3, 8]// x 有值,y 无值的情况
m1({x: 3}) // [3, 0]
m2({x: 3}) // [3, undefined]// x 和 y 都无值的情况
m1({}) // [0, 0];
m2({}) // [undefined, undefined]m1({z: 3}) // [0, 0]
m2({z: 3}) // [undefined, undefined]