ECMA -> ECMAScript -> ES
标准规范
ES6: js的第6套标准规范
- 一、 let
-
- 1.1 let特点
- 1.2 let底层原理
- 块级作用域:解决全局污染
- var let const三个区别
- 二、参数增强
-
- 2.1 参数默认值(default)
- 2.2 剩余参数(rest)
- 2.3 打散数组(spread)...
-
- a.复制一个数组:
- b.合并两个数组
- c.浅克隆一个对象
- d.合并两个对象
- 三、箭头函数
-
- 3.1 简化语法规定
- 3.2 箭头函数中的this
-
- 图解
- 四、模板字符串
- 五、for of
-
-
- for of 和 for in 和 forEach()
-
- 六、解构
-
- 6.1数组解构
- 6.2 对象解构
- 6.3 参数解构
一、 let
var
- 关键字定义的变量可以在使用后声明,也就是变量可以先使用再声明。
//var a //会将第三行的var a提到最前面,提前声明变量
console.log(a); //undefined
var a = 1; //有var才提升
console.log(a); //1
1.1 let特点
- let在全局声明在window中也找不到
- 不允许提前使用let变量,也就是变量需要先声明再使用,存在块级作用域。
- 同一作用域内不允许重复声明两个同名let变量
console.log(a); //引用报错ReferenceError:
let a = 1; //let不再存在提升
console.log(a); //1
1.2 let底层原理
在底层自动转换为匿名函数自调用,且
变量名
=>
_变量名
示例:
↓
(function(){
var _a = 100;
})()
块级作用域:解决全局污染
大括号之间的语句块就是一个块级作用域,例如:if、else、while、do-while、for…
在块级作用域下,let和const声明的都是局部的,无法被块级作用域以外访问到。
{//块级作用域
var c = 3;
let d = 4;//局部变量
const e = 5;//局部常量
}
console.log(e);
var let const三个区别
- var声明的变量存在提升,在同一个作用域下可以重复声明同一个变量
- let声明的变量不存在提升,在同一个作用域下不允许重复声明同一个变量,存在块级作用域,即使在全局作用域下let声明的变量也不是全局的
- const 声明的时候必须赋值,不允许重新赋值,存在块级作用域
二、参数增强
2.1 参数默认值(default)
调用函数时,即使不传入实参值,形参变量也有默认值可用,不至于是undefined
2.定义函数时:
function 函数名(形参1=默认值1, 形参2=默认值2, ...) {
//调用函数时,给形参传了实参值,则首选用户传入的实参值。
//如果没有给形参传是实参值,则形参默认启用=右边的默认值。
}
示例:
function fn(a, b, c=0) {
console.log(a, b, c);
}
fn(10000,2000,500);
//未出现的实参就会使用默认值
fn(10000,2000);//1000,2000,0
fn(10000);//NaN
3.旧js版本兼容写法
function 函数名(形参1=默认值1, ...) {
形参1 === undefined && (形参1=默认值);
}
4.默认值只能解决最后一个形参不确定有没有的情况!
如果多个形参都不确定有没有,应该用后边学的参数解构来解决!
2.2 剩余参数(rest)
ES6箭头函数中碰到参数个数不确定的情况,都要用剩余参数语法来代替arguments(箭头函数不能使用)
只要使用arguments,都换成剩余参数语法!
1.定义函数时
var 函数名=( ...数组名 )=>{
//将来传入函数的所有实参值,都会被...收集起来,保存到...会指定的数组中。
}
...
在定义函数时的意思是收集
2.优点:
1). 支持箭头函数
2). 生成的数组是纯正的数组类型,可以使用数组家所有函数
3). 自定义数组名,比arguments简单
示例一:
//定义一个函数,求任意多个数字的和
var add=(...arr)=>{
console.log(`本次收到的arr:${arr}`);
return arr.reduce(
(捐款箱,当前值)=>捐款箱+当前值, 0
);
// return arr.reduce(
// function(捐款箱,当前值){
// return 捐款箱+当前值
// },
// 0//起始值
// )
}
console.log(add(1,2,3));//6
console.log(add(1,2,3,4,5));//15
3.
...
可以和其它形参配合使用
只获得其它形参不要的剩余参数。
实参值1,实参值2,除实参值1、2之外其余实参:
...数组名
收集的是除了前两个形参变量对应的实参值之外的剩余实参值
示例二
function cal(ename,...arr){
console.log(ename, arr);
var total=arr.reduce(
function(捐款箱,当前值){
return 捐款箱+当前值
},
0//起始值
);
console.log(`${ename}的总工资是${total}`)
}
cal("Li Lei",10000,1000,2000);
cal("Han Meimei",3000,500,1000,2000,3000);
2.3 打散数组(spread)…
只要需要多个值,但是多个值是放在数组中给的,将这个数组打散为多个元素值,依次传给函数的多个形参变量
调用函数时
...
在调用函数时是"打散":将数组打散为多个元素
...
在定义函数时是"收集"
a.复制一个数组:
var arr = [1,2];
var arr2=arr.slice();
👇
//先打散数组,将原数组中每个值放入新创建的数组中
b.合并两个数组
var arr1 = [1,2];
var arr2 = [2,4];
var arr3=[].concat(arr1,arr2)
👇
//先将两个数组打散后,将所有元素都放入新数组中
c.浅克隆一个对象
//先打散obj1对象,然后将打散后的所有属性,放入新数组中
d.合并两个对象
👇
//先将obj1和obj2打散后,所有的属性,都放入第一个参数空对象中返回
三、箭头函数
3.1 简化语法规定
1.去掉匿名函数的function,小括号和大括号之间使用箭头
()=>{ }
不等价于匿名函数
var arr = [23,9,78,6,45];
arr.sort( /*function*/(a,b)=>{
return a-b;
} )
2.箭头函数的函数体中只有一行代码,可以省略
{}
如果只有一行代码且是return形式,必须省略
{}
和
return
arr.sort( (a,b)=>{return a-b} )
↓
arr.sort( (a,b)=>a-b )
3.如果只有一个形参,可以省略()
arr.map( (elem)=>{return elem} )
//↓
arr.map( elem=>elem )
示例:用箭头函数求三个数的平均值
//方法一
var pingjun=(a,b,c)=> {
return (a+b+c)/3;
};
//方法二
var pingjun= (a,b,c)=> (a+b+c)/3;
console.log(pingjun(1,2,3));
3.2 箭头函数中的this
箭头函数可让函数内的this与函数外的this保持一致!
- 如果函数中就不包含this,或刚好希望函数内的this与外部this保持一致时,就可以改为箭头函数
-
不希望函数内的this与函数外的this保持一致时,都不能改为箭头函数。
比如: 对象中的方法就不能改为箭头函数。
ES6中为对象的方法定义提供了一种专门的不带function的简写:
var 对象名={
属性名: 属性值,
方法名(){ ... this.属性名 ... }
}
既不带:function,又不要加=>。
省略了function,又不等同于箭头函数,不会影响内部的this!
示例:
原生bind()方法和箭头函数方法将函数内的this改为函数外的this
var erya = {
sname:"erya",
friends:["yaya","yuanyuan"],
//原生写法:
intr1:function(){
// erya调用,所以this->erya
this.friends.forEach(
function(ele) {
console.log(`${this.sname}的朋友是${ele}`);
}.bind(this)//绑定intr1作用域中的this
)
},
// 箭头函数:可让函数内的this与函数外的this保持一致!
// intr:function(){简写intr() 既省略了function,但是又不等同于箭头函数,不会影响内部的this!
intr() {
this.friends.forEach(
(ele)=>{
console.log(`${this.sname}的朋友是${ele}`);
}
)
}
}
erya.intr1();
erya.intr();
图解
①在erya对象中,intr方法有一个作用域,且’erya’调用了intr方法,所以intr的作用域中this->erya。
intr方法中还有一个回调函数,它也有一块作用域
②在回调函数作用域中this因自身无this,所以找到window.sname,window中sname找不到,所以返回undefined
解决方法一:使用bind()绑定this
.bind(this),将intr中的’this->erya’传进来
解决方法二:使用箭头函数
箭头函数相当于将回调函数的作用域推倒
四、模板字符串
解决了字符串的拼接问题
\` 模板字符串 ${JS表达式} \`
反引号(`)标识,它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。
// 普通字符串
console.log(`In JavaScript '\n' is a line-feed.`)
// 多行字符串
console.log(`In JavaScript this is
not legal.`)
var name = "ERYA", time = "tomorrow";
console.log(`
Hello ${name},
how are you ${time}?
`);
练习:声明变量保存一条员工的数据,格式为对象,包含的属性有编号,姓名,性别(1/0),工资;最后打印出以下格式
var emp = {
eid: 2,
ename: 'erya',
sex: 0,
salary: 50000
};
console.log(`
编号:${emp.eid}
姓名:${emp.ename}
性别:${emp.sex ? '男' : '女'}
工资:${emp.salary.toFixed(2)}元
`);
五、for of
遍历数字下标的数组或类数组对象
a. 普通for循环:
1). 优点: 既可遍历索引数组,又可以遍历类数组对象(arguments)
2). 缺点: 没有可简化的空间
加粗样式
b. forEach:
1). 优点: 可以配合ES6的箭头函数,很简化
2). 缺点: 无法用于遍历类数组对象
只要遍历数字下标的东西,都可用
for of
代替通for循环和forEach
for(var 变量 of 索引数组/类数组对象){
//of会依次取出数组或类数组对象中每个属性值
//自动保存of前的变量中
}
缺点:
a. 无法获得下标位置i,只能获得元素值
b. 无法控制遍历的顺序或步调(不能倒序等)
for of 和 for in 和 forEach()
Column 1 | Column 2 | 普通for | forEach | for of | for in |
---|---|---|---|---|---|
数字下标 | 索引数组 | √ | √ | √ | × |
数字下标 | 类数组对象 | √ | × | √ | × |
自定义下标 | 关联数组 | × | × | × | √ |
自定义下标 | 对象 | × | × | × | √ |
六、解构
定义:
将一个大的对象或数组中的个别成员提取出来单独使用.
只要一个大的对象或数组中,我们只想用其中个别成员时,都要先将要使用的成员解构出来,再脱离开对象,单独使用该成员。
6.1数组解构
从数组中提取出个别值,单独使用
①先将等号左边等着接元素值的变量装扮成一个数组的样子
var [变量1, 变量2] = 数组
②结果:下标对下标,自动赋值
变量1 = 数组[0]
变量2 = 数组[1]
示例:
var arr = [
{pid:1, pname:'yaya'},
{pid:2, pname:'feifei'},
{pid:3, pname:'yuanyuan'}
]
// 取出数组第一个和第二个对象
var [p1,p2] = arr;
// 0 1
console.log(p1);
console.log(p2);
//取出数组第一个和第三个对象
var [p1, , p3] = arr;
// 0 2
console.log(p1);
console.log(p3);
在这里插入代码片
6.2 对象解构
从对象中提取出个别成员(属性或方法),单独使用
①先将等号左边等着接属性值的变量装扮成和右边对象一模一样的样子,再用等号赋值
var {属性名1:变量1,属性名2:变量2}=对象
只要变量名和配对的属性名相同,可只写一个,既配对又当变量!
var {属性名1,属性名2}=对象
②结果: 属性对属性
变量1=对象.属性名1 的属性值
变量2=对象.属性名2 的属性值
示例:
var db = {
host:"127.0.0.1",
port:3306,
query() {
console.log(`查询商品列表`);
},
login() {
console.log(`登录`);
}
}
// 只使用db对象的host和login
// 配对:变量 配对:变量
var {host:host, login:login} = db;
// ES6简写:
var {host, login} = db;
console.log(host);
console.log(login);
6.3 参数解构
只要任意一个实参值都可能没有,但是又要求实参值必须传给指定的形参,顺序不能乱,都可用参数解构:
步骤:
1.定义函数时:将所有形参变量装扮成一个对象结构
一旦定义函数时,采用对象解构形式,则调用函数时,并须传入一个对象结构,至少是一个{}
function 函数名({
//配对 : 接实参值
属性名1: 形参1,
属性名2: 形参2,
... : ...
}){
函数体
}
简写: 定义函数时,形参列表中,属性名和形参名起相同名字,只写一个,既配对,又当形参变量名。
function 函数名({
属性名1=默认值1,
属性名2=默认值2,
... : ...
}){
函数体
}
2.调用函数时:将所有实参值,装扮成和定义函数时形参结构一模一样的结构
函数名({
//配对
属性名1: 实参值1,
属性名2: 实参值2,
... : ...
})
示例:
// 1.将所有形参变量装扮成一个对象结构
function order({
zhushi = "香辣鸡腿堡",
xiaochi = "鸡薯条",
yinliao= "可乐"
}) {
console.log(`
您点的套餐是:
主食:${zhushi},
小吃:${xiaochi},
饮料:${yinliao}
`);
}
//2.调用函数时:将所有实参值,装扮成和定义函数时形参结构一模一样的结构
// 一个都不换,也要加上{}
order({});
order({
xiaochi:'红豆派'
});
// 全都换
order({
// 配对 实参值
zhushi:"奥尔良烤腿堡",
xiaochi:"扭扭薯条",
yinliao:"雪碧"
});