解构赋值
定义:按照一定的模式匹配,从数组和对象中提取值,对变量进行赋值
数组解构
基本用法
let [a, b] = [1, 2]; // a = 1, b = 2
let [a, ...b] = [1, 2, 3]; // a = 1, b = [2, 3]
let [a, ...b] = [1]; // a = 1, b = []
如果解构不成功,默认值为undefined
let [a, , b] = [1, 2]; // a = 1, b = undefined
如果等号右边不是数组将会报错
// 报错
let [foo] = 1
let [foo] = false
let [foo] = null
let [foo] = undefined
let [foo] = {}
let [foo] = NaN
默认值
解构赋值还可以有默认值
只有当成员变量严格等于undefined,默认值才生效
let [a = 1, b] = []; // a = 1, b = undefined;
let [a = 1, b = 2]; // a = 1 , b =2;
let [a = 1, b] = [null]; // a = null, b = undefined;
默认值可以引用解构赋值的其他变量,前提必须要该变量已申明
let [a = 1, b = a] = []; // a = 2, b = 1
let [a = 1, b = a] = [2]; // a = 2, b = 2
let [a = 1, b = a] = [2, 3]; // a =2 , b = 3;
let [a = b, b = 1] = []; // 报错 b is not defined
对象的解构
基本用法
对象的解构和数组的解构有所区别,数组中的元素是有次序的,变量的取值由它的位置决定,而对象中的元素是没有次序的,变量必须与属性名同名,才能取到值
let {foo, bar} = { foo: '1', bar: '22'}; // foo = '1', bar = '22'
解构失败,默认值为undefined
let { foo } = {bar: 'aa'}; // foo = undefined
对象的解构赋值,实际是找到同名属性后,对变量进行赋值
let {foo: bar} = { foo : 'ss'} ;// bar = 'ss', 如果输出fool变量,foo is not defined
复杂结构的解构赋值
let obj = {
p: [
'Hello',
{ y: 'World' }
]
};let { p: [x, { y }] } = obj;
x // "Hello"
y // "World"p是模式,不是变量,不会被赋值。
如果有p要被赋值,可以写作下面:
let obj = {
p: [
'Hello',
{ y: 'World' }
]
};let { p, p: [x, { y }] } = obj;
如果解构模式是嵌套对象,子对象所在的父属性不存在,那么将会报错。
// 报错
let { foo: { bar}} = { bar: 'bar' };
foo属性为undefined,再取子对象就会报错。 // bar is not defined
对象解构默认值
对象解构默认值生效的条件,对象的属性值严格等于undefined
let {x: y = 1} = {} // y = 1
let {x = 3} = {y: 4} ; // x = 3
let {x, y = 1} = {x: 2}; // x = 2 , y = 1
let {x: y = 3} = {x: 4}; // y = 4
let {x: y =4} = { y: 3}; // y = 4
函数参数的默认值
// 默认值
function move([x = 3, y = 4]) {
return x + y ;
}
move([1, 2]); // x =1 , y =2
move([1]); // x = 1, y =4
move(); // 报错
move([]) ;// 3. 4
// 对函数的参数指定默认值
function move([x , y ] = [5, 6]) {
return x + y ;
}
move([1, 2]); // x =1 , y =2
move([1]); // x = 1, y = undefined
move(); // x = 5, y = 6
move([]); // x = undefined, y = undefined
// 对x和y解构给默认值
function move([x =1, y=2 ] = []) {
return x + y ;
}
move([1, 2]); // x =1 , y =2
move([1]); // x = 1, y =2
move(); // x =5 , y =6
move([]); // x = 1, y = 2
用途
1、交换变量值
let x= 1;
let y = 2;
let [x, y] = [y, x]
2、 从json中提取变量
let jsonData = { name: ''22", age: 31}
let {name, age} = jsonData
3、从模块中提取变量
const { SourceMapConsumer, SourceNode } = require("source-map");
字符串的扩展
startWith() 、endsWith()、includes()
const a = 'hellow javascript'
a.startsWith('hellow') ;// true
a.endsWith('javascript'); // true
a.includes('java'); // true
// 允许有第二个参数
a.startsWith('java', 8); // true
a.endsWith('ow', 6); // true
a.includes('java', 6); true
当有第二个参数是,endsWith和其他2个方法不同,它针对前n个字符,而其他两个方法表示从第n个字符开始知道结束
数值的扩展
Number
Number.parseInt()、Number.parseFloat()
将全局方法parseInt()、parseFloat()移植到Number对象上面,行为完全保持一致。
// ES5写法
parseInt('22.4'); // 22
parseFloat('22.3#'); // 22.3
// ES6的写法
Numebr.parseInt('22.4'); // 22
Number.parseFloat('22.3#'); // 22.3
Number.isInteger()
判断一个值是否为整数,返回布尔值,如果参数不是数值,则返回false
Number.isInteger('25'); // true
Number.isInteger('25.1'); // false
Number.isInteger(null); // false
Math
Math.trunc()
去除一个数的小数部分,返回整数部分。
Math.trunc(1.1); // 1
Math.trunc(-1.9); // -1
Math.trunc(0.333); // 0
如果参数是非数值,默认会将其转换为数值
Math.trunc(false); // 0
Math.trunc('11.22'); // 11
Math.trunc(null); // 0
如果是空值或者无法截取整数的值,返回NaN
Math.trunc(); // NaN
Math.trunc(undefined); // NaN
Math.sign()
判断一个数到底是整数,负数,还是零,如果该数不是数值,会将其转换为数值。
会返回五种值:
--参数为正数,返回+1;
--参数为负数,返回-1;
--参数为0,返回 +0
--参数为-0,返回 -0;
--其他值,返回NaN;
Math.sign(1000); +1
Math.sign(-111.4); -1
Math.sign(0); // +0
Math.sign(undefined); // NaN
Math.sign('111.44'); // +1
Math.sign(false); // 0
Math.sign(null); // 0
函数的扩展
默认值
function foo(x, y = 0) {
//
}
使用参数默认值时,函数不能有同名参数
// 不报错
function foo(x, y, y ) {}
// 报错
function foo(x, y, y = 0) {}
与解构赋值默认值结合使用
function foo({x, y = 1}) {
//
}
foo({}) // ;undefined 1
foo({ x: 1}); 1, 1
foo({x:3, y: 7}); // 3 7
foo(); // 报错
解构默认值结合函数参数默认值
function foo({x=1, y = 2} = {}) {
console.log(x, y);
}
foo({}) // ;1, 2
foo({ x: 2}); 1, 2
foo({x:3, y: 7}); // 3 7
foo(); // 1, 2
参数默认值的位置
带默认值的参数不是函数的尾参数不能省略
function foo(x=1, y) {}
foo(,1); // 报错
函数的length属性
函数的length属性表示,函数的参数的个数。
函数的参数带有默认值,则只返回不带默认值的参数个数。
应用
rest参数 ...values
使用了rest参数,后面不允许带其他参数
function foo(x, ...value) {} //
foo(1,3,4); // value = [3, 4]
箭头函数
数组的扩展
扩展运算符
rest运算的逆运算,将数组打散为逗号分隔的参数序列
console.log(...[1,2]);
// 1 2
扩展运算符的作用
复制数组
let a1 = [1,2]
let b = [...a1]
数组合并(浅拷贝)
let a = [{x: 1}];
let b = [{y: 2}];
let c = [...a, ...b]
c[0] === a[0] // true
Array.from()
将类数组对象或者可遍历的对象转换为真实的数组
let a = {'0': 1, '1': 2}
Array.from(a); // [1, 2]
Array.of()
将一组值转换为数组
Array.of(1, 2, 3); // [1, 2, 3]
find() 、findIndex()
find()返回第一个符合该条件数组成员,接收一个函数作为参数,没有找到就返回undefined
findIndex() 返回第一个符合该条件的成员的数组索引,没有找到就返回-1
includes()
表示数组是否包含指定值
对比indexOf
indexOf方法有两个缺点,一是不够语义化,它的含义是找到参数值的第一个出现位置,所以要去比较是否不等于-1,表达起来不够直观。二是,它内部使用严格相等运算符(===)进行判断,这会导致对NaN的误判。
flat()
拉平数组,默认拉平一层
拉平一层:flat()
拉平二层:flat(2)
拉平n层:flat(Infinity)
flatMap()
对象的扩展
属性的简写
const name = "Alice"
const obj = {
name,
say() {
return `my name is ${this.name}`
}
}
这种写法对函数的返回值非常有用
function foo () {
const x = 1;
const y = 2;
return {x, y}
}
foo(); // { x: 1, y: 2}
简写的对象写法不能用作构造函数,否则会报错
属性名表达式
// 写法一
const obj.ab = false;
// 写法二
const obj['a' + 'b'] = false
对象新增的方法
Object.is
除了+0和-0不等,NaN和NaN相等之外, 其他和 === 表现基本一致
Object.assign
Symbol
避免属性重名
symbol作为对象属性名时,该属性不会出现在for in, for of 遍历中,也不会在Object keys, JSON.stringify, getOwnPropertyNames中返回
Symbol.for(), Symbol.keyFor()