ES6知识点梳理
什么是ES6
ES6 ECMAScript 第六版,全称 ECMAScript 6.0
ECMAScript 是JavaScript的一套标准化设置
变量
作用域
let和const 命令是ES6新增的语法
作用 : 是用来声明变量和var的作用一样
概念:在ES6中,凡是{}包裹的代码都是块级作用域,凡是在块级作用域中用let const声明的变量都在有一个暂时性死区。
{
let a=20;
}
console.log(a);//报错
let注意点
-
不存在变量提升,未声明直接报错
console.log(a); //ReferenceError: a is not defined let a = 3;
-
在同一作用域内,不能重复声明
let a = 12; let b = 20; console.log(a); //Identifier 'a' has already been declared //它是变量可以修改 let a = 5; a = 10;
-
for循环具有两个作用域,外面的变量个里面的变量互不干扰
let的作用
-
作用域问题
通常情况下 如果我们需要一个变量在一个规定的作用域内起作用 那么我们就需要使用function关键字搭建一个局部作用域
function(){ var a = 1; }()) console.log(a);
但是在ES6的情况下 引入了let 只要尊在{} 就可以形成一个款及作用域 不管是if结构 还是for循环结构 只要有{}存在,即形成了块级作用域
{ let b=10; } console.log(b);
-
var会变量提升,let不存在变量提升
console.log(a); //ReferenceError: a is not defined
let a = "《千与千寻》";
console.log(b); //undefined
var b = "《宫崎骏》";
解构
什么是解构?
在ES6中 按照一定的模式 从数组中提取数 对对应的变量进行赋值的操作 就叫做解构赋值
本质上讲 解构赋值 就是模式匹配
解构赋值
var [a,b,c] = [2,3,4];
console.log(a,b,c);//2,3,4
-
如果想要解构赋值成功 那么就必须保证两边的值完全一样
var [a,b,c] = [2,{name : "张三"},{age : 18}] console.log(a,b,c);//2,{name : "张三"},{age : 18}
-
如果解构不成功 那么变量的值就等于undefined
let [a] = []; console.log(a); //undefined 像var声明之后没有赋值 let [a,b] = [12]; console.log(a,b);//12 undefined 数值不够
-
不完全解构的情况下 也可以进行解构赋值 只是后面放数值的数组都有很多数字
不完全解构 : 指的是等号左右两边模式完全一样 但是只匹配到右边的一部分数据
let [a,b]=[12,23,34]; console.log(a,b);//12,23
-
如果等号右边不是数组 那么就会报错 因为模式一样
let [a] = 23; console.log(a);//报错 let [a] = {}; console.log(a); //{}is not iterable 因为{}不可以使用下标进行迭代
注意点
-
解构赋值是允许设置默认值的 但是 如果要启用默认值 那么这个变量的值就必须严格等于undefined
let [a,b] = [1,2] consloe.log(a,b); // 1,2 let [c,d = "abc"] = [1]; consloe.log(c,d);//1,"abc" let [a,b = "123"] = [1,undefin]; consloe.log(a,b); //1,"123"
-
如果设置的默认是一个表达式 那么这个表达式只是在需要启用默认值的时候才会运算
-
默认值可以使用其他变量 但是前提是赋值的这个变量必须是提前声明过的
let a= 3; let [b=a] = []; console.log(b);//3 let [c="张三",d=c] = []; console.log(c,d); //"张三""张三"
扩展运算符(…)
扩展运算符的作用
-
数组合并 这里不管是concat方法 还是扩展运算符 都是浅拷贝
如果修改了原数组的指向 就会同步反应到新数组 就是浅拷贝
var arr1=[10,20,30]; var arr2=[40,50,60]; var newArr = arr1.concat(arr2); console.log(newArr); //[10, 20, 30, 40, 50, 60] var newArr1 = [...arr1,...arr2]; console.log(newArr1);//[10, 20, 30, 40, 50, 60] // 这里证明了合并后的数组和合并前的数组指向同一片内存空间 所以证明了都是浅拷贝 console.log(newArr[0] === arr1[0]); //true console.log(newArr1[0] === arr1[0]); //true
-
数组拷贝
var arr = [1,[3,[12,15,[15,18]]],{name : "丽丽"}]; var arrSp = [...arr]; console.log(arrSp);
-
与结构赋值相结合
(1)与解构赋值相结合 给变量和数组赋值
如果是普通变量 那么就按照模式赋值 如果使用了扩展运算符 那么就是后面的值一次放入数组
var [s, ...t] = [1, 2, 3, 4, 5]; console.log(s, t); //1 ,[2,3,4,5]
如果等号右边是空数组 那么仅仅是声明 变量就是undefined 数组就是[]
var [a, ...b] = []; //undefined []
(2) 如果将扩展运算符用于数组赋值 只能放在参数的最后一位 否则就会报错
let [a, ...b, c] = [1,2,3,2,9]; let [...b, a ,c] = [1,2,3,2,9]; console.log(a,b,c); //Rest element must be last element
(3) 扩展运算符可以将字符串转换成正真的数组
console.log([..."hrllo"]); //["h", "r", "l", "l", "o"]
(4) 只有函数调用时 扩展运算符才可以放在圆括号里面 否则这种写法就直接报错
(...arr1); //报错 console.log((...arr1)); // 报错
对象的扩展
-
属性和方法的简介表示方法
ES6在{}允许直接写入变量名,解析的时候 变量名作为属性名 变量值作为属性值
如果给对象写入方法 那么可以省略function
var obj = { name, age, study(){ console.log("好好学习 天天向上"); } } console.log(obj); obj.study();
-
super关键字
super关键字 指的是指向与当前对象的原型对象
注意点:
- super关键字只能在对象的方法中使用 在其他地方使用 就会报错
const proto = {
title :'原型对象'
sayTitle(){
console.log(this.title);
}
};
const obj = {
title : '对象',
sayPrototypeTitle(){
super.sayTitle();
}
}
Object.setPrototypeOf(obj,proto);obj.sayPrototypeTitle();// 结果:// 原型对象
- super关键字目前只能在对象方法的简写方式里面取用 常规写法的方法会报错
//报错,因为super不能应用在方法之外。
var obj = {
protoTitle : super.foo
}
对象新增方法
-
Object.is() 这个方法和js的严格判断(===)用法基本一致 只是对于-0和+0 以及NaN的判断上做了改善
console.log(Object.is(-0,+0)) //false console.log(Object.is(NaN,NaN));//true
-
Object.assign() 是用来合并对象的
参数1 : 目标对象 参数2… : 需要合并的对象
var mingzi = {"name": "孙艺珍" }; var age = { "age": 20 }; var sex = { "sex": "女" }; var newObj = Object.assign(mingzi, age, sex); console.log(newObj);//{name:"孙艺珍",age:20,sex:"女"}
-
返回值是传入的第一个目标对象,会把所有的对象合并上去的时候 在返回
-
第一个参数必须是对象 如果不是对象 就会把它转换成对象
-
如果是undefined 或者null 没办法转换成对象 name就会报错
var star = Object.assign("", mingzi, age, sex); var star = Object.assign("", mingzi, age, sex); // var star = Object.assign(undefined, name, age, sex); // var star = Object.assign(null, name, age, sex); console.log(star); console.log(star === name); console.log(star === age); console.log(star === sex);
-
如果在需要合并的多个对象里面 有同名的属性 那么后面的属性就会对前面的进行覆盖
var mingzi = {"name": "孙艺珍" }; var age = {"name": "孙艺珍", "age": 20 }; var sex = { "age": 20,"sex": "女" }; var newObj = Object.assign(mingzi, age, sex); console.log(newObj);
-
如果undefined和null不是第一个参数 那么就不会报错 第一个参数返回
var objAssign = Object.assign(age, undefined); var objAssign = Object.assign(age, null); var objAssign = Object.assign(age, {}); console.log(objAssign); //{age : 20}
-
assign方法是浅拷贝 不是深拷贝
var objAssign = Object.assign({}, age); console.log(objAssign === age); var a = { b: { c: 3 } } var s = Object.assign({}, a); a.b.c = 9; console.log(s.b.c); console.log(a.b.c);
-
class关键字的基本使用
-
class就是一个语法糖 本质就是一个函数 就是使用ES5里面的函数封装的
-
在类里面去定义方法的时候 可以省略function
console.log(typeof Person); // function
类使用的注意点
-
类是不可枚举的
for(var key in Person) { console.log(key); }
-
类的用法很let和const一样 都有暂时性死区 必须先定义 再使用
-
类里面的方法不能做为构造函数来使用
var s1 = new p2.toString(); console.log(s1);
-
类(Person)使用的时候 必须配合new关键字进行使用 否则就会报错
Person(); // 报错
模板字符串
ES5之前拼接的字符串
-
拼接太麻烦 需要多次分割 不便于维护
-
所有拼接的字符串只能一行 显示 太长
var stu = { name: "lisa", age: 12, place: "湖北武汉", grade: 6 } document.querySelector("p").innerHTML = "我叫" + stu.name + ",我今年" + stu.age + "岁了,我住在" + stu.place + ",今天上" + stu.grade + "年级"
模板字符串 所有的内容写在反引号(``)里面 然后变量放在${}里面
document.querySelector("p").innerHTML = `我
叫${stu.name},我今年 ${stu.age} 岁了,
我住在${stu.place}`;
在${}可以放入任意的js表达式 可以进行运算
function age(name) {
return num - 1;
}
document.querySelector("p").innerHTML = `我
叫${stu.name},我今年 ${age(stu.age)} 岁了,我上${stu.grade -1}年级了,
我住在${stu.place}`;
模板引擎
页面渲染使用字符串拼接 会存在问题 :字符的守恒性 字符串拼接的时候容易出错
模板引擎不用拼接字符串 直接使用 静态页面里面的html里面的结构生成模板 需要渲染的时候直接调用
模板引擎的实现方式有很多,最简单的是“置换型”模板引擎,这类模板引擎只是将指定模板内容(字符串)中的特定标记(子字符串)替换一下便生成了最终需要的业务数据(比如网页)。
使用步骤
-
导入模板引擎
<script src="./template-web.js"></script>
-
准备一个模板
-
准备模板必须要是用script 模板引擎规定的只能使用script
-
必须要给他一个id 在调用方法的时候使用
-
必须要有type属性 而且type属性绝对绝对不能使text/javascript
-
调用方法 生成html结构
<script type="text/html" id="tpl"> <h1>自我介绍</h1> <p>动漫<%= name %>, 作者<%= author %> </p> </script> <script> var habby = { name: "千与千寻", author:"宫崎骏" } var html = template("tpl", habby); </script>
注意点
- 挖坑的时候 一定要注意 坑的名字一定要和对象的属性名一直
- type的值只要不是text/javascript 但是建议使用text/html 因为其他的没办法识别标签
- <%= %> 必须是一个完整的整体 不能加空格 或者其他的符号
-
模板引擎的内部循环
<script src="./template-web.js"></script>
<script type="text/html" id="tpl">
<%for(var i = 0; i < list.length; i++) { %>
<h1>作品</h1>
<p>动漫<%= name %>, 作者<%= author %> </p>
<% } %>
</script>
<script>
var arr = [
{
name: "千与千寻",
author:"宫崎骏"
},
{
name: "哈儿的移动城堡",
author:"宫崎骏"
},
{
name: "龙猫",
author:"宫崎骏"
},
{
name: "悬崖上的金鱼姬",
author:"宫崎骏"
}
]
var html = "";
html += template("tpl", {list : arr});
console.log(html);
document.body.innerHTML = html;
</script>
模板引擎的应用
点击按钮后,数据添加到表格里
<body>
<input type="button" value="加载数据" id="load">
<table>
<thead>
<tr>
<th>序号</th>
<th>姓名</th>
<th>年龄</th>
<th>成绩</th>
</tr>
</thead>
<tbody id="tb">
</tbody>
</table>
</body>
<script src="./template-web.js"></script>
<script>
var arr = [
{ Id: 0, name: "张三", age: 18, score: 68 },
{ Id: 1, name: "王亚", age: 28, score: 55 },
{ Id: 2, name: "李辉", age: 16, score: 70 },
{ Id: 3, name: "秦虹", age: 18, score: 50 },
{ Id: 4, name: "海庆", age: 19, score: 76 },
{ Id: 5, name: "蛋娃", age: 14, score: 27 },
]
var html = "";
// html += template("tpl", {list : arr});
// console.log(html);
var load = document.getElementById("load");
var tb = document.getElementById("tb");
// load.onclick = function(){
// tb.innerHTML = html;
// }
load.onclick = function(){
for(var i = 0; i<arr.length; i++){
html += '</tr>'
for(const key in arr[i]){
html += '<td>' + arr[i][key] + '</td>'
}
html+='</tr>'
}
tb.innerHTML = html;
}
</script>
字符串里新增API
-
includes() 检测字符串或者数组中是否包含某一个子字符串或者元素
返回值 : 布尔类型
参数1 : 需要查询的目标字符串 参数2 : 就是开始查询的索引(如果不写 默认从0开始)
indexOf 和 includes的区别
(1)返回值 indexOf方法 返回找到的第一个子字符串位置为索引 includes 找到了就返回true 没有就返回false
var str = "千与千寻、哈尔的移动城堡、龙猫"; console.log(str.indexOf("千寻"));//2 console.log(str.indexOf("千寻", 3));//-1 console.log(str.indexOf("无脸男"));//-1 console.log(str.includes("城堡",3));//true console.log(str.includes("龙猫",1));
(2)如果数组里面包含NaN 但是我们又正好需要差数组里面有没有NaN 那么indexOf就不能用 就只能使用includes
var arr1 = [2,3,4,5,6,NaN]; console.log(arr1.indexOf(NaN)); //-1 console.log(arr1.includes(NaN)); // true
-
startsWith() endsWith() 判断是否以某一个字符串开头 或结尾
var sayHi = "悬崖上的金鱼姬!"; console.log(sayHi.startsWith("悬崖"));//true console.log(sayHi.endsWith("!"));//true
第二个参数:
startsWith :第二个参数 表示从索引为几的字符串开始找
endsWith :第二个参数 表示是从索引为n之前的元素里面去找(不算自身的)
console.log(sayHi.startsWith("悬崖", 3)); //false console.log(sayHi.endsWith("!" ,11)); //true console.log(sayHi.endsWith("!" ,16)); //true
字符串标记
标签模板 他本质上不是模板 而是函数的另外的一种调用形式
其实我们所说的标签 其实就是我们事先封装好的函数 他的参数就是他后面接的字符串 以 作 为 分 隔 符 , 固 定 的 字 符 串 方 静 数 组 里 面 然 后 {}作为分隔符,固定的字符串 方静数组里面 然后 作为分隔符,固定的字符串方静数组里面然后{}里面的变量一次作为后面的参数
标记模板(函数)的参数:
参数1 :被插入的变量分割成字符串数组
参数2 …:都是被插入的变量
var name = "千与千寻";
var author="宫崎骏";
var str = `${author}是我最喜欢的动漫家,代表作有${name}`