博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ES6 随记(3.4.1)-- 函数的拓展(参数默认值,扩展运算符)
阅读量:5291 次
发布时间:2019-06-14

本文共 3087 字,大约阅读时间需要 10 分钟。

上一章请见:

1. 

2. 

3. 

4. 

5. 

 

4. 拓展

e. 函数的拓展

· 参数默认值。此节与结构赋值关系甚大,可去往再看一次

再来烧脑的重新打开这个蛋疼的案例,

function fn1({x = 0, y = 0} = {}) {    console.log(x, y);}function fn2({x, y} = { x: 0, y: 0 }) {    console.log(x, y);}fn1() // 0, 0fn2() // 0, 0fn1({x: 3, y: 8}) // 3, 8fn2({x: 3, y: 8}) // 3, 8fn1({x: 3}) // 3, 0fn2({x: 3}) // 3, undefinedfn1({}) // 0, 0fn2({}) // undefined, undefinedfn1({z: 3}) // 0, 0fn2({z: 3}) // undefined, undefined 

但需要一提是函数参数作用域问题。

(写了好些次,还是无法清晰的描述这个现象,我尽力了)

参数,默认值,函数体是同一个作用域,所以不妨按严格的先后关系来运行,由参数开始先声明新变量,然后判断传参有无解析默认值,再运行函数体。

let a = 10;function fn1(b = a+1) {    let a = 100;    console.log(b,a);}fn1();  // 11, 100a = 20;fn1();  // 21, 100function fn2(a, b = a) {    console.log(a, b);}fn2();  // undefined, undefinedfn2(1);  // 1, 1// 同一作用域内同名变量不能声明两次function fn3(x) {    let x = 999;    console.log(x);}fn3();  // 报错:Identifier 'a' has already been declared,// function fn4(x = x+1) 也会报错,同理

而默认值是函数时,这个问题就有些妖了,不过也还是符合规则的。

let a = 1;function test(fn = x => a) { // 此 a 已解析,参数作用域里没有,向上寻找    let a = 10;    console.log(fn());  // 故而参数中的 a 和函数内的 a 早就没关系了}test();          // 1console.log(a);  // 1let x = 1;function test2(x, y = function(){ x = 2; }) {    var x = 3;    y();    // y 中的 x 只与参数 x 有关,var x 后,就是新的 x 不是参数 x 了, 所以不改变 var x 的值    console.log(x);}function test3(x, y = function(){ x = 2; }) {    x = 3;    y();    // 此处所有的 x 都是参数 x 的修改,所以可被修改    console.log(x);}test2();        // 3console.log(x); // 1  函数内都有自己的 x,在自己作用域中,所以就不影响商机作用域了test3();        // 2console.log(x); // 1

所以判断传参有无再解析默认值这个也可以有些其他应用,比如默认值是自运行函数

function throwIfMissing() {    throw new Error('Missing parameter');}function foo(arg = throwIfMissing()) {    return arg;}// 没有传参选用了默认值,所以解析直接运行了 throwIfMissing,// 否则是不运行的那个自运行函数的console.log(foo(1)); // 1foo(); // Uncaught Error: Missing parameter

注:当传入参数为 null 时不会选用默认值,而 undefined 会。

function foo(x = 1, y = 1) {    console.log(x, y);}foo(undefined, null); // 1, null

再者,非最后一位参数传入空值,会报错,显而易见的。

fn(, 3);    // 报错fn(1, , 3); // 报错

函数的 length 属性会被默认值打断,虽然并不知道这个有啥实际用途,但还是抄下来吧

(function (a) {}).length; // 1(function (a = 5) {}).length; // 0(function (a, b, c = 5) {}).length; // 2(function(...args) {}).length // 0

 

 ·  拓展运算符 ...

1. 剩余参数非常好理解,也非常好用

function add(first, ...items) {    return first + items.reduce((pre, cur) => pre + cur);}console.log(add(10, 2,3,4));  // 19

2. 数组的拆分

console.log(...[1,2]); // 1 2let point1 = [0, 0], point2 = [3, 4];function distance(x1, y1, x2, y2){    return Math.hypot((x2-x1), (y2-y1));}console.log(distance(...point1, ...point2));  // 5

3. 转化类数组数据

[...arguments][...document.querySelectorAll('div')]

4. 可取代 apply

Math.max.apply(null, [14, 3, 77]);Math.max(...[14, 3, 77]);Array.prototype.push.apply(arr1, arr2);arr1.push(...arr2);

5. 解构赋值

const [first, ...rest] = [1, 2, 3, 4, 5];console.log(first, rest); // 1 [2, 3, 4, 5]

6. 帮助解决字符串 UTF-16 问题

console.log([...'x\uD83D\uDE80'].length) // 2console.log([...'x\uD83D\uDE80'].reverse().join('')); // ?x

  

 · 'use strict' 的不同

由于现在默认值的解析是在函数体之前的,所以默认值解析完再设定严格模式当然有时会产生错误。

因此,现在的 'use strict' 只能放在全局或者没有参数的函数里

 

本文部分转载自  的 

转载于:https://www.cnblogs.com/foreverZ/p/6734052.html

你可能感兴趣的文章
<每日 1 OJ> -LeetCode 7. 整数反转
查看>>
<每日 1 OJ> -LeetCode 13 . 罗马数字转正数
查看>>
c语言用指针定义一个类型进行输入输出
查看>>
数字电路基础知识
查看>>
C语言之“字符”与“字符串”之间的区别解析
查看>>
<每日 1 OJ> -24. The Simple Problem
查看>>
<每日 1 OJ> -内存文件系统
查看>>
<每日 1 OJ> -LeetCode 28. 实现 strStr()
查看>>
<每日 1 OJ> -LeetCode 21. 合并两个有序链表
查看>>
字符串必须申请内存空间
查看>>
字符串与指针
查看>>
Linux上安装git并在gitlab上建立对应的项目
查看>>
<每日 1 OJ> -LeetCode20. 有效的括号
查看>>
git 学习网站
查看>>
Git常用操作
查看>>
ping-pong buffer
查看>>
Linux 中【./】和【/】和【.】之间有什么区别?
查看>>
Ubuntu sudo 出现 is not in the sudoers file解决方案
查看>>
内存地址对齐
查看>>
看门狗 (监控芯片)
查看>>