变量提升
代码执行前会对变量进行提前声明,对未声明的变量会赋一个初始值Undefined。但是如果使用 let 或者 const 就不会被变量提升,代码必须要执行到 let 或者 const 的那一行才会对变量进行声明。
作用域链?
let和const不影响作用域链{
let a=123
function fn(){
console.log(a)
}
fn(); //123
}
解构赋值?
数组的解构
let a=[1,2,3,4]
let [one,two,three,four]=a
console.log(one,tow,three,four) //1,2,3,4
对象的解构
let obj={
name:'张三',
age:18,
job:function(){
console.log("工作")
}
}
let {name,age,job}=obj
console.log(name,age,job) //张三,18,function(){}
job(); //工作
属性解构用得比较少,方法解构用得比较多,比如原来调用job方法都需要 obj.job();这样 会很麻烦,
解构之后只需要 job();这样就能调用了
简化对象?
比如
let name='张三';
let age=19;
let Person={
name:name,
age:age
}
这样写比较麻烦,可以这样写
let Person={
name,
age
}
效果是一样的
箭头函数
this的指向
this是静态的 始终指向函数声明时所在作用域下的this的值function printThis(){
console.log(this.name)
}
let printThis2(){
console.log(this.name)
}
windows.name='张三';
printThis();//张三
printThis2();//张三
const nn={
name:"李四";
}
printThis.call(nn);//李四
printThis2.call(nn);//张三
可以看出,箭头函数的this是静态的,始终指向箭头函数在声明时所在作用域下的那个this
不能作为构造函数
let Person = (name,age)=>{
this.name=name;
this.age=age;
}
let a= new Person('a',17);
console.log(a);//Person is not a constructor
不能使用arguments变量
let fn=()=>{
console.log(arguments);
}
fn('abc');//arguments is not defined
箭头函数的简写
//参数简写
let add = n =>{
return n+n;
}
//花括号省略,在省略花括号的同时return语句也要省略
let add = n => n+n;
函数参数赋值初始值
functionh add(a+b+c=10){
return a+b+c;
}
let res=add(1,2)
console.log(res)//13
let res2=add(1,2,3)
console.log(res2)//6
rest参数
es5的arguments虽然能够获取传入函数的参数,但是获取到的结果却不是数组,没有办法使用数组方法
使用rest
得到的就是一个数组,可以使用数组方法对其操作
Symbol
Symbol特点(1)Symbol的值是唯一的,用来解决命名冲突的问题
(2)Symbol值不能与其他的数据类型进行运算
(3)Symbol定义的对象属性不能使用for…in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名
//创建Symbol
let Sym=Symbol('这是一个Symbol');
//Symbol比较
let Sym2=Symbol('这是一个Symbol');
console.log(Sym===Sym2)//false
let s=Symbol.for('1');
let s2=Symbol.for('1');
console.log(s===s2)//true
迭代器
ES6新添加了一种遍历命令for..of循环,Iterator接口主要供for...of消费 原生具备iterattor接口可用的数据(可以用for of遍历)Array
Arguments
Set
Map
String
TypedArray
NodeList
工作原理
(1)创建一个指针对象,指向当前数据结构的起始位置
(2)第一次调用对象的next方法,指针自动指向数据结构的第一个成员
(3)接下来继续调用next方法,指针就一直往后移动,直到指向最后一个成员
(4)每调用nex方法返回一个包含value和done属性的对象
简单的iterator用法
let arr=['a','b','c']
console.log(ierator.next()); //输出{value:'a',done:false}
console.log(ierator.next()); //输出{value:'b',done:false}
console.log(ierator.next()); //输出{value:'c',done:false}
console.log(ierator.next()); //输出{value:undefined,done:true}
如果指针指到 最后一个成员的时候再调用next(),则done的值会变为true表示循环完成
生成器Generator
简单的Generator用法
function * gen(){
console.log("Generator")
}
let it=gen();
it.next(); //Generator
配合yield使用
function * gen(){
console.log(111)
yield "a";
console.log(222)
yield "b";
console.log(333)
yield "c";
}
let it=gen();
it.next(); //111
it.next(); //222
it.next(); //333
it.next(); //undefined
//输出每次调用的结果,每次都会返回一个对象
console.log(it.next()) //{value:"a",done:false}
console.log(it.next()) //{value:"b",done:false}
console.log(it.next()) //{value:"c",done:false}
console.log(it.next()) //{value:undefined,done:false}
相当于每次调用it.next() 都会执行下一条语句
另外一种用法
function one() {
setTimeout(()=>{
console.log(111);
g.next(); //当one结束后就调用two
},1000)
}
function two(){
setTimeout(()=>{
console.log(222);
g.next(); //当two结束后就调用three
},2000)
}
function three(){
setTimeout(()=>{
console.log(333);
},3000)
}
function *gen(){
yield one();
yield two();
yield three();
}
let g=gen()
g.next();
在异步操作执行结束后就调用下一个异步操作
或者也可以写成这样
function one() {
setTimeout(()=>{
let data=111
g.next(data);
},1000)
}
function two(){
setTimeout(()=>{
let data=222
g.next(data);
},2000)
}
function three(){
setTimeout(()=>{
let data=333
g.next(data);
},3000)
}
function *gen(){
let a= yield one();
console.log(a);
let b=yield two();
console.log(b);
let c=yield three();
console.log(c);
}
let g=gen()
g.next();