ES6 随记(3.4.1)-- 函数的拓展(参数默认值,扩展运算符)
上一章请见:
4. ES6 随记(3.2)-- 正则的拓展 & 数值的拓展
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, 0
fn2() // 0, 0
fn1({x: 3, y: 8}) // 3, 8
fn2({x: 3, y: 8}) // 3, 8
fn1({x: 3}) // 3, 0
fn2({x: 3}) // 3, undefined
fn1({}) // 0, 0
fn2({}) // undefined, undefined
fn1({z: 3}) // 0, 0
fn2({z: 3}) // undefined, undefined
但需要一提是函数参数作用域问题。
(写了好些次,还是无法清晰的描述这个现象,我尽力了)
参数,默认值,函数体是同一个作用域,所以不妨按严格的先后关系来运行,由参数开始先声明新变量,然后判断传参有无解析默认值,再运行函数体。
let a = 10;
function fn1(b = a+1) {
let a = 100;
console.log(b,a);
}
fn1(); // 11, 100
a = 20;
fn1(); // 21, 100 function fn2(a, b = a) {
console.log(a, b);
}
fn2(); // undefined, undefined
fn2(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(); // 1
console.log(a); // 1 let 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(); // 3
console.log(x); // 1 函数内都有自己的 x,在自己作用域中,所以就不影响商机作用域了
test3(); // 2
console.log(x); // 1
所以判断传参有无再解析默认值这个也可以有些其他应用,比如默认值是自运行函数
function throwIfMissing() {
throw new Error('Missing parameter');
}
function foo(arg = throwIfMissing()) {
return arg;
}
// 没有传参选用了默认值,所以解析直接运行了 throwIfMissing,
// 否则是不运行的那个自运行函数的
console.log(foo(1)); // 1
foo(); // 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 2 let 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) // 2
console.log([...'x\uD83D\uDE80'].reverse().join('')); //ES6 随记(3.4.1)-- 函数的拓展(参数默认值,扩展运算符)的更多相关文章
- C++ 函数特性_参数默认值
函数参数默认值写法 有默认参数值的参数必须在参数表的最右边 ,) // 这是正确的写法 , int k) // 这是错误写法 先声明,后定义 在写函数时要先在代码前面声明,然后再去定义. 函数默认参数 ...
- JS:函数多个参数默认值指定
函数有一个参数时,以往这样定义(参数为p1): function mfun(p1){ … } 当需要为p1设定一个默认值时 function mfun(p1){ if(p1===undefined) ...
- 关于Java函数不支持参数默认值的讨论,最后一条亮了 2333
- es6(三):es6中函数的扩展(参数默认值、rest参数、箭头函数)
1.函数可以设置参数默认值 function test1(x,y=1){ console.log(x,y) } test1(10)//10 1 2.rest参数:形式为...变量名 function ...
- ES6笔记之参数默认值(译)
原文链接:http://dmitrysoshnikov.com/ 原文作者:Dmitry Soshnikov 译者做了少量补充.这样的的文字是译者加的,可以选择忽略. 作者微博:@Bosn 在这个简短 ...
- ES6学习 --函数参数默认值与解构赋值默认值
1. ES6的解构ES6中引入了解构赋值的操作,其作用是:将值从数组Array或属性从对象Object提取到不同的变量中 即分为两种情况:从数组Array中解构,以及从对象Object中解构 ①.从数 ...
- ES6 学习笔记之三 函数参数默认值
定义函数时为参数指定默认值的能力,是现代动态编程语言的标配.在ES6出现之前,JavaScript是没有这种能力的,框架为了实现参数默认值,用了很多技巧. ES6 的默认参数值功能,与其他语言的语法类 ...
- ES6函数参数默认值作用域的模拟原理实现与个人的一些推测
一.函数参数默认值中模糊的独立作用域 我在ES6入门学习函数拓展这一篇博客中有记录,当函数的参数使用默认值时,参数会在初始化过程中产生一个独立的作用域,初始化完成作用域会消失:如果不使用参数默认值,不 ...
- ES6 - 函数扩展(函数参数默认值)
函数参数默认值 ES6 之前,不能直接为函数的参数指定默认值,只能采用变通的方法. function log(x, y) { y = y || 'World'; console.log(x, y); ...
随机推荐
- Android开源-NineOldAndroids
开源地址: https://github.com/JakeWharton/NineOldAndroids 简单介绍:NineOldAndroids是一款支持在低版本号开发的Android动画的框架 包 ...
- echarts使用要点
- ARM汇编语言(1)(基本概念)
1.***.s文件为汇编语言文件格式: 2.ARM寄存器(以Samsung芯片为例) 2.1.要介绍arm寄存器之前我们要先了解一下arm处理器的工作模式: Arm处理器有七种工作模式,为的是形成不同 ...
- inux redis 安装配置, 以及redis php扩展
一,什么是redis redis是一个key-value存储系统. 和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合)和zset ...
- 【SR】MAP
MAP:最大后验概率(Maximum a posteriori) 估计方法根据经验数据获得对难以观察的量的点估计.它与最大似然估计中的 Fisher方法有密切关系, 但是它使用了一个增大的优化目标,这 ...
- 转载 web前端简历
Web前端程序员简历模板 本简历模板由国内首家互联网人才拍卖网站「 JobDeer.com 」提供. (括号里的是我们的顾问编写的说明,建议在简历书写完成后统一删除) 先讲讲怎样才是一份好的技术简历 ...
- Web 前端从入门菜鸟到实践老司机所需要的资料与指南合集
http://web.jobbole.com/89188/ 2016 – 对于未来五年内Web发展的7个预测 2015 – 我的前端之路:从命令式到响应式,以及组件化与工程化的变革 怎么成为一名优秀的 ...
- Delphi 发送邮件 通过Office Outlook
Delphi 发送邮件 通过Office Outlook 网上搜到的Delphi邮件发送系统,绝大多数是使用SMTP协议来发送. 但是事实上它们已经过时了,大多数邮件服务器已经屏蔽了Delphi In ...
- 【BZOJ4688】One-Dimensional 矩阵乘法
[BZOJ4688]One-Dimensional Description 考虑一个含有 N 个细胞的一维细胞自动机.细胞从 0 到 N-1 标号.每个细胞有一个被表示成一个小于 M 的非负整数的状态 ...
- form.submit 方法 并不会触发 form.onsubmit 事件
做表单的时候发现一个奇怪的地方,总结下: form.submit 方法 并不会触发 form.onsubmit 事件,看代码: <body> <div class="con ...