解构赋值
从数组或者对象中提取值去对变量/数组赋值被称为解构。
一、数组解构赋值
类似于
注意点:
右边必须为可遍历的结构。
- 左>右
对于没有办法匹配的变量,会被赋值为undefined,数组会被赋为空1234let [x, y, ...z] = ['a'];x // "a"y // undefinedz // []
为了避免这样,可以考虑给默认值。且一旦右边的值非严格等于undefined,就会覆盖左边的默认值
- 左<右
不完全解构,只取部分值1234let [a, [b], d] = [1, [2, 3], 4];a // 1b // 2d // 4
二、对象的解构赋值
变量必须与属性同名,才能取到正确的值。本质上类似于
|
|
- 区分模式和变量
也可以设置默认值
123456var {x,y=5} = {x:1}x //1y //5var {x:y = 3} = {x: 5};y // 5不要将花括号写在行首,避免被解释为代码块,用括号包裹即可。
123456var x;{x} = {x: 1};// SyntaxError: syntax error// 正确的写法({x} = {x: 1});
三、字符串的解构赋值
|
|
数值和布尔值也可以解构
四、用途
交换变量
1[x, y] = [y, x+y];从函数返回多个值
1234function example() {return [1, 2, 3];}var [a, b, c] = example();函数参数的默认值
与for of 配合遍历
123for (let [key, value] of map) {console.log(key + " is " + value);}模块
字符串扩展
- includes/startsWith/endsWith(str,index)
index为开始搜索的位置 repeat()
12"he".repeat(3) //hehehe"he".repeat(0) //""
- 标签模板
跟在函数名后面的模板字符串会被识别为多个参数。
可以用来对用户传入的数据进行预处理,比如过滤HTML字符串,防止用户输入恶意内容- 用途1
123456789101112131415161718192021222324252627var message =SaferHTML`<p>${sender} has sent you a message.</p>`;function SaferHTML(templateData) {var s = templateData[0]; //<p>for (var i = 1; i < arguments.length; i++) {var arg = String(arguments[i]); //sender// Escape special characters in the substitution.s += arg.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");// Don't escape special characters in the template.s += templateData[i];//templateData[i]这边指has sent you a message.</p>}return s;}//类似于functionName(strArr,..valuesArr),这边的strArr即为模板字符串中分解出来的所有非变量的字符串所组成的数组。//"templateData" ["<p>", " has sent you a message.</p>"]//"arguments" [object Arguments] {0: ["<p>", " has sent you a message.</p>"],1: "luchen"}arguments = strArr + valuesArr
除此之外,还有一个很神奇的用法,就是可以将普通的javascript转换为其他语言,比如说jsx..
,找到jsx函数的实现,然后就可以将一个DOM字符串转为React对象..四国以..
数值的扩展
0b,0o 二进制八进制写法
123456780b111110111 === 5030o767 === 503//es5parseInt("111110111", 2) === 503parseInt("767", 8) === 503//转为十进制用Number(str)Number('0b111')原有方法加了Number限定,取消全局函数
传统方法先用Number转换,然后判断,而现在不会转换,如果非数值,直接false12345Number.isFinite() Number.isNaN()Number.parseInt() Number.parseFloat()Number.isInteger()//Number.isInteger(25) // true 25与25.0被认为是同一个数//Number.isInteger(25.0) // true增加极小值,用于浮点数误差判断
Number.EPSILON整数范围
JavaScript能够准确表示的整数范围在-2^53到2^53之间(开区间)
现在用Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER这两个常量,用来表示这个范围的上下限。12Number.MAX_SAFE_INTEGER === 2**53-1Number.MAX_SAFE_INTEGER === -(2**53-1)Math对象的扩展
Math.trunc()
取数的整数部分,截断,非四舍五入。非数值先Number(),不能转则NaN1234//等于function mathTrunc (x) {return (x < 0 ? Math.ceil(x) : Math.floor(x))}Math.sign()判断符号
- 三角函数运算
- 对数运算
- 指数运算 12**3 ===8
数组扩展
对象=》数组
- Array.from()
将以下两种对象转变为数组
- 类似数组的对象(array-like object),如arguments,getElementsByTag得到的集合
可遍历(iterable)的对象,如Set Map
任何有length属性的对象,都可以通过Array.from方法转为数组
(1)用法:
1Array.from(arrayLike, x => x * x);
**补充**:
扩展运算符(...)也可以做到。主要是以下场景:
12345
function f1(param1,...arr){//确切的说是rest参数 //arr == [v2,v3]}f1(v1,v2,v3)
Array.of()
将一组数值转为数组123Array.of() // []Array.of(undefined) // [undefined]Array.of(1) // [1]arr.copyWithin(destIndex,srcStart,srcEnd)
12// 将3号位复制到0号位[1, 2, 3, 4, 5].copyWithin(0, 3, 4)arr.find() arr.findIndex
主要是由于arr.indexOf比较是基于===全等操作符,那么NaN就不能被找到,因为跟NaN有关的表达式都会返回false.
参数为回调函数123[1, 5, 10, 15].findIndex(function(value, index, arr) {return value > 9;}) // 2补充:
1arr.includes(param1,startIndex) //es7arr.fill()
常用语初始化1new Array(3).fill(7) //[7,7,7]arr.entries(),keys(),values()
常与for..of一起使用进行对象遍历123for (let index of ['a', 'b'].keys()) {console.log(index);}
函数的扩展
函数参数默认值
只能作为尾参数rest参数 值-》数组
1234567891011function add(...values) {let sum = 0;for (var val of values) {sum += val;}return sum;}add(2, 5, 3) // 10扩展运算符
将数组-》逗号分隔的序列
不同于rest参数是在形参中,扩展运算符用于函数调用里123456function add(x, y) {return x + y;}var numbers = [4, 38];add(...numbers) // 42
常用
- 箭头函数
- 尾递归
-》递归改写,以解决多余的参数的问题(套一层函数/curry/es6默认值)
-》优化:循环替代递归
(1)返回函数而不是返回函数调用,用链式调用来替代嵌套调用
见阮一峰es6
(2)memonization存储中间值
具体见高性能javascript(p76)
对象扩展
属性、方法的简写
12345678910111213var birth = '2000/01/01';var Person = {name: '张三',//等同于birth: birthbirth,// 等同于hello: function ()...hello() { console.log('我的名字是', this.name); }};属性名表达式,
也可以用来定义方法名12345let propKey = 'foo';let obj = {[propKey]: true,};方法的name属性
get/set函数 -》person.firstName.name // “get firstName”
匿名函数 (new Function()).name // “anonymous”
symbol const key1 = Symbol(‘description’);Object.is
在===的基础上补充两点:
NaN
1Object.is(NaN, NaN) // true+0 -0不相等
1Object.is(+0, -0) // false
- Object.assign
浅拷贝,如果源对象的某个key的value是对象,那么复制的是这个对象的引用。
123456var obj1 = {a: {b: 1}};var obj2 = Object.assign({}, obj1);obj1.a.b = 2;obj2.a.b // 2tong同名属性,只会替换,不会添加
只能拷贝自身属性,不能拷贝继承的属性以及不可枚举的属性。
用途:
给对象添加属性
12345class Point{constructor(x,y){Object.assign(this,{x,y})}}给对象添加方法
12345Object.assign(someClass.prototype,{someMethod(arg1, arg2) {···},})
- 克隆对象1234function clone(origin) {let originProto = Object.getPrototypeOf(origin);return Object.assign(Object.create(originProto), origin);}
- 属性的遍历
for..in,Object.keys(),Object.getOwnPropertyNames(obj),Object.getOwnPropertySymbols(obj),Reflect.ownKeys(obj)
遍历顺序: 数字(按大小)-》字符串(按生成时间)-》Symbol(按生成时间)
- es7中的
Object.getOwnPropertyDescriptors
rest用于对象解构
补充知识
ES5有三个操作会忽略enumerable为false的属性。
- for…in循环:只遍历对象自身的和继承的可枚举的属性
- Object.keys():返回对象自身的所有可枚举的属性的键名
- JSON.stringify():只串行化对象自身的可枚举的属性
- es6中Object.assign():跟Object.keys一样,只拷贝自身的可枚举属性
es6中所有class的原型的方法都是不可枚举的。