ES5 ES6 ES7

ES6 语法

es5 和 es6 声明变量的方式对比

ES5中声明变量的方式: ```javascript //1.通过var声明 var num;

//2.函数方式声明 function fn(num){ return num; } fn(10); ES6中声明变量的方式: javascript //1.使用let声明 let a = 10; //2.使用const声明 const name = "小红"; ```

var、let、const 的区别

  1. 不存在变量提升
    • var 命令会发生 变量提升 现象,即变量可以在声明之前使用,值为undefined
    • let 和 const 则没有变量声明提升的功能,必须要先声明才能使用
  2. 不允许重复声明
    • var命令能重复声明,后者覆盖前者
    • let 和 const不允许在相同作用域内,重复声明同一个变量
  3. 作用域
    • var 的作用域是以函数为界限
    • let 和 const 的作用域是块作用域,块级作用域指 { } 内的范围
    • var 可以定义全局变量和局部变量,let 和 const 只能定义局部变量
    • const 的声明的常量不能被修改,但对于引用类型来说,堆内存中的值是可以被改变的。
  4. 变量作为全局属性
    • var定义的变量会作为window对象的属性,而let不会

** 常量定义的引用类型可以修改 javascript //1.使用常量定义数组 const arr = [100, 200, 300]; console.log(arr); arr[0] = "hello"; console.log(arr); //['hello', 200, 300] //2.使用常量来定义对象 const obj = { name: "Jack", age: 22, no: "001" } console.log(obj); obj.age = 100; console.log(obj); //{name: "Jack", age: 100, no: "001"}

暂时性死区 定义:块级作用域内存在let命令时,所声明的变量就“绑定”这个区域,不再受外部的影响 javascript { //let a 之前的区域成为暂时性死区,调用a 会报错 let a = "hello"; }

for循环中的作用域问题

//设置循环变量的部分是父级作用域,而循环体内部是一个单独的子作用域。 //ES6 中引用变量采用就近原则

变量的解构

```javascript 本质:模式匹配 1. 完全解构:模式完全匹配 2. 不完全解构:模式不完全匹配 - 为解构变量设置默认值,不会出现 undefined 的现象 - 解构成功时,解构变量的默认值会被覆盖 - 解构不成功时,解构变量的值为默认值

对象的解构注意: 1.对象在解构时,变量名要与属性名一致 2.对象解构的解构变量不考虑顺序 3.对象在解构时,为对象属性重命名,可以方便程序的编写。注:重命名不会更改对象的属性 4.和解构数组一样,解析对象时可以设置默认值 outLookURL:url = 111 ```

函数添加参数的默认值 ```javascript 1. 利用解构传参,参数设置默认值 //show({ name = 'lucy', age = 22 } = {})
//show([a = 0, b = 0])

  1. ES6 直接为参数添加默认值 //show(a = 0, b = 0) ```

rest参数 ```javascript

rest 参数: 接收不定参

  1. rest 参数是一种方式(形参),rest参数可以重命名为其他参数 ...a
  2. rest 参数只能作为最后一个参数 ```

es6 对于对象的扩展**

```javascript //1.对象的属性简写: 当对象的属性名和属性值(变量)名称一致,可省略赋值

//2.对象的方法简写: let name = "jack"; let age = 22; let obj = { name, age, walk: function () { console.log(this.name + " is walk"); }, say() { console.log(this.name + say); } } ```

es6 中箭头函数

ES5 中的两种函数定义方法 javascript 1. 函数式 //var fn = function(){} 2. 声明式 //function show(){}

ES6 中函数式声明方式被箭头函数( => )取代 javascript 箭头函数:使用 => 定义函数

  1. 当函数没有参数时,()不能省略
  2. 当函数只有一个参数,且函数体是一句代码,且是返回语句, 参数的()可省略、函数体 {} 可省略、return 可省略、中间使用 => 连接
  3. 若函数体只有一句,且不是return 语句, 不能省略 {}
  4. 若函数体有多条语句,不能省略 {}
  5. 若函数有多个参数,不能省略()
  6. 若函数的返回值为对象,此时不能省略return

使用箭头函数注意

  1. 箭头函数不适用于声明函数
  2. 箭头函数不适用于DOM事件
  3. 箭头函数不能作为构造函数(迭代器)
  4. 箭头函数内不能使用arguments
  5. 不能使用yield命令
箭头函数this指向
  1. 箭头函数没有this,this是父级的
  2. 定义时候绑定,就是this是继承自父执行上下文中的this
  3. ES5中的this指调用者,ES6中的this指定义时候绑定

字符串遍历

```javascript let str = "hello"; //1.for遍历 for (let i = 0; i < str.length; i++) { console.log(i, str[i]); //i 索引 数值类型 }

//2.数组->for->for in
let arr = [1, 2, 3];
for (let i in arr) {
    console.log(i, arr[i]);     //i 索引    字符串类型
}

//3.for... of
for(let i of str){
    console.log(i);     //数据
}

//4.解构
let [a, b, c, d ,e] = str;
console.log(a, b, c, d ,e);

```

ES6 新增字符串方法 ```javascript //字符串新增方法: 方法 返回值 作用 includes('str') boolean 判断字符串中包含子串 endWith('str') boolean 判断字符串以"str"结尾 startWith('str') boolean 判断字符串以"str"开头 repeat(n) 重复拼接自身 重复n次输出字符串 repeat + repeat

//补全字符串长度的方法 padStart(length, s); 字符串开头补全 endStart(length, s); 字符串末尾补全 ```

es6 模板字符串

es6的模板字符串为反引号

  • 支持换行
  • 模板中传变量${变量} ```javascript let obj = { name: 'jack', age: 20 };

console.log(名称:${obj.name},年龄:${obj.age}); //名称:jack,年龄:20 ```

es6 的Set结构

set结构 此结构中元素是唯一的,不能重复 ```javascript 使用new Set()实例化

方法:返回值是set可以连缀 add(val) 加元素 delete(val) 删元素 has(val) 判断是否包含元素 boolean clear() 删除所有数据

属性: size 元素个数

set结构的遍历: 1. for of 遍历set 2. for of 遍历keys() 3. for of 遍历values() 4. for of 遍历对象实体 entries 5. forEach遍历 set 6. 使用扩展运算符 和 解构 将set结构转为数组 javascript // for of 遍历数据 for (let i of set) { console.log(i); //1 2 5 3 }

// 遍历 keys    等于遍历set
for (let i of set.keys()) {
    console.log(i);
}
//遍历values
for (let i of set.values()) {
    console.log(i);
}
//遍历对象实体 entries
for (let i of set.entries()) {
    console.log(i[0]);
}

//解构的方式遍历对象实体
for (let [k, v] of set.entries()) {
    console.log(k, v);
}
// for  each遍历 set
set.forEach(i => {
    console.log(i);
})

```

es6 Map结构

Map 结构 由于对象的属性只能接受字符串类型,所有产生了Map结构,优化对象结构, Map的Key能为任何属性 ```c 使用new Map()实例化

方法:返回值是Map实例可以连缀 set(key,val) 加元素 get(key) 取元素 has(key) 判断是否包含元素 boolean clear() 删除所有数据

// 1.添加数据 set()
map.set('name', 'jack').set('age', 22).set(0,100);
console.log(map);
// 2.获取数据 get()
console.log(map.get(0));        //100
console.log(map.get('name'))    //jack
// 3.判断存在数据 has()
console.log(map.has(0));        //true
// 4.删除数据 delete()
map.delete(0);
console.log(map);       //Map(2) {"name" => "jack", "age" => 22}
// 5.清空数据 clear()
map.clear();
console.log(map);       //Map(0) {}

```

Map结构规则 ```javascript //1. map 支持数组作为构造函数的参数,但必须是二维数组 // let arr = [1, 2, 3, 4, 5]; //Iterator value 1 is not an entry object let arr = [['name', 'jack'], ['age', 23]]; let map = new Map(arr); console.log(map); //Map(4) {"name" => "jack", "age" => 23}

// 2.key 不能重复,val可以重复, key如果重复会将原来的值覆盖 map.set('name','tom'); map.set('hob','sing'); console.log(map); //Map(5) {"name" => "tom", "age" => 23, "hob" => "sing"} ```

Map的遍历

  • let of 遍历map
  • forEach 遍历 map
  • let of 遍历map.keys
  • let of 遍历map.values
  • let of 遍历map.entries
  • let of 遍历 map.entries + 解构 ```javascript // 1.let of 遍历map for (let i of map) { console.log(i[0], i[1]); }

    // 2.foreach 遍历 map map.forEach((v, k) => { console.log(k, v); })

    // 3.let of 遍历map.keys for (let k of map.keys()) { console.log(k, map.get(k)); }

    // 4.let of 遍历map.values for (let v of map.values()) { console.log(v); }

    // 5.let of 遍历map.entries for (let i of map.entries()) { console.log(i[0], i[1]); }

    // 6.let of 遍历 map.entries + 解构 for (let [k, v] of map.entries()) { console.log(k, v); } ```

es6 set与map类型转换

```javascript Set 和 数组 1.set -> 数组 方式1. Array.from(); 方式2. 遍历set然后push 方式3. 扩展运算符 2.数组 -> set 方式1. new Set(arr);

Map 对象 string 1.map -> 对象 -> String 方式1. forEach遍历Map -> 对象 -> JSON.stringify 2.String -> 对象 -> map 方式1. JSON.parse -> 对象 -> for...in 遍历对象 -> Map.add() ```

Set 和 数组之间 ```javascript let set = new Set(); set.add(1).add(2).add(3).add(2); // 1.Array.from(); var arr = Array.from(set); console.log(arr);

// 2.遍历set然后push var arr = []; set.forEach(i=>{ arr.push(i); }); console.log(arr);

// 3.扩展运算符 var arr = [...set]; console.log(arr); ```

map、对象和字符串之间 ```javascript let map = new Map(); map.set('name', 'jack').set('age', 22).set('tel', 151);

// 1.map -> 对象 -> String var obj = {}; map.forEach((v,k)=>{ obj[k] = v; }) console.log(obj); var str = JSON.stringify(obj); console.log(str);

// 2.String -> 对象 -> map var obj1 = JSON.parse(str); var map1 = new Map(); for(let i in obj1){ map1.set(i,obj1[i]); } console.log(map1); ```

rest 和 扩展运算符区别

rest参数,出现在函数参数位置 离散数据 -> 数组 javascript function fn(...rest) { console.log(rest); } fn(100, 110, 120); //(3) [100, 110, 120] ⚠️*注意: *... 扩展 运算符出现在非参数位置 **

```javascript let arr = [1, 2, 3, 4, 5]; console.log(...arr); //1 2 3 4 5

function fn1() { console.log(arguments); //Arguments(3) [2, 3, 4] console.log(...arguments); //2 3 4 } fn1(2,3,4); ```

  • 数组 -> 离散的数据
  • 拆分伪数组: NodeList HTMLCollection arguments...

ES6 面向对象

```javascript class 类、模板 1. 构造器:当类被实例化时,自动执行构造器 2. 每个类必须至少一个构造器,若没有,系统自动添加一个无参构造器 3. 构造函数,不能主动调用

set 和 get 设置和获取属性 1. get 不能传递参数 2. 只有当有set方法时才可以写get方法,同时出现

静态方法: 1. 类自身的方法,不用实例化即可调用 2. 不会被实例继承,直接通过类来调用

静态属性: 1. 类名.属性名 = 值;

extends 实现继承 1. 继承是单向的 2. 被继承的类属于父类,基类,也称超类 3. 静态方法可以被子类继承 4. 继承属性super()必须放在构造器第一句 5. 一个父类可以有多个子类,一个子类只有一个父类

注意: 1. 父类可调用自己的成员方法 2. 父类可以调自己的静态方法 3. 父类不能调子类的成员方法 4. 子类的实例可以调父类成员方法 5. 子类的实例不能调父类静态方法 6. 子类可以调父类静态方法 javascript class Person { static name = "Ken"; constructor(uname, uage) { this.uname = uname; this.uage = uage; }

//成员方法 walk() { console.log(${this.uname}正在奔跑!); }

// 静态方法:类自身的方法 static cry() { console.log('人生下来就会哭!'); } }

// 静态属性 Person.living = 'earth';

//学生类继承Person类 class Student extends Person { constructor(sname, sage, sno) { super(sname, sage); //此句必须在构造器第一句 this.sno = sno; } // 成员方法 study() { console.log(${this.sname}在学习呢!); }

//set 访问器 控制属性的设置 set sage(age) { this.age=age} // get 访问器,获取属性 get sage() { return this.age } } //创建类的实例 类的实例化 var stu = new Student('王飒', 23, '001'); stu.sage = 25 console.log(stu.sage); ```

JS中的异常处理

javascript try..catch try..finally try...catch..finally

ES6 Promise 解决回调地狱

promise:为了解决异步编程中的回调地狱而产生 Promise的实例需要接收一个函数作为参数 该函数又需要接收两个函数数作为参数 resolve 函数 reject 函数

promise 的三种状态 pending 进行中 fullfilled 已成功 resolved 成功 执行resolve函数 rejected 已失败 rejected 失败 执行reject函数

then方法 参数一:是resolve函数的实现 参数二:是reject函数的实现

then方法返回值的是一个新的Promise实例 ⚠️注意,不是原来那个Promise实例 若前一个回调函数返回的是一个Promise对象(即有异步操作)时 后一个回调函数,会等待该Promise对象的状态发生变化,才会被调用

promise的异常处理

  1. 建议总是使用catch方法。
  2. Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。
  3. Promise 的状态一旦改变,就永久保持该状态,不会再变了。
  4. catch方法返回的还是一个 Promise 对象
  5. catch和reject同时出现时,只执行reject

多个异步操作 javascript // 加载图片函数 function loadPic(id, src, sec) { return new Promise((resolve, reject) => { let oImg = new Image(); oImg.onload = function () { resolve(oImg); } oImg.onerror = function () { reject(`编号为${id}的任务失败`); } // oImg.src = src; setTimeout(() => { oImg.src = src; }, sec); //延迟加载函数 }) } let s1 = "远程图片"; let s2 = "远程图片"; let p1 = loadPic('001', s1, 1000); let p2 = loadPic('002', s2, 100); // Promise.all 方法 // 当所有图片都加载完在执行后续动作,有一张失败都不执行then let p = Promise.all([p1, p2]); //all返回新的promise对象 p.then(data=>{ console.log(data,'加载成功'); document.body.append(data[0],data[1]); }).catch(err=>{ console.log(err); }).finally(()=>{ console.log('不论成功与否,我都执行'); }); // Promise.race 方法 // 注: // 1.只要有一张图片加载完成,就执行then的resolve实现 // 2.如果先加载的图片有失败的情况,后续图片就不加载,直接执行catch 或 reject let p = Promise.race([p1, p2]); p.then(data => { console.log(data); //只返回最先加载成功的那个 document.body.append(data); //由于设置了延迟,所以第二个先加载完成 }).catch(err => { console.log(err); })

ES模块导入规则

容易出错的地方

  1. 页面不基于服务器运行,会出现跨域的错误

javascript origin 'null' has been blocked by CORS policy: Cross origin requests are only

  1. 使用模块化时,页面不加type = "module" 会出现语法错误 app.js:1 Uncaught SyntaxError: Unexpected token {

```javascript

```

  1. import导入模块时不添加 .js 的后缀名会报找不到module错误 GET xxx net::ERRABORTED 404 (Not Found)_

javascript import { Student } from './Student.js'; 导出方式

  • 定义时导出
  • 批量导出
  • 导出重命名(不建议)
  • 默认导出 ```javascript // 1.定义时导出 export let uname = '李四';

export function showStudentName() { console.log(uname); }

export class SomeAnimalInfo { constructor(type, age) { this.type = type; this.age = age; } showInfo() { console.log(物种:${this.type},年龄:${this.age}); } }

// 2.批量导出 const PI = 3.1415926; const DBNAME = 'Local'; ... ...

export { PI, DBNAME };

// 3.默认导出 - 工具类 export default class { static log(msg) { let now = new Date(); console.log(${now.toLocaleString()} ${msg}); }

static setCookie() {

} ... ... } ``` 导入方式

  • 导入重命名
  • 导入整个模块
  • 导入默认模块 ```javascript //1.导入重命名 as语法 import { num, showStudentName as showName } from './all.js';

// 2.导入整个模块 需要使用as重命名,接收的是一个对象 import * as cons from './const.js';

// 3.导入默认模块 需要起名,名字包含导出内容 import Tool from './tools.js'; ```

es7 语法

async await转化es5

```javascript async function asyncFN() { var getSyncFnResult = await syncFn() console.log(getSyncFnResult); }

function syncFn() { return "这是syncFn()的结果"; }

asyncFN() 转成es5后的代码: javascript function asyncGeneratorStep(gen, resolve, reject, next, _throw, key, arg) { try { var info = genkey; //相当于 步骤标点1-fn'next' var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(next, _throw); } }

function _asyncToGenerator(fn) { //其实步骤标点1-fn=function* () { // var getSyncFnResult = yield syncFn(); // console.log(getSyncFnResult); // } return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { console.log("value", value);

asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
  }
  function _throw(err) {
    asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
  }
  _next(undefined);
});

}; }

function asyncFN() { return _asyncFN.apply(this, arguments); }

function _asyncFN() { _asyncFN = _asyncToGenerator(function* () { var getSyncFnResult = yield "这是syncFn()的结果"; // var getSyncFnResult = yield syncFn(); console.log(getSyncFnResult); });

return _asyncFN.apply(this, arguments); }

// function syncFn() { // return "这是syncFn()的结果"; // }

asyncFN(); ``` image.png

参考文献

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值