ES6,可以理解为JavaScript规范
const ,let
1. 不允许重复声明
var arg1 = 'a';
arg1 = 'b';
----------------如果想定义常量
// -ES5
Object.defineProperty(window, 'arg2',{
value:'a',
writable: false
})
//也可以修改getter,setter方法
//ES6
const arg2 = 'a';
2. 块级作用域 -- 解决变量覆盖问题
if(true){
var arg1 = 'a';
}
console.log(arg1); //可以打印a
if(true){
const arg1 = 'a';
}
外面访问不到arg1
es5如何实现let
let a=10;
{
let a = 29
console.log(a) //29
}
console.log(a) // 10
--------------编译成es5---------------
var a=10;
{
var _a=29;
console.log(_a);
}
console.log(a);
3. const定义的对象
能用const,都用const,可以保证对象地址不被轻易改变
// 会被改变的对象,到底用const还是let
const obj = {
name:'',
age:'18'
}
obj.name = 'a';
// 栈,堆
const保证栈里的内容不会被改变,obj存在栈里的是指向堆的地址
-
如何对一个对象进行常量化 -- Object.freeze()
Object.freeze(obj); -
只能冻结根层
const obj = { name:'', age:'18', course: { course1: '1', course2: '2' } } function deepFreeze(obj){ Object.freeze(obj); (Object.keys(obj) || []).forEach(key => { if(typeof obj[key] === 'object){ Object.freeze(Obj[key]) } }) }
4. var定义的变量,会挂到Windows上,let/const不会
解构
- 数组的解构 - 具备Iterator接口的数据结构,都可以使用数组的解构赋值
let [x, y, z] = new Set(['a', 'b', 'c']);
- 对象的解构
- 和数组不同,数组的元素按次序排列,对象的属性没有次序,变量要和属性同名
- 数组是特殊的对象,可以对数组进行对象属性解构
arr = [1,2,3]
let { 0: first, [arr.length - 1]: last } = arr;
first:1 last:3
- 不能对 对象进行数组解构,会报错,因为对象默认不具备iterator接口
- 字符串可以数组解构,也可以对象解构
用途
- 交换变量的值
- 返回多个值
- 提取JSON对象中的数据
- 遍历map结构
解构的原理
调用遍历器方法,会返回一个迭代器对象,迭代器对象有一个next()方法,迭代器对象调用next()方法,就会返回value值
Iterator遍历器
- 为数据结构提供可以遍历访问的方法,for of循环就是使用Iterator接口
- 默认接口部署在[Symbol.iterator]属性上,一个数据结构有这个属性,就认为它是可遍历的
- Array, Set, Map, String, 函数arguments对象原生有Iterator接口
箭头函数
//传统函数
const add = (a, b) => {retrn a+ b;} //写{}必须有return
const add1 = (a,b) => a+b
箭头函数的this
箭头函数没有独立上下文,没有自身的this,取决于外面的this,写代码时就确定,而不是执行时
class Obj{
a =13;
test = () => { console.log(this.a)}
}
const obj1 = new Obj();
obj2.fn = obj1.test;
obj2.fn() // this指向的都是obj1
obj3.fn = obj1.test;
boj3.fn() //this指向的都是obj1
需要上下文的场景
-
dom操作callback的时候
const btn = document.querySelector('#btn'); btn.addEventListener('click', function(){ this.style.color = '#fff'; }) -
类操作的时候
//箭头函数无法构造类 function Obj(name, age){ this.name = name; this.age = age; }
箭头函数的参数特性 - 没有arguments
class 类(基于函数的语法糖)
传统类型对象 - function
function Course(teacher, course){
this.teacher = teacher
this.course = course
}
Course.prototype.getCourse = function(){
return ...
}
const course1 = new Course('aa', 'ES')
ES6-class
class Course{
constructor(teacher, course){ //构造函数内部的逻辑
this.teacher = teacher
this.course = course
}
getTeacher(){ //实例的方法
return ''
}
static getCourse(){} //挂在类上公用
}
class继承
class Person{
constructor(name){
this.name = name
}
printName(){
console.log(this.name)
}
}
class Student extends Person{
constructor(name, course){
super(name); // 执行父类构造函数
this.course = course
}
}
class的类型是什么
Function => Object => null
建立只读变量
class Course{
let _course = 'aa'
this.getcourse = () =>{ return _course }
}
Map
键值对的集合
const map = new Map();
map.set('1', 2);
map.set({key: '1'}, 10);
和Object区别
- object对象的key,字符串或symbol,如果用其他类型如数组作为key,也会调用toString转化为字符串
- map的key可以是任何类型
Set
数值的集合,类似数组,但元素是不重复的--可以用于数组去重
const set = new Set();
const arr = [1,2,3,4,3,2,1];
const arrnew = [...new Set(arr)]
Generator函数
- 生成器函数,会返回一个Generator对象,这个对象是可迭代的
- 生成器函数执行时可以暂停,后面从暂停处继续执行
- 生成器函数
function* funGenerator(){
yield 'a'
yieldqa
}
- 获取Generator对象
const gen = funGenerator(); 这时函数还没有执行,只是获取对象
- 调用next()方法
gen.next() { value: yield之后的值, done: true/false 是否执行完毕}
gen.next().value --'a'
gen.next().value --'b'
- for of 可以获取到yield后面的所有值
for(const ite of gen){
console.log(ite) -- 'a' 'b'
}
function* genfib(){
console.log('gen开始执行');
let a = 1;
let b = 1;
while(true){
console.log('gen即将 yield');
yield a
console.log('gen yield返回');
const t = b;
b += a;
a = t;
}
}
const gen = genfib();
for(let i=0;i<5;i++){
gen.next();
}