ES6
1.let,const,var区别
- 变量提升
- var会发生
变量提升
现象,即变量可以在声明之前使用,值为undefined - let和const没有变量提升的功能,必须先声明
- 重复声明
- var能重复声明,后者覆盖前者
- let和const不允许在相同作用域中,重复声明同一个变量
- 作用域
- var的作用域是以函数为界限
- let和const的作用域是块级作用域,块级作用域值
{}
内的范围 - var可以定义全局变量和局部变量,let和const只能定义局部变量
- const的声明的常量不能被修改,但对于引用类型来说,堆内存中的值是可以修改的,可以使用常量定义对象,对象的属性可以被修改
- 变量作为全局属性
- 定义的变量会作为window对象的属性,let不会
暂时性死区
- 如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域,假如尝试在声明前去使用这类变量,就会报错
- 暂时性死区的本质:当进入当前作用域时,let或者const声明的变量就已经存在了-它们只是不允许被获取
要想获取它们,必须等到代码执行到声明处
var a = 1
{
a = 2 //报错,因为上面就是暂时性死区
let a
}
2.for循环中的作用域问题
- 设置循环变量的部分是父级作用域,而循环体内部是一个单独的子作用域。
- ES6 中引用变量采用就近原则
3.变量解构
- 基础解构
/**ES6之前的写法(数组) */
const array = ['数组1','数组2','数组3']
let 组1 = array[0]
console.log(组1) //-> 数组1
/**ES6写法(数组) */
const [组1,组2,组3] = ['数组1','数组2','数组3']
consloe.log(组1) //->数组1
//这种写法属于“模式匹配”,按照对应的位置对变量赋值,只要等号两边相同,左边的变量就会被赋予对应的值
-
解构的源,解构赋值表达式的右边部分
-
解构的目标,解构赋值表达式的左边部分
当解构的目标和解构的源匹配模式相同时,就可以将源中的数据赋值给变量。需要注意的是:数组的解构和顺序有关,顺序的调整会改变变量的值。
/**解构其他操作 */
/**基本操作 */
let [a,b,c] = [1,2,3] ->a=1 b=2 c=3
/**嵌套操作 */
let [a,[[b],c]] = [1,[[2],3]] ->a=1 b=2 c=3
/**可忽略操作 */
let [a,,c] = [1,2,3] ->a=1 c=3
/**扩展运算符 */
let [a,...b] = [1,2,3] ->a=1 b=[2,3]
/**不完全解构 */
let [a=1,b] = [] ->a=1 b=undefined
let [a,b,c] = [1,2] ->a=1 b=2 c=undefined
/**如果解构不成功变量值未undefined */
- 对象解构
对象的解构和数组的解构有一个最大的不同,就是数组解构取决于次序,对象解构的取值取决于它的位置。而对象的属性没有次序,解构的对象变量名必须与属性key同名,才能取到正确的。对象解构允许我们使用变量的名字匹配对象的属性,将对象的属性赋给变量。
let obj = {
name : 'lsh',
age : '24'
}
let {name,age} = obj ->name:'lsh',age:'24' //正确的
let {a,b} = obj ->a:undefined,b:undefined //错误的
/**如果变量名与属性名的不一致 */
let {name:a,age:b} = obj ->a:'lsh',b:'24'
- 特殊解构赋值
/**字符串解构赋值 */
let [a,b,c,d,e] = hello -> a:'h',b:'e',c:'l',d:'l',e:'o'
/**类数组对象解构 */
let {lenght:len} = 'hello' -> len:'5'
/**函数参数解构 */
/**我们常用的函数中的参数也可以用解构赋值,形参可以重复利用数组,对象,字符串等解构的方式,将传入的参数解析并赋值给变量 */
function add([a,b]){
//讲传入的数组的值赋给a和b变量
return a+b;
}
add([1,2]) -> 3
4.rest运算符(…变量名)
在函数调用/数组构造时,将数组表达式或者String在语法层面展开;还可以在构造字面量对象时讲对象表达式按照key-value的方式展开
字面量一般指[1,2,3]或者{name:‘111’}这种简洁的构造方式,如果多层嵌套的数组和对象就无能为力了
- 使用方法
//数组
var array = [1,2,3,4]
console.log(...array) ->1,2,3,4
//对象
var obj = {name:'lsh',age:'24'}
console.log(...obj) -> {name:'lsh',age:'24'}
- 应用场景
//数组的复制
var array1 = [1,2,3,4]
var array2 = [...array1]
console.log(array2) -> 1,2,3,4
//对象的复制
var obj1 = {name:'lsh'}
var obj2 = {...obj1}
console.log(obj2) -> {name:'lsh'}
//数组的合并
var array1 = ['lsh1']
var array2 = ['lsh2']
var arrayJoin = [...array1,...array2]
console.log(arrayJoin) -> ['lsh1','lsh2']
//对象的合并
var obj1 = {name:'lsh'}
var obj2 = {age:'24'}
var objJoin = {...obj1,...obj2}
console.log(objJoin) -> {name:'lsh',age:'24'}
//字符串转数组
var arrayStr = [...'hello']
console.log(arrayStr) -> ['h','e','l','l','o']
//参数传参
function func(a,b,c){}
var array = [1,2,3]
func(...array)
5.箭头函数
ES6中允许使用 =>来定义函数。箭头函数相当于匿名函数,并简化了函数定义
- 相比普通函数,箭头函数的语法更加简洁
- 箭头函数只能用赋值写法(匿名函数)不能用声明式写法(命名函数)
- 如果参数只有一个,可以不加括号,如果没有参数或者参数多于一个就需要加括号
const func = count =>{return count+1}
- 如果函数体只有一句话,可以不加花括号
const func = (count,num) =>count+num
- 如果函数体没有括号,可以不加return,箭头函数会默认return
/**普通函数*/
function func(count){
return count+1
}
/**箭头函数 */
const func = count => count + 1
- 箭头函数中的this指向
- 如果箭头函数是被另一个函数包裹着的,那么this指向的就是包裹着的函数,如果箭头函数没被包裹,那么就是指向上下文的this(全局变量比如:vue对象)
/** 包裹在函数内的this指向,外层是object,所以this指向是object*/
let object={
fn:function(){//普通函数
this === object//true
return ()=>{
this === object//true
}
}
}
/**如果没有包裹在普通函数内,指向的是全局的this*/
let fn={
fn:()=>{
return console.log(this === vue) //true
}
}
- 箭头函数是匿名函数,不能作为构造函数(不能new对象)
- 箭头函数没有arguments(类似于数组的对象),取而代之用rest(展开对象)解决,同时没有super(调用父类的属性和方法)和new.targer(检测使用new运算符调用了函数或构造函数)
- 注意事项:
- 箭头函数不适用dom事件
- 箭头函数不适用声明函数
- 箭头函数不能作为构造函数
- 箭头函数不能使用arguments
- 不能使用yield
6.循环遍历
- for循环遍历,效率高(使用let会更快点)
let str = 'hellow' for(let i = 0 ; i < str.length ; i++){ console.log(i,str[i]) //i->索引,str[i]值,输出:(0,'h') }
- for in (遍历对象用,效率低)
let obj = {name:'lsh',birthday:'1999-12-05'} for(i in obj){ console.log(i,obj.i) //i->对象的key,obj.i 对象的值,输出:(name,'lsh') }
- for of (ES6新,遍历数组用,能直接拿数组的值)
let array = [1,2,3,4,5] for(i of array){ console.log(i) //i直接循环数组的值(value)输出:(1) }
7.字符串新增方法
includes方法:includes方法可以判断数组或字符串中是否包含某个元素。*最常用
const arr = [1, 2, 3];console.log(arr.includes(2));
const str = 'Hello, world!';
console.log(str.includes('world'));
true
startsWith() 和 endsWith(): 检查字符串是否以特定字符串开始或结束。
let str = "Hello, world!";
console.log(str.startsWith("Hello")); // 输出: true
console.log(str.endsWith("world!")); // 输出: true
repeat(): 返回一个新字符串,表示将原始字符串重复n次。
let str = "abc";
console.log(str.repeat(2)); // 输出: "abcabc"
padStart() 和 padEnd(): 用于添加填充字符串以达到指定长度。
let str = "abc";
console.log(str.padStart(5, "12")); // 输出: "12abc"
console.log(str.padEnd(5, "12")); // 输出: "abc12"
trimStart() 和 trimEnd(): 去除字符串开头和结尾的空白字符。
let str = " Hello, world! ";
console.log(str.trimStart()); // 输出: "Hello, world! "
console.log(str.trimEnd()); // 输出: " Hello, world!"
matchAll(): 执行正则表达式全局搜索,并返回所有匹配结果的迭代器。
const str = "Hello, world!";
for (const match of str.matchAll(/o/g)) {
console.log(match); // 输出: ["o", index: 7, input: "Hello, world!"]
}
8.扩展的对象字面量:扩展的对象字面量可以更方便地定义对象。
const a = 1, b = 2;
const obj = { a, b };
9.Set和Map:Set和Map可以更方便地处理集合和键值对,使得数据结构更加丰富和易用。
可以用来存储唯一值和键值对
let mySet = new Set([1, 2, 3, 4, 2, 3]);
console.log([...mySet]); // [1, 2, 3, 4]
let myMap = new Map([['a', 1], ['b', 2]]);
console.log(myMap.get('a')); // 1
10.Promise
Promise可以更好地处理异步操作,避免了回调地狱的问题
比较全的文章:前后端交互系列之promise详解
https://blog.csdn.net/zxdznyy/article/details/129939306
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Hello, Promise!");
}, 1000);
});
promise.then(value => console.log(value));
Promise.all方法:Promise.all方法可以同时执行多个Promise对象,并在所有Promise对象都执行完毕后返回结果。
Promise.all([fetchData1(), fetchData2()]).then(
results => console.log(results)
).catch(error => console.log(error));
11.模板字符串
模板字符串可以更简洁何方便的拼接字符串,不用之前’‘+’'这种拼接方法了
<img :src="`aaa/${bbb}`.png">
12.模块化:ES6引入了模块化的概念,可以更好地组织和管理代码,避免了全局变量的污染。
export function sum(a, b) {
return a + b;
}
import {sum} from './math.js';
console.log(sum(1, 2));