一、ES6
1.什么是ES6
ES的全称是:ECMAScript,它是ECMA国际标准化组织制定的一项脚本语言的标准规范
2015年6月:ES2015
2016年6月:ES2016
2017年6月:ES2017
2018年6月:ES2018
…
2.为什么要学习ES6
每一次标准的诞生都意味着语言的完善,功能的加强。javaScript语言本身也有一些不令人满意的地方。
- 变量提升特性增加了程序运行时的不可预测性。
- 语法过于松散,实现相同的功能,不同的人可能会写出不同的代码
3.ES6 新增的语法
3.1 let
es6中新增的用于声明变量的关键字.
let声明的变量只在所处的块级有效
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>11let</title>
</head>
<body>
<script>
//ES6中:如果一个变量用let声明,那么它只在所处的块级中有效
if(true){
let a = 10;
}
function fn(){
}
for(let i = 0; i <= 10; i++){
}
console.log(i);
console.log(a);
</script>
</body>
</html>
**注意:**使用let关键字声明的变量才具有块级作用域,使用var声明的变量不具备块级作用域特性
不存在变量提升
//不存在变量提升
console.log(a);
let a = 20;
暂时性死区
利用let声明变量会绑定这个块级作用域,不会受到外界的影响
var temp = 123;
if(true){
let temp;
temp = 'abc';
}
经典面试题
var arr = [];
for(var i = 0; i < 2; i++){
arr[i] = function(){
console.log(i);
}
}
arr[0]();
arr[1]();
关键是变量i是全局的,函数执行时候输出是全局作用域下的i的值
let arr = [];
for(let i = 0; i < 2; i++){
arr[i] = function(){
console.log(i);
}
}
arr[0]();
arr[1]();
关键点就在于每次循环都会产生一个块级作用域,每个块级作用于下的变量都是不同的,函数执行时输出的都是自己上一级(循环产生的块级作用域)下的i的值
小结
- let关键字就是用来声明变量的
- 使用let关键字声明的变量具有块级作用域
- 在一个大括号中使用let关键字声明的变量才具有块级作用域,var关键字声明的变量不具备块级作用域
- 防止循环变量变成全局变量,可以使用let声明变量
- 使用let官架子声明的变量没有变量提升
- 使用let关键字声明的变量具有暂时死区特性
3.2 const
声明常量,常量就是(内存地址)不能变化的量
具有块级作用域
if(true){
const a = 10;
}
console.log(a); //a is not defined
声明的时候必须赋值
const PI; //Missing initializer in const declaration
常量赋值后,值不能被修改
const PI = 3.14;
PI = 100; //Assignment to constant variable
小结
- const声明的变量是一个常量(值不能被修改)
- 既然是常量就不能重新再赋值,如果是基本数据类型,不能更改值。如果是复杂数据类型,不能更改地址值。
- 声明const的时候必须要给定值
3.3 let、const和var的区别
var | let | const |
---|---|---|
函数级作用域 | 块级作用域 | 块级作用域 |
变量提升 | 不存在变量提升 | 不存在变量提升 |
值可以修改 | 值可以修改 | 值不可更改 |
4.解构赋值
ES6中允许从数组中提取值,按照对一个位置,对变量赋值,对象也可以实现解构
4.1 数组解构
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>14数组解构</title>
</head>
<body>
<script>
let [a,b,c,d] = [1,2,3];
console.log(a);
console.log(b);
console.log(c);
console.log(d); //undefined
//如果解构不成功,变量的值就是undefined
</script>
</body>
</html>
4.2 对象解构
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>15.对象解构</title>
</head>
<body>
<script>
let person = {
name:'张三',
age:20,
gender:'男'
}
//对象解构 - 这种写法要求解构出来的变量名必须和属性名一致
let {name,age,gender} = person;
console.log(name);
console.log(age);
console.log(gender);
//对象解构 - 可以解构出来的变量名和属性名不一样 (myname,myage,sex都属于别名)
let {name:myname,age:myage,gender:sex} = person
console.log(myname);
console.log(myage);
console.log(sex);
</script>
</body>
</html>
小结
- 解构赋值就是把数据结构分解,然后给变量进行赋值
- 如果解构不成功,变量跟数值个数不匹配的时候,变量的值为undefined
- 数组解构用中括号包裹,对象解构用花括号包裹,多个变量之间用逗号分隔
- 利用解构赋值能够让我们方便的去取对昂中的属性和方法
5.箭头函数(⭐⭐⭐⭐⭐)
5.1 ES6中新增的定义函数的方式
() => {} //() 代表是函数 => 必须要的符号,指向哪一个代码块 {}表示函数体
const fn = () => {} //代表把一个函数赋值给了fn
5.2 大括号可省略
函数体内只有一行代码,且代码的执行结果就是返回值,可以省略大括号
//1.在箭头函数中,如果函数体内只有一句代码,
// 并且代码的执行结果就是函数的返回值,函数体大括号可以省略
// const sum = (x,y) => {
// return x + y;
// }
const sum = (x,y) => x + y;
5.2 形参括号可省略
如果形参只有一个,可以省略小括号
//2.在箭头函数中,如果形参只有一个,形参外侧的小括号也是可以省略不写
// const fn = (v) =>{
// console.log(v);
// }
const fn = v =>{
console.log(v);
}
fn('我爱中国');
5.3 箭头函数中没有this
箭头函数不绑定this关键字,箭头函数中的this,指向的是函数定义位置上下文的this
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>02箭头函数中的this</title>
</head>
<body>
<button>按钮1</button>
<div>哈哈</div>
<script>
var btn = document.querySelector('button');
var div = document.querySelector('div');
btn.onclick = function(){
console.log(this);
// div.addEventListener('click',function(){
// console.log(this); //这个时候是div
// });
//箭头函数不绑定this关键字,箭头函数中的this,指向的是函数定义位置上下文的this
div.addEventListener('click',() => {
console.log(this); //这个时候是btn
});
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>01.箭头函数</title>
</head>
<body>
<script>
//箭头函数:用来简化函数定义语法的
// const fn = () => {
// }
// fn();
//1.在箭头函数中,如果函数体内只有一句代码,
// 并且代码的执行结果就是函数的返回值,函数体大括号可以省略
// const sum = (x,y) => {
// return x + y;
// }
const sum = (x,y) => x + y;
const result = sum(10,20);
console.log(result);
//2.在箭头函数中,如果形参只有一个,形参外侧的小括号也是可以省略不写
// const fn = (v) =>{
// console.log(v);
// }
const fn = v =>{
console.log(v);
}
fn('我爱中国');
//3. 箭头函数不绑定this。箭头函数没有自己的this关键字,如果在箭头哈桑怒中使用this关键字,
// this关键字将指向箭头函数定义位置中的this
function fn2(){
console.log(this); //window
// return function(){
// console.log('返回的:' + this);
// }
return () => {
console.log(this);
}
}
const obj = {name:'张三'}
var resFn = fn2().call(obj);
resFn();
</script>
</body>
</html>
5.4 小结
- 箭头函数不绑定this,箭头函数中的this指向的是它所定义的位置,可以简单的理解为,定义箭头哈桑农户中的作用域的this指向谁,他就指向谁
- 箭头函数的有点在于解决了this执行环境中所造成的一些问题。比如:解决了匿名函数this指向的问题(匿名函数的执行环境具有全局性),包括setTimeout和setInterval使用this造成的问题。
5.5 面试题
var age = 100;
var obj = {
age: 20,
say: ()=>{
alert(this.age);
}
}
obj.say(); //100
箭头函数this指向是被声明的作用域里面,而对象没有作用域,所以箭头函数虽然在对象中被定义,但是this指向的是全局作用域。
6.剩余参数(⭐⭐⭐)
剩余参数语法允许我们将一个不定数量的参数表示为一个数组,不定参数定义方式,这种方式很方便的去声明不知道参数的情况下的一个函数。
6.1 语法
function 函数名 (first,...args){
}
6.2 剩余参数和解构
let students = ['zs','ls','ww'];
let [s1,...s2] = students;
console.log(s1); //sz
console.log(s2); //['ls','ww']
6.2 案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>04剩余参数</title>
</head>
<body>
<script>
const sum = (...args) => {
let total = 0;
//args.forEach(function(value){});
args.forEach(value => {
total += value;
});
return total;
}
console.log(sum(10,20));
console.log(sum(10,20,30));
console.log(sum(10,20,30,40,50,60));
let arr1 = ['张三','李四','王五','赵六'];
let [s1,...s2] = arr1;
console.log(s1);
console.log(s2);
</script>
</body>
</html>
7.ES6的内置对象扩展
7.1 Array的扩展方法
扩展运算符(展开语法)
扩展运算符可以将数组或对象转换为用逗号分隔的参数序列
let arr = [1,2,3]
...arr
console.log(...arr); //等同于下面的写法
console.log(1,2,3);
扩展运算符可以应用于合并数组
//方法一
let arr1 = [1,2,3]
let arr2 = [3,4,5]
let arr1 = [...arr1,...arr2]
//方法二
arr1.push(..arr2);
将类数组或可遍历对象转换成为真正的数组
let oDivs = document.getElementByTagName('div');
oDivs = [...oDivs]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>05数组扩展运算符</title>
</head>
<body>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<script>
//1.扩展运算符可以将数组拆分成以逗号分隔的参数序列
let arr = ['a','b','c'];
// ...arr; 'a','b','c'
console.log(...arr); //等同于下面的写法
console.log('a','b','c');
//2.扩展运算符应用于数组的合并
let arr1 = [1,2,3];
let arr2 = [3,4,5];
let arr3 = [...arr1,...arr2];
console.log(arr3);
//第二种合并的方式
arr1.push(...arr2);
console.log(arr1);
//3.利用扩展运算符将伪数组转换成真正的数组
var oDivs = document.getElementsByTagName('div');
console.log(oDivs);
//转换成一个真数组
var arr4 = [...oDivs]
arr4.push('a');
console.log(arr4);
</script>
</body>
</html>
7.1.2 构造方法
Array.from()
将伪数组或可遍历对象转换成为真正的数组
//定义一个集合
let arrLike = {
'0':'a',
'1':'b',
'2':'c',
length: 3
}
//转成一个真数组
let arr2 = Array.from(arrLike); //['a','b','c']
方法还可以接受第二个参数,作用类似于数组的map方法,用原来对每个元素进行处理,将处理的值放入到返回的数组
//定义一个集合
let arrLike = {
'0':1,
'1':2,
'2':3,
length: 3
}
//转成一个真数组
let arr2 = Array.from(arrLike,item => item*2); //[2,4,6]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>06Array.from方法</title>
</head>
<body>
<script>
// var arrayLike = {
// '0':'a',
// '1':'b',
// '2':'c',
// length: 3
// }
// //将伪数组或可遍历对象转换成为真正的数组
// var arr = Array.from(arrayLike);
// console.log(arr); //['a', 'b', 'c']
var arrLike = {
'0':1,
'1':2,
'2':3,
'length':3
}
//var arr = Array.from(arrLike,(item) => {return item*2});
var arr = Array.from(arrLike,item => item*2);
console.log(arr);
</script>
</body>
</html>
7.1.3 实例方法find
用于找出第一个符合条件的数组成员,如果没有找到就返回undefined
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>实例方法find</title>
</head>
<body>
<script>
let arr = [
{
id:1,
name:'张三'
},
{
id:2,
name:'李四'
}
];
//找数组里面符合条件的值,当数组中元素id等于2就查找出来
//只会匹配一个
//let target = arr.find((item,index) => { return item.id = 2;});
let target = arr.find((item,index) => item.id = 2);
console.log(target);
</script>
</body>
</html>
7.1.4 实例方法findIndex
用于找出第一个符合条件的数组成员的位置,如果没有找到返回-1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>实例方法findIndex</title>
</head>
<body>
<script>
// var arr = [
// {
// id:1,
// name:'张三'
// },
// {
// id:2,
// name:'李四'
// }
// ]
let arr = [10,20,30,50]
let index = arr.findIndex((item) => {return item > 20;});
//let index = arr.findIndex(item => item > 20);
console.log(index);
</script>
</body>
</html>
7.1.4 实例方法Includes
判断某个数组是否包含给定的值,返回布尔值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>实例方法Includes</title>
</head>
<body>
<script>
let arr = ['a','b','c','e'];
let result = arr.includes('a');
console.log(result); //true
result = arr.includes('d');
console.log(result);//false
</script>
</body>
</html>
7.2 String的扩展方法
7.2.1 字符串模板
ES6 新增的创建字符串的方式,使用反引号定义
let name = `张三`
模板字符串中可以解析变量
let name = '张三';
let sayHello = `hello,my name is ${name}`;
模板字符串可以换行
let result = {
name:'张三',
age:20,
sex:'男'
}
let html = `<div>
<span>${result.name>}</span>
<span>${result.age>}</span>
<span>${result.sex>}</span>
</div>`
在模板字符串中可以调用函数
const sayHello = function(){
return '厉害了我的国';
}
let grant = `${sayHello()}哈哈哈`
console.log(grant); //厉害了我的国哈哈哈
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>10.字符串模板</title>
</head>
<body>
<script>
let name = '张三';
let sayHello = `hello,my name is ${name}`;
console.log(sayHello);
let result = {
name:'张三',
age:20
}
let html = `
<div>
<span>姓名:${result.name}</span>
<span>年龄:${result.age}</span>
</div>
`;
console.log(html);
const fn = () => {
return '厉害了我的国';
}
let html2 = `${fn()}哈哈哈`
console.log(html2);
</script>
</body>
</html>
7.2.2 startWith() 和 endWith()
- startWith() 表示参数字符串是否在原字符串的头部,返回布尔值
- endWith() 表示值参数字符串是否在原字符串的尾部,返回布尔值
let str = 'Hello World';
str.startWith('Hello'); //true
str.endWith('World'); //true
str.endWith('d'); //true
str.endWith('x'); //false
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>11startWith() 和 endWith()</title>
</head>
<body>
<script>
let str = 'Hello ECMAScript 2024';
let r1 = str.startsWith('Hello'); //区分大小写
console.log(r1);
let r2 = str.endsWith('4');
console.log(r2)
</script>
</body>
</html>
7.2.2 repeat()
字符串重复多少次
语法:字符串.repeat(次数);
console.log('*'.repeat(10));
8.Set数据结构
ES6中提供了一个新的数据解构set,它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set本身是一个构造函数,用来生成Set数据结构
8.1 创建语法
const s = new Set();
set函数可以接受一个数组作为参数,用来初始化
const set = new Set([1,2,3,4,4,5]); //{1,2,3,4}
8.2 实例方法
- add(value):添加某个值到set,返回set结构本身
- delete(value):删除某个值,返回一个布尔值,表示删除是否成功
- has(value):返回一个布尔值,表示该值是否为Set的成员
- clear() :清除所有的成员,没有返回值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>13.set</title>
</head>
<body>
<script>
//1.创建一个空的set对象
const s1 = new Set();
console.log(s1);
console.log(s1.size); //set的长度
const s2 = new Set(['a','b','c']);
console.log(s2);
console.log(s2.size);
//set中不能有重复的元素
const s3 = new Set(['a','b','c','a']);
console.log(s3);
console.log(s3.size);
const set = new Set();
//往set中添加元素
set.add('a');
set.add('b').add('c').add('d').add('c');
//set中删除元素
const d1 = set.delete('d'); //删除成功返回true
const d2 = set.delete('d'); //删除失败返回false
console.log(d1);
console.log(d2);
//判断一个值是否是set数据结构中的成员,使用has,有就返回true,没有就返回false
const r1 = set.has('d')
console.log(r1);
//清空set数据结构中的值,clear方法
set.clear();
console.log(set);
</script>
</body>
</html>
8.3 遍历
Set结构的实例和数据一样,也拥有forEach方法,用于对每个成员执行某种操作,没有返回值
set.forEach(value => console.log(value));
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>14set结构的遍历</title>
</head>
<body>
<script>
const set = new Set(['a','b','c','d']);
//遍历
set.forEach(value =>{
console.log(value);
});
</script>
</body>
</html>
d(‘b’).add(‘c’).add(‘d’).add(‘c’);
//set中删除元素
const d1 = set.delete(‘d’); //删除成功返回true
const d2 = set.delete(‘d’); //删除失败返回false
console.log(d1);
console.log(d2);
//判断一个值是否是set数据结构中的成员,使用has,有就返回true,没有就返回false
const r1 = set.has(‘d’)
console.log(r1);
//清空set数据结构中的值,clear方法
set.clear();
console.log(set);
</script>
````
8.3 遍历
Set结构的实例和数据一样,也拥有forEach方法,用于对每个成员执行某种操作,没有返回值
set.forEach(value => console.log(value));
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>14set结构的遍历</title>
</head>
<body>
<script>
const set = new Set(['a','b','c','d']);
//遍历
set.forEach(value =>{
console.log(value);
});
</script>
</body>
</html>