【NodeJS】ES6的基础语法
ES6的基础语法
一. let和const的认识
let关键字:
- ES6新增的命令,用来声明变量。用法和var相似,但let所声明的变量只在let命令所在的代码块内有效
```js
{
let a = 5;
var b = 10;
}
console.log(a); // ReferenceError: a is not defined
console.log(b); // 10
```
-
在同一块级作用域内不允许重复声明,不存在变量提升
// 不存在变量提升会报错 console.log(num); let num = 10; // 在同一块级作用域内不能重复声明,会报错 let num = 10; let num = 30;
-
有块级作用域
for(let i = 0;i<=5;i++){ // 不报错 console.log(i);// 0 1 2 3 4 5 } // 报错只能在声明的代码块内有效 console.log(i); // ReferenceError: i is not defined
- 很适合在for循环中使用
-
有暂时性死区: 只要在块级作用域内存在let命令,他所声明的变量就”绑定“这个区域,不再受外部影响
if (true) { // num = '一二三'; // ReferenceError // console.log(num); // ReferenceError let num; console.log(num); // undefined num = '四五六' console.log(num); // 四五六 }
在代码块内,使用let声明变量之前,该变量都是不可用的
-
**注意:**ES6 明确规定,如果区块中存在
let
和const
命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。 -
var和let的区别:
- var:
- 有变量提升
- 没有块级作用域,是函数作用域
- 可以重复声明
- 可以重新赋值
- let:
- 没有变量提升
- 有块级作用域
- 不能重复声明
- 可以重新赋值
- var:
const关键字:
-
声明一个只读的常量。一旦声明,常量的值就不能改变.
const
只声明不赋值会报错const num; // SyntaxError: Missing initializer in const declaration
- 一旦声明就必须立即初始化,不能留到以后赋值。
const num = 10086;
-
const作用域和let一样,只在声明所在的块级作用域内有效
if(true){ const num = 666; console.log(num); // 666 } console.log(num); // ReferenceError: num is not defined
-
不存在变量提升,不可重复声明
// 不能重复声明 const num = 100; const num = 200; // SyntaxError: Identifier 'num' has already been declared // 不存在变量提升 console.log(str); // ReferenceError: Cannot access 'str' before initialization const str = 'hello';
-
有暂时性死区
if(true){ // console.log(num); // ReferenceError const num = 666; console.log(num); // 666 }
-
扩展:ES6声明变量有六种方法: var、function、let、const、import、class
二. 变量解构赋值
1. 对象解构赋值
-
取对象中属性的值,赋值给变量
// 当变量名和对象属性名不一致 let {name:username,age:userage} = {name:'李四',age:16} console.log(username,userage); // 李四 16 // 当变量名和对象属性名一致 let {name:name,age:age} = {name:'zhangsan',age:28} console.log(name,age); //张三 28 // 当变量名和对象属性名一致时简化写法 let {name,age} = {name:'张三',age:28} console.log(name,age); //张三 28
-
对象解构只要属性名和变量名一致就能取得值,次序不一致没影响
let cat = { name: '狸花猫', age: 2, color: '黑色' } // 次序不一致没影响 let { color, age, name } = cat console.log(name, age, color); // 狸花猫 2 黑色
-
可以将现有对象的方法,赋值到某个变量。
const {log} = console; log('hello'); // hello
把console的log赋值给log变量
const { log:look } = console; look('hello'); // hello
可以自定义
-
如果变量取不到值,就等于undefined
let {color}={name:'yahaha',age:2}; console.log(color); // undefined
-
可以用于嵌套结构的对象
let obj ={ dog:[ '汪汪', {x : '叫'} ] }; let {dog:[a,{x}]} = obj; console.log(a,x); // 汪汪 叫 // 如果dog也要作为变量赋值 let{dog,dog:[a,{x}]} = obj; console.log(a, x, dog); // 汪汪 叫 [ '汪汪', { x: '叫' } ]
-
剩余符号…,表示取所有剩下的. 只能在最后一个变量前使用
let obj = { name: '某某某', age: 18, score: 0.5, like: '听音乐' } let {name,...obj2} = obj; console.log(name,obj2); // 某某某 { age: 18, score: 0.5, like: '听音乐' } let {name,like,...obj2} = obj; console.log(name,obj2); // 某某某 听音乐 { age: 18, score: 0.5}
-
可以指定默认值
let {color='red',name,age}={name:'yahaha',age:2}; console.log(name, age, color); // yahaha 2 red
默认值生效的条件是对象的属性值严格等于undefined
let {color = 'black'} = {color:undefined}; console.log(color); // black let { num = 3 } = { num: null }; console.log(num); // null
- 如果有默认值的情况
let obj = { name:'李白' , age:20 } let {age=10,name} = obj; console.log(name,age); // 李白 20
相当于
let { age: age = 10, name:name } = obj;
用obj里age属性的值对变量age重新赋值,所以值是20 -
总结: 对象解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。
2. 数组解构赋值
-
从数组中提取值,按照对应位置,对变量赋值。
let arr = [1,2,3]; let [a,b,c] = arr; console.log(a,b,c); // 1 2 3
- 可以只匹配一部分值
```js
let arr = [1,2,3];
let [a,,] = arr;
console.log(a); // 1
let [,b,] = arr;
console.log(b); // 2
let [,,c] = arr;
console.log(c); // 3
let [a , , c] = arr;
console.log(a, c); // 1 3
let [a, , , , , f] = [1,2,3,4,5,6];
console.log(a, f); // 1 6
let [, , ,d , , f] = [1,2,3,4,5,6];
console.log(d, f); // 4 6
-
默认值
let arr = [1,2,3]; let [a,b,c,d=50] = arr; console.log(a,b,c,d); // 1 2 3 50 let [a=10, b, c] = arr; console.log(a, b, c); // 1 2 3
-
剩余符号…,表剩下的全要.只能在最后一个变量前使用
let [a, ...b] = [1, 2, 3,4,5,6] console.log(b); // 2 3 4 5 6 let [a, ...b, c] = [1, 2, 3,4,5,6] console.log(b); // SyntaxError: Rest element must be last element
3. 字符串的解构赋值
let [a,b,c,d,e] = 'hello';
console.log(a,b,c,d,e); // h e l l o
let {length:len} = 'hello'; console.log(len); // 5
因为类似数组所以有length属性,可以对这个属性结构赋值
4. 解构赋值结合函数声明
-
声明一个函数,有多个形参
function test({name,age,color}){ console.log(name,age,color) } test({ name:'二哈', age:3, color:'黑色' }); // 二哈 3 黑色
-
默认值
function test({name,age,color='黑色'}){ console.log(name,age,color) } test({ name:'二哈', age:3 }); // 二哈 3 黑色 test({ name:'二哈', age:3, color:'白色' }); // 二哈 3 白色
三. 箭头函数
-
是密名函数的一个简写
// 普通的密名函数 let fn = function(name){ console.log('你的名字是:'+name); } // 箭头函数 let fn = name => console.log('你的名字是:' + name); fn('张三');
-
简写规则:
- function改成=>, =>可以理解成goes to
- 如果只有一个形参,那就可以省略形参小括号
- 如果不是一个形参,0个或者多个形参,那就不能省略这个形参小括号了
- 如果函数体只有一句话, 那就可以省略函数体的大括号
- 如果函数体只有一句话, 并且这一句话是return 返回值,那return也要省略
- 如果函数体不是一句话, 那就不能省略这个大括号
-
例子
/* let fn = function(str){ return str+'World'; } */ // 箭头函数 let fn = str => str + 'World'; console.log(fn('Hello')); // HelloWorld
// let fn = function(num1,num2){ // console.log(num1+num2); // return num1+num2+63; // } // 箭头函数 let fn = (num1, num2) => { console.log(num1 + num2); return num1 + num2 + 63; } console.log(fn(1,2)); // 3 66
-
箭头函数的this
- 箭头函数的this和我们原来的那些个普通函数的this指向确实是不一样的.
- 箭头 函数的this指向谁? 由箭头函数的上下文环境决定的
- 箭头函数的this指向的原理。
- 把箭头函数上下文环境的this用
_this
来保存 了,那箭头函数中用的this其实就是_this
.
- 把箭头函数上下文环境的this用
- 箭头函数使用注意:
- 不是什么时候都要去使用箭头函数,就像下面这个dom操作使用箭头函数就不方便.
- 不要用new关键字去调用箭头函数.
<input type="button" value="按钮按钮" class="btn"> <script> var btn = document.getElementsByClassName('btn')[0]; // btn.onclick = function(){ // console.log(this.value); // 按钮按钮 // } // 箭头函数 // btn.onclick = () => console.log(this.value); // undefined // btn.addEventListener('click',function(){ // console.log(this.value); // 按钮按钮 // }) // 箭头函数 // btn.addEventListener('click',() => console.log(this.value)); // undefined $('.btn').click(function () { console.log(this.value); // 按钮按钮 }) // 箭头函数 $('.btn').click(() => console.log(this.value)); // undefined </script>
箭头函数的this和普通函数的this指向是不一样的
-
箭头函数的this是由上下文环境决定的
let obj1 = { name:'呀哈哈', sayHi:function(){ console.log('1你好obj1我叫'+this.name); setTimeout(function () { console.log('2你好obj1我叫' + this.name) }, 1000); } } let obj2 = { name: '张三', sayHi: function () { console.log('1你好obj2我叫' + this.name); setTimeout(() => console.log('2你好obj2我叫' + this.name), 1000) } } obj1.sayHi(); obj2.sayHi();
obj1输出为: 1你好obj1我叫呀哈哈
2你好obj1我叫undefined
obj2输出为: 1你好obj2我叫张三
2你好obj2我叫张三
-
箭头函数this指向的原理
let obj2 = { name: '张三', sayHi: function () { var _this = this console.log('1你好obj2我叫' + this.name); setTimeout(() => console.log('2你好obj2我叫' + _this.name), 1000) } }
把箭头函数上下文环境的this用
_this
来保存了,那箭头函数中用的this其实就是_this
四. 数组和对象的扩展
1. 对象的简写
-
ES5写法
let name = '张三' let age = 20 let score = 100 var obj = { name:name, age:age, score:score, show:function(){ console.log(name,age); } }; console.log(obj); // { name: '张三', age: 20, score: 100, show: [Function: show] } obj.show(); // 张三 20
-
ES6写法
let obj2 = { name, age, score, show(){ console.log(name, age); } } console.log(obj2); // { name: '张三', age: 20, score: 100, show: [Function: show] } obj2.show(); // 张三 20
- 如果想新加属性
let obj2 = { name, age, score, nianling:age, show(){ console.log(name, age); } } console.log(obj2); /* { name: '张三', age: 20, score: 100, nianling: 20, show: [Function: show] } */ obj2.show(); // 张三 20
2. 展开运算符
-
对象展开
let person = { eat:'吃东西', run:'跑' } let student = { homework: '做作业', exam: '测试' } let zhangsan = { // 展开语法 ...person, ...student, sex:'男' } console.log(zhangsan); // 输出结果: { eat: '吃东西', run: '跑', homework: '做作业', exam: '测试', sex: '男' }
-
数组展开
let arr1 = [1,2,3] let arr2 = [...arr1,40,50,66] console.log(arr2); // [ 1, 2, 3, 40, 50, 66 ] let arr3 = [66,50,1,55,100,12] let arrMax = Math.max(...arr3); console.log(arrMax); // 100
-
数组降维: 如把二维数组变为一维数组
var arr = [[10,20],[30,40,50]] var arrNew = []; arr.forEach(v=>{ arrNew.push(...v); }) console.log(arrNew); // [ 10, 20, 30, 40, 50 ]
var arr = [10,20,[30,40,50],60,70] var arrNew = []; arr.forEach(v=>{ if(Array.isArray(v)){ arrNew.push(...v); }else{ arrNew.push(v); } }) console.log(arrNew); // [ 10, 20, 30, 40, 50, 60, 70 ]
-
数组去重: 把数组中重复的去掉
var arr = [10,30,20,50,20,30,40,50,60]; var arrNew = []; // 排序后判断 arr.sort((a,b)=>{ return a-b; }) console.log(arr); // [10,20,20,30,30,40,50,50,60] arr.forEach((value,index)=>{ if(value != arr[index+1]){ arrNew.push(value) } }) console.log(arrNew); // [ 10, 20, 30, 40, 50, 60 ]
上面的就是先排序后判断
var arr = [10,20,30,30,20,10,40,50,60]; var arrNew = []; var obj = {}; // 利用对象的属性不能重名 arr.forEach(value=>{ if(obj[value] == undefined){ arrNew.push(value); obj[value] = 1; } }) console.log(arrNew); // [ 10, 20, 30, 40, 50, 60 ]
使用对象法: 利用对象的属性不能重名
-
数组升维
var arr = [ {type:'电子产品',name:'iPhone',price: 8888}, { type: '家具', name: '桌子', price: 50 }, { type: '电子产品', name: '微波炉', price: 500 }, { type: '家具', name: '凳子', price: 25 }, { type: '家具', name: '床', price: 1200 }, { type: '食品', name: '辣条', price: 99999 }, { type: '电子产品', name: '电视', price: 6666 }, { type: '食品', name: '馒头', price: 0.5 }, { type: '食品', name: '老干妈', price: 6 }, { type: '电子产品', name: '电脑', price: 10000 }, { type: '电子产品', name: '手机', price: 4000 } ] var arrNew = []; var obj = {}; arr.forEach(value=>{ // 第一个判断存入第一次出现的类型 if (obj[value.type] == undefined){ arrNew.push({ type: value.type, data:[value] }) obj[value.type] = 1 }else{ // 进了else说明不是第一次出现,追加进相同类型的data中 arrNew.forEach((value2,index)=>{ // 判断是哪一类 if(value.type == value2.type){ // 追加进相应的类 arrNew[index].data.push(value) } }) } }) console.log(arrNew);
-
五. 其他数据类型的拓展
一. 模板字符串
-
会保留原样字符串格式,可以站位
let author = '李白'; let str = ` 静夜思 \t${author} 床前明月光, 疑是地上霜. `; console.log(str); /* 静夜思 李白 床前明月光, 疑是地上霜. */
-
例子
let name = '张三', age = 66, sex = '男'; console.log(`我叫${name},性别:${sex},年龄:${age}`); // 我叫张三,性别:男,年龄:66 function show(){ return '看书'; } console.log(`我喜欢${show()}`); // 我喜欢看书
二. 补充数组的方法
-
forEach()方法:遍历数组,没返回值
let arr = [10,20,30,40] arr.forEach((value,index)=>{ console.log(`索引:${index},值:${value}`); })
输出结果:
索引:0,值:10
索引:1,值:20
索引:2,值:30
索引:3,值:40
-
map()方法:遍历数组,有返回值
let arr = [10,20,30,40] let arrNew = arr.map((value,index)=>{ return value * value; }) console.log(arrNew); // [ 100, 400, 900, 1600 ]
-
filter()方法:过滤器, 会返回一个符合条件的新数组
let arr = [1,2,3,4,5,6,7,8,9,10] let newArr = arr.filter((value,index)=>{ return value % 2 == 0; // 如果条件成立则返回 }) console.log(newArr); // [ 2, 4, 6, 8, 10 ]
六. set和map的使用
一. set本身是一个构造函数,用来生成 Set 数据结构
-
set可以接收一个数组作为参数,用来初始化
let set1 = new Set([10,20,30,40,10,20,20,30,50]) console.log(set1) // 得到的是set对象 Set { 10, 20, 30, 40, 50 }
set不能存放重复的元素
-
用数组展开和
Array.from
方法可以将 Set 结构转为数组数组展开方式
let set1 = new Set([10,20,30,40,10,20,20,30,50]) let arrNew = [...set1]; console.log(arrNew); // [ 10, 20, 30, 40, 50 ]
Array.from
方法let set1 = new Set([10,20,30,40,10,20,20,30,50]) let arrNew = Array.from(set1); console.log(arrNew); // [ 10, 20, 30, 40, 50 ]
-
利用set做数组去重
let arr = [10,10,20,20,30,40,10,10,50] let set = new Set(arr); let arrNew = [...set]; console.log(arrNew);// [ 10, 20, 30, 40, 50 ] // 上面代码可简写成一句 let arrNew1 = [...new Set(arr)]; console.log(arrNew);// [ 10, 20, 30, 40, 50 ]
-
也可以做字符串去重
let str = [...new Set('aaabbbcccddddefg')].join(''); console.log(str); // abcdefg
-
-
WeakSet
- 结构与Set 类似,也是不重复的值的集合
- 但是WeakSet 的成员只能是对象,而不能是其他类型的值
- WeakSet 中的对象都是弱引用
二. map
-
ES6提供了Map数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键
-
map可以说是’值-值‘的对应
let map = new Map(); map.set(1,2); // 数字做键 map.set(10,'hello'); map.set(true,'world'); // 关键字做键 map.set(null,'空'); console.log(map); // Map { 1 => 2, 10 => 'hello', true => 'world', null => '空' }
-
map可以接收一个数组作为参数,该数组的成员是一个个表示键值对的数组
let map = new Map([ ['name','张三'], ['age',20] ]) console.log(map); // Map { 'name' => '张三', 'age' => 20 } console.log(map.size); // 2 console.log(map.has('name')); // true console.log(map.get('name')); // 张三 map.set('name','李四'); console.log(map.get('name')); // 李四
-
对同一个键赋值多次,后面的会覆盖前面的
let map = new Map(); map.set(1,2); map.set(1,'hello'); console.log(map.get(1)); // hello
-
map的属性和方法
-
属性
size
属性:返回 Map 结构的成员总数。 -
方法
1.set(key, value): 设置键名
key
对应的键值为value
,然后返回整个 Map 结构。如果key
已经有值,则键值会被更新,否则就新生成该键。let map = new Map([ ['name','张三'], ['age',20] ]) map.set('name','李四'); console.log(map.get('name')); // 李四
2.get(key): 读取
key
对应的键值,如果找不到key
,返回undefined
。let map = new Map([ ['name','张三'], ['age',20] ]) console.log(map.get('name')); // 张三 console.log(map.get('age')); // 20
3.has(key): 返回一个布尔值,表示某个键是否在当前 Map 对象之中。
let map = new Map([ ['name','张三'], ['age',20] ]) console.log(map.has('name')); // true console.log(map.has('sex')); // false
4.delete(key): 删除某个键,返回
true
。如果删除失败,返回false
。let map = new Map([ ['name','张三'], ['age',20] ]) map.delete('name'); console.log(map.get('name')); // undefined
5.clear(): 清除所有成员,没有返回值。
let map = new Map([ ['name','张三'], ['age',20] ]) map.clear(); console.log(map); // Map {}
-
ES6转成ES5
一个网站,可以自动转换成ES5: https://www.babeljs.cn/
上一篇: ES6知识点整理class的应用
下一篇: ES6知识点整理——symbol