一、简介
ECMAScript(简称ES6),是JavaScrit语言的下一代标准,它的目标是使JavaScript语言可以用来编写复杂的大型应用程序,成为企业级开发语言。
二、使用babel搭建环境
因为浏览器不识别ES6,所以要转换为ES5。
① 安装node (上一篇有记录方法)
② 在vscode中选择文件夹,打开终端输入
npm init -y
③ 输入
npm install --save-dev babel-cli babel-preset-es2015
④ 创建项目录,src目录用于存放编写的es6代码,dist目录用于存放由es6转化后的代码
⑤ 新建.babelrc 文件,在文件中输入
{
"presets": ["es2015"]
}
⑥ 在终端输入(根据自己创建的文件的名字)
node_modules/.bin/babel src/test.js --out-file dist/test.js
⑦ 创建index.html文件,输入
<script src="./dist/test.js"></script>
⑧ 整个目录转码(区别于第6步,某个文件转码)
node_modules/.bin/babel src --out-dir dist
⑨ 每次写完代码都转太麻烦了,可以配置package.json文件,添加一句话
("dev": "babel src -w -d dist")
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "babel src -w -d dist"
},
⑩ 用法:在终端输入
npm run dev
二、变量声明关键字let、const
let只在声明的代码块中生效(块级作用域),暂时性死区(在声明变量之前无法读取或操作这个变量),没有变量提升,无法重复声明
const 用于声明常量,只是保证里面的内存地址不变的(简单数据类型如字符串,数字,布尔类型的值,值就保存在变量指向的内容地址,而复杂数据类型的数据如对象、数组和函数,变量指向的内存地址,实际上是保存了指向实际数据的指针。所以const只能保证指针是固定的,至于指针指向的数据结构变不变就无法控制了)
const obj = {
name:"xxx"
}
// obj = {
// aaa:"aaa"
// }
obj.name = "yyy";
console.log(obj);
三、Symbol
1.symbol
确保创建的每一个对象都是独一无二的,即便名字相同。
2.symbol.for
symbol.for 这个 API 代表会在全局寻找叫做aa这个变量,如果有就会把当前这个Symbol赋值到a1变量中,如果没有就会创建Symbol再赋值
let a1 = Symbol.for("aa");
let a2 = Symbol.for("aa");
console.log(a1 === a2);
3.应用
① 如果代码:
let obj = {
a1:123,
aa:123,
a1:457
}
console.log(obj);
后面的a1把前面的覆盖了。
如果不想被覆盖,可以把外面 let a1 = Symbol.for("aa"); 作为 key 的名字。
写法是:加方括号。
let a1 = Symbol.for("aa");
let obj = {
[a1]:123,
aa:123,
a1:457
}
console.log(obj);
同样的,也可以写成
let obj2 = {}
obj2[a1] = 3;
console.log(obj2);
② 为对象赋值的另一种方式:参数1是对象的名称,参数2是key的名称,参数3是当前这个key的值
let a1 = Symbol.for("aa");
let obj = {
[a1]:123,
aa:123,
a1:457
}
Object.defineProperty(obj,a1,{value:893})
console.log(obj);
如果 a1 的写法是字符串 "a1",那对应的是 a1:457
不加" "是变量的名字,会去找变量 let a1 = Symbol.for("aa");
③ Symbol的另外一个作用,声明字符串常量,下面代码中的hahaha这个字符串就为常量
const user = Symbol("hahaha");
console.log(user);
四、解构赋值
1.简介
解构赋值针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。代码书写上言简意赅,语义明确,也方便了对象数据的读取操作。
2.实质
ES6中只要某种数据有遍历接口(数组、字符串、对象),都可以进行数组的解构赋值。
3.使用
① 如果赋值时变量的个数和值的数对应不上,多出来的变量中的值就是undefined
{
let a,b,c,d;
[a,b,c,d] = [1,2,3];
console.log(a,b,c,d);
}
② 指定默认值
{
let a, b, c;
[a,b,c = 9] = [1,2,3];
console.log(a,b,c);
}
③ ...为ES6中的扩展运算符,这样会将a赋值给1,而other会作为一个数据将剩余的值作为整个数组中的元素进行存储
{
let a, other;
[a,...other] = [1,2,3];
console.log(a,other);
}
④ 只读取第一个和第三个值,逗号只作为占位符
{
let a, b;
[a,,b] = [1,2,3];
console.log(a,b);
}
⑤ 对象解构赋值,如果当前行中的第一个字符为大括号的会报错,所以需要加上小括号
{
let a, b;
({a,b} = {a:2,b:3});
console.log(a,b);
}
⑥ 只使用属性值不使用属性名,相当于给原有对象中的属性名重新命名
{
let num,total;
({a:num,b:total} = {a:2,b:3});
console.log(num,total);
}
五、字符串的扩展方法及模板字符串
① 在 es5 中显示乱码 es6 中显示汉字
{
// es5
const str = "\u20bb7"
console.log(str);
}
{
// es6的方案:将超过两个字节的组成字符的码点放在一对达阔中里就可以正确的识别
const str = "\u{20bb7}"
console.log("es6",str);
}
② for of:传统for循环无法处理超出范围的字符的,而for of能够正确的处理,处理字符串循环时推荐使用for of进行处理
{
const str = "\u{20bb7}"
for(let i = 0; i < str.length;i++){
console.log(str[i]);
}
for(let word of str){
console.log("for-of",word);
}
}
③ 判断字符串中是否包含指定字符串,返回值是布尔值
{
let str = "123abc321";
console.log("includes",str.includes("abc"));
//表示从3角标开始查 0,1,2,a
console.log("startsWith",str.startsWith("abc",3));
// 6 之前
console.log("endsWith",str.endsWith("abc",6));
}
④ repeat() 方法返回一个新字符串,表示将原字符串重复n 次。
{
let str = "1abc23"
let str2 = str.repeat(3);
console.log(str,str2);
}
⑤ 头部补全,参数1:补全之后的字符串长度,参数2:作为补位的字符串,如果超出补全长度自动截取
{
let str = "Apple"
str = str.padStart(7,"abc");
console.log(str);
}
⑥ 模板字符串(反引号-tab按键上面那个``,可以换行,可以加入${变量}解析变量里面的值)
{
const name = "张三"
const age = 19
const str = "我叫:"+name+",今年"+age+"岁了"
console.log(str);
const str2 = `我叫${name}
我今年${age}岁了
`
console.log(str2);
}
六、数组的扩展方法
① 扩展运算符...如果使用 arr2 = arr1 这种方式的话,只是将arr1中存放的地址赋值给了arr2,这样如果arr1中的数组改变的话arr2也会跟着改变的
{
const arr1 = [1,2,3,4,5];
// let arr2 = arr1;
let arr2 = [...arr1];
arr1.push(6);
console.log(arr2);
//分割数组
const totalArr = [1,"a","b","c"];
//两个逗号,输出 b c
let[,...strArr] = totalArr;
console.log(strArr);
//给函数传参 ...arr表示数组的元素
function add (x,y) {
return x + y;
}
let arr = [4,5];
console.log(add(...arr));
}
② fill替换数组中的元素
{
const list = [1,2,3,4,5];
//将数组中的元素全部替换为3 原来的数组也发生变化了
// let list2 = list.fill(3);
let list2 = [...list].fill(3);
console.log(list,list2);
//将数组中的下标为 1 的元素到下标为 4 之前的元素中的值替换成3
//参数1:要替换后的值 参数2:开始下标 参数3:结束下标
let list3 = [...list].fill(3,1,4);
console.log(list3);
}
③ find findIndex
{
const list = [{title:'es6'},{title:'webpack',id:2},{title:'vue'},{title:'webpack',id:3}]
//find:循环遍历数组,根据条件返回对应的这条数据
//回调函数中的item代表数组中的每个元素(arr[i])
let result = list.find(function(item) {
return item.title === "webpack";
})
console.log(result);
let resultIndex = list.findIndex(function(item) {
return item.title === "webpack";
})
console.log(resultIndex);
}
④ Includes 和 indexOf
{
//Includes判断当前元素是否存在,返回为布尔类型,indexOf返回的是索引或者-1
const arr = [1,2,3,4,5,6];
let result = arr.includes(7);
let result2 = arr.indexOf(7);
console.log(result,result2);
}
⑤ flat展开数组
{
const list = [1,2,3,['2nd',4,5,6,["3nd",7,8]]];
let flatList = list.flat(2);
console.log("flat",flatList);
let flatList2 = [].concat(...list)
console.log(flatList2);
}
flat (数字可以表示多展开几层),另一种方法只能到第二层数组
七、map和reduce
① map 数据映射
把数组中的 0 ,1 映射成文字
{
// map 数据映射
const json = [{name:"张三",gender:0},{name:"李四",gender:1},{name:"小花",gender:1},{name:"小明",gender:0}]
let arr = json.map(function(item){
// return{
// name:item.name,
// 0 代表 false
// genderTxt:item.gender ? "女":"男"
// }
// item.gender = item.gender?"女":"男"
// return item
//如果原数据不再使用了,可以使用上面这种方法
let obj = {}
// 复制对象
Object.assign(obj,item);
obj.gender = obj.gender?"女":"男"
return obj
})
console.log(arr,json);
}
在工作时,后台在一些情况下返回的是编码,所以我们要转换为汉字。
② reduce
{
/*
reduce 对数组中每个元素进行一次回调
reduce(callback,initalValue)
callback里面的参数
acc:返回值(每次回调之后的返回值)
currentValue:当前进行回调的值
currentIndex:当前进行回调的值对应的索引
initalValue:是一个返回值,它是一个可选参数,如果传入值得话callback里面的参数acc的初始值就是initalValue的值,如果不传入的话acc初始值就是数组中的第一个元素
*/
const letterList = "abcadefadc";
//reduce 是数组的API 所以要把字符串转为数组
const arr = letterList.split("")
// cur:arr[i]
const result = arr.reduce(function(acc,cur){
// acc[cur]?acc[cur]++:acc[cur]=1
if(acc[cur] !== undefined){
acc[cur]++
}else{
acc[cur]=1
}
return acc
},{})
console.log(result);
}
理解 acc[cur]?acc[cur]++:acc[cur]=1
// let obj = {}
//obj 默认是空对象 有值吗?false , =1
// obj["a"]?obj["a"]++:obj["a"] = 1
// obj["a"]?obj["a"]++:obj["a"] = 1
acc 相当于下面代码中的 a
// let obj = {name:"xxx"};
// let a = "name"
// console.log(obj[a]);
③ reduce 展开多层数组
{
// 展开多层数组
const list = [1,['2nd',2,3,['3rd',4,5]],['2nd',6,7]]
const deepFlat = function(arr){
return arr.reduce(function(acc,cur){
//判断是不是数组,是数组的话展开,不是的话跟空数组拼接上
return acc.concat(Array.isArray(cur) ? deepFlat(cur) : cur)
},[])
}
let result = deepFlat(list);
console.log(result);
}
八、扩展运算符
1.es8 插件
babel 不支持 es8的语法,所以要安装插件,在终端输入
npm i babel-plugin-transform-object-rest-spread
"plugins": ["transform-object-rest-spread"] 添加到.babelrc里面的,如下:
{
"presets": ["es2015"],
"plugins": ["transform-object-rest-spread"]
}
然后重新输入
npm run dev
2.使用
{
// 对象中扩展运算符的使用
// 复制对象
const obj = {name:"tom",age:19}
let obj2 = {...obj};
console.log(obj2);
// 设置对象默认值
let obj3 = {...obj,name:'jerray'}
console.log(obj3);
// 合并对象
let initObj = {color:"red",a:{aaa:"aaa"}}
let obj4 = {...obj,...initObj}
console.log(obj4);
initObj.a.aaa="bbb"
console.log(obj4);
}
注意:简单数据类型的时候,使用扩展运算符是没问题的,但是如果扩展运算符展开对象以后,还是一个对象的话,复制的就是一个指针
{
let name = "小明"
let age = 19;
let es5Obj = {
name:name,
age:age,
say:function(){
console.log("es5");
}
}
let es6Obj = {
name,
age,
say(){
console.log("es6");
}
}
}
es6 : key value是一样的,可以只写一个,还可以省略function
{
// Object.is() 和 ===
let result = Object.is(NaN,NaN);
console.log(result,NaN === NaN);
// Object.assign() 复制对象
const person = {name:'小明',age:19,cars:{carName:"法拉利"}};
let person2 = {};
// 参数1:目标对象,参数2:来源对象
Object.assign(person2,person)
console.log(person2);
person.cars.carName = "奥托";
console.log(person2);
}
NAN跟任何数包括自己 === 都是 false
Object.is 就是true
Object.assign() 复制对象 一层对象很好用,如果两层对象的话,复制的就是指针了。
修改的话,原对象也会被修改。