ECMA -> ECMAScript -> ES
标准规范
ES6: js的第6套标准规范
文章目录
一、 let
1. let底层原理
在底层自动转换为匿名函数自调用,且变量名
=>_变量名
let a = 100;
👇
(function(){
var _a = 100;
})()
接下来以var/let/const对比来讲解let的特性:
1.2 var let const三个区别
a. 变量提升
var
声明的变量存在提升, 可在声明前调用(undefined
)
let
和const
不存在变量提升,有暂时性死区,等到声明以后才能使用该变量
console.log(a) // undefined
var a = 10
console.log(b) // 报错
let b = 10
console.log(c) // 报错
const c = 10
b. 块级作用域
大括号之间的语句块就是一个块级作用域,例如:if、else、while、do-while、for…
var
无块级作用域
let
和const
有块级作用域
{
var a = 20
let b = 20
const c = 20
}
console.log(a, b, c) // 20, 报错, 报错
c. 重复声明
var
可以重复声明同一个变量
let
和const
同一个作用域下不允许重复声明同一个变量
d. 修改变量
var
和let
可以
const
声明时必须赋值,不允许重新赋值(引用地址)
总结: 能用const尽量使用const,次之let,避免使用var
二、参数增强
2.1 参数默认值(default)
形参变量有默认值可用,不至于是undefined
示例:
function fn(a, b, c=0) {
console.log(a, b, c);
}
fn(1, 2, 3);
fn(1, 2); //1, 2, 0
fn(10000);//NaN
旧js版本兼容写法
function 函数名(形参1=默认值1, ...) { 形参1 === undefined && (形参1=默认值); }
2.2 解构
将一个大的对象或数组中的个别成员提取出来单独使用.
2.2.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); // {pid:1, pname:'yaya'},
console.log(p2); // {pid:2, pname:'feifei'},
//取出数组第一个和第三个对象
var [p1, , p3] = arr;
// 0 2
console.log(p1);
console.log(p3); // {pid:3, pname:'yuanyuan'}
2.2.2 对象解构
从对象中提取出个别成员(属性或方法),单独使用
var {属性名1:变量1,属性名2:变量2}=对象
es6简写: (属性名和变量名相等)
var {属性名1,属性名2}=对象
示例:
var db = {
name: erya,
port:3306,
}
var {name:name, port:port} = db;
// ES6简写:
var {name, login} = db;
console.log(name, login); // erya, 3306
2.3 剩余参数(rest) …
ES6箭头函数中碰到参数个数不确定的情况,都要用剩余参数语法来代替arguments
(arguments箭头函数不能使用)
优点:
- 支持箭头函数
- 生成的数组是纯正的数组类型,可以使用数组所有函数
数组拓展运算符
a. 转换为参数序列
示例一:
...
在调用函数时是"打散":将数组打散为多个元素
...
在定义函数时是"收集"
var add=(...arr)=>{
return arr.reduce((x,y)=>x+y, 0);
}
const arr1=[1,2,3]
const arr2=[1,2,3,4,5]
add(...arr1) //6
add(...arr2);//15
示例二:...
+解构
function cal(name,...arr){...}
cal("eyra",1,2,3); // name: erya, arr=[1,2,3]
cal("user",1,2,3,4); // name: user, arr=[1,2,3,4]
b. 展开数组
每次只能展开一层数组
var arr = [1, [2,3,4], 5]
console.log(...arr) // 1 [2,3,4] 5
c.复制数组:
var arr = [1,2];
var arr2=arr.slice();
👇
var arr2=[..arr]
d. 合并数组
var arr1 = [1,2];
var arr2 = [3,4];
var arr3=[].concat(arr1,arr2)
👇
var arr3=[..arr1, ...arr2] // [1,2,3,4]
e. 字符串转数组
[...'erya'] // ['e', 'r', 'y', 'a']
对象拓展运算符
a. 浅克隆对象
var obj2 = {...obj1};
b.合并两个对象
var obj3=Object.assign({},obj1,obj2);
👇
var obj3={...obj1, ...obj2}
// 将obj1和obj2打散后,所有的属性,都放入第一个参数空对象中返回
三、箭头函数
3.1 简化语法规定
-
去掉匿名函数的function,小括号和大括号之间使用箭头
()=>{ }
ex:arr.sort( /*function */(a,b)=>{ return a-b; } )
-
箭头函数的函数体中只有一行代码,可以省略
{}
如果只有一行代码且是return形式,必须省略{}
和return
arr.sort( (a,b)=>{return a-b} )
↓
arr.sort( (a,b)=>a-b )
-
如果只有一个形参,可以省略()
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;
3.2 箭头函数中的this
箭头函数没有属于自己的this,它的this是捕获所在上下文的this值。
如果希望函数内的this与函数外的this保持一致就可以改为箭头函数
对象中的方法不能改为箭头函数!
ES6中为对象的方法定义提供了一种专门的不带function的简写:var 对象名={ 属性名: 属性值, 方法名(){ ... this.属性名 ... } }
既不带:function,又不要加=>。
省略了function,又不等同于箭头函数,不会影响内部的this!
3.2.1 示例
原生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
)
},
// intr:function(){简写intr() 既省略了function,但是又不等同于箭头函数,不会影响内部的this!
intr() {
this.friends.forEach(
// 箭头函数:可让函数内的this与函数外的this保持一致!
(ele)=>{
console.log(`${this.sname}的朋友是${ele}`);
}
)
}
}
erya.intr1();
erya.intr();
3.2.2 图解
①在erya对象中,intr方法有一个作用域,且’erya’调用了intr方法,所以intr的作用域中this->erya。
intr方法中还有一个回调函数,它也有一块作用域
②在回调函数作用域中this因自身无this,所以找到window.sname,window中sname找不到,所以返回undefined
解决方法一:使用bind()绑定this
.bind(this),将intr中的’this->erya’传进来
解决方法二:使用箭头函数
箭头函数相当于将回调函数的作用域推倒
3.2.3 不支持new箭头函数
箭头函数没有prototype,也没有自己的this指向,不支持使用arguments 参数,所以不能new
一个箭头函数。
new 操作符的实现步骤如下:
new运作的图解:JavaScript——this+面向对象(封装)以及new如何运作?
i. 创建一个新的空对象等待
ii.让新创建的对象自动继承构造函数的原型对象(将对象的__proto__属性指向构造函数的prototype属性)
iii. 将构造函数中的this->new刚创建的新对象
iv. 返回新对象的地址,保存到=左边的变量里。
上面的第ii、iii步,箭头函数都是没有办法执行的。
四、模板字符串
解决了字符串的拼接问题
\` 模板字符串 ${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}?
`);
五、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 |
---|---|---|---|---|---|
数字下标 | 索引数组 | √ | √ | √ | × |
数字下标 | 类数组对象 | √ | × | √ | × |
自定义下标 | 关联数组 | × | × | × | √ |
自定义下标 | 对象 | × | × | × | √ |