ES6-ES11 学习笔记
let,常用于 for 循环
1. 变量不能重复声明;
2. 块级作用域 { };(其他作用域还有全局,函数,eval)
3. 不存在变量提升;(变量提升:在声明之前使用变量)
4. 不影响作用域链。
const,常量
1. 一定要赋初始值;
2. 一般常量使用大写;
3. 块级作用域;
4. 常量的值不能修改;
5. 对于数组和对象的元素修改,不算做对常量的修改,不会报错。
模版字符串【``】,相当于 C# 的 @"" 和 $""。
对象简化,ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。
let name = '字符串'; let change = function () { console.log('字符串'); } const school = { name, change, //声明一个函数 improve () { console.log('字符串'); } } 对象简化
解构赋值,允许按照一定模式从数组和对象中提取值,对变量进行赋值。
const zhao = { name: '赵本山', age: '不详', xiaopin: function () { console.log("我可以演小品"); } }; let { name, age, xiaopin } = zhao;
箭头函数,ES6 允许使用箭头 => 定义函数
//普通写法 let fn = function (n) { return n * n; } //箭头函数写法 let fn1 = (n) => { return n * n; } //当形参有且只有一个的时候 let fn2 = n => { return n * n; } //当代码体只有一条语句的时候 let fn3 = n => n * n; //使用案例1 setTimeout(() => { console.log("字符串"); }, 2000); //使用案例2 const arr = [1, 6, 8, 5, 11, 34]; const result = arr.filter(item => item % 2 === 0); console.log(result.join(','));
1. this 是静态的。this 始终指向函数声明时所在作用域下的 this 的值;(扩充:JavaScript call() 方法)
2. 不能作为构造函数实例化对象;
3. 不能使用 arguments 变量;
4. 箭头函数适合与 this 无关的回调,如定时器、数组的方法回调;
不适合与 this 有关的回调。如事件回调、对象的方法。
(arguments:实参对象,解决 js 函数不可以重载的问题。ES6 用 rest 参数【...args】代替使用)
(数组过滤:JavaScript Array filter() 方法)
扩展运算符,【...】
//1. 可以将数组转换为参数序列 function add (x, y) { return x + y; } const array0 = [4, 6]; console.log(add(...array0)); //2.可以复制数组 const array1 = ['E', 'G', 'M']; const array2 = [...array1]; console.log(array2); //3.可以合并数组 const array3 = ['A', 'B']; const array4 = ['C', 'D']; // 方式一(原来的方式) const array5 = array3.concat(array4); console.log(array5); // 方式二 const array6 = [...array3, ...array4]; console.log(array6); //在ES6中只针对数组,ES9中扩展到了对象,rest参数同理 const skill1 = { q: '天音波' } const skill2 = { w: '金钟罩' } const skill3 = { e: '天雷破' } const skill4 = { r: '猛龙摆尾' } const mangseng = { ...skill1, ...skill2, ...skill3, ...skill4 }; console.log(mangseng)
Symbol,JS语言的第七种数据类型,表示独一无二的值
1. Symbol 值是唯一的,用来解决命名冲突问题
2. Symbol 值不能进行运算
//Symbol.prototype.description:获取 Symbol 字符串描述(ES10功能) let s = Symbol('尚硅谷'); console.log(s.description); // 数据类型速记: u are so nb // u undefined // s string symbol // o object // n null number // b boolean
迭代器 Iterator 是一种接口,任何数据结构只要部署了 Iterator 接口,就可以完成遍历操作。
原生具备 Iterator 接口的类型:Array、Arguments、Set、Map、String、TypedArray、NodeList…
ES6 创造了一种新的遍历命令 for...of 循环,和 for in 的区别:一个获取键值,一个获取键名。
//声明一个对象 const banji = { name: "终极一班", stus: ['xiaoming', 'xiaoning', 'xiaotian', 'knight'], [Symbol.iterator] () { //索引变量 let index = 0; let _this = this; return { next: function () { if (index < _this.stus.length) { const result = { value: _this.stus[index], done: false } //下标自增 index++; //返回结果 return result; } else { return { value: undefined, done: true }; } } }; } } //遍历这个对象 for (let v of banji) { console.log(v); //输出xiaoming xiaoning xiaotian knight } Iterator
类似链表:
a) 创建一个指针对象,指向当前数据结构的起始位置
b) 第一次调用对象的next方法,指针自动指向数据结构的第一个成员
c) 接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员
d) 每调用next方法返回一个包含value和 done属性的对象
生成器,一个特殊的函数,ES6 提供的一种异步编程(文件操作、网络操作、数据库操作等带来的回调地狱)的解决方案。
//yield,函数代码的分隔符 function* gen (arg) { console.log(arg); let one = yield 111; console.log(one); let two = yield 222; console.log(two); let three = yield 333; console.log(three); } //执行获取迭代器对象 let iterator = gen('AAA '); console.log(iterator.next()); //next方法可以传入实参 console.log(iterator.next('BBB')); console.log(iterator.next('CCC')); console.log(iterator.next('DDD'));
//回调地狱 // setTimeout(() => { // console.log(111); // setTimeout(() => { // console.log(222); // setTimeout(() => { // console.log(333); // }, 3000); // }, 2000); // }, 1000); function one () { setTimeout(() => { console.log(111); iterator.next(); }, 1000) } function two () { setTimeout(() => { console.log(222); iterator.next(); }, 2000) } function three () { setTimeout(() => { console.log(333); iterator.next(); }, 3000) } function* gen () { yield one(); yield two(); yield three(); }
//模拟获取 用户数据、订单数据、商品数据(没懂) function getUsers () { setTimeout(() => { let data = '用户数据'; //调用 next 方法,并且将数据传入 iterator.next(data); }, 1000) } function getOrders () { setTimeout(() => { let data = '订单数据'; iterator.next(data); }, 1000) } function getGoods () { setTimeout(() => { let data = '商品数据'; iterator.next(data); }, 1000) } function* gen () { let users = yield getUsers(); let orders = yield getOrders(); let goods = yield getGoods(); } //调用生成器函数 let iterator = gen(); iterator.next();
Promise,ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
//创建promise对象 const p = new Promise((resolve, reject) => { setTimeout(() => { //resolve('用户数据'); //正确时返回 reject('出错啦'); //错误时返回 }, 1000) }) //调用then方法 p.then(value => { console.log(value); }, reason => { console.warn(reason); })
//1. 引入fs模块 const fs = require('fs'); //2. 调用方法读取文件(原来的方式) // fs.readFile('./为学.md', (err, data) => { // //如果失败,则抛出错误 // if (err) throw err; // //如果没有出错,则输出内容 // console.log(data.toString()); // }) //3. 使用Promise封装 const p = new Promise(function (resolve, reject) { fs.readFile("./为学.mda", (err, data => { //判断如果失败 if (err) reject(err); //如果成功 resolve(data); })) }) p.then(function (value) { console.log(value.toString()); }, function (reason) { console.log(reason); });
//1. 引入fs模块 const fs = require('fs'); //2. 调用方法读取文件(原来的方式) // fs.readFile('./为学.md', (err, data1) => { // fs.readFile('./插秧诗.md', (err, data2) => { // fs.readFile('./观书有感.md', (err, data3) => { // let result = data1 + '\r\n' + data2 + '\r\n' + data3; // console.log(result); // }) // }) // }) //3. 使用Promise实现 const p = new Promise(function (resolve, reject) { fs.readFile("./为学.mda", (err, data) => { resolve(data); }) }) p.then(value => { return new Promise((resolve, reject) => { fs.readFile("./插秧诗.mda", (err, data) => { resolve([value, data]); }); }) }).then(value => { return new Promise((resolve, reject) => { fs.readFile("./观书有感.mda", (err, data) => { //压入 value.push(data); resolve(value); }); }) }).then(value => { console.log(value.join('\r\n')); });
+ 实例:Promise 封装 Ajax 请求
Set 集合,ES6 提供的新的数据结构,类似于数组,但成员的值都是唯一的。
.size 获取元素个数;.add 添加新的元素;.delete 删除元素;.has 检查元素是否存在;.clear 清空;
let arr = [1, 2, 3, 4, 5, 4, 3, 2, 1]; //1. 数组去重 let result = [...new Set(arr)]; console.log(result); //[1, 2, 3, 4, 5] //2. 交集 let arr2 = [4, 5, 6, 5, 6]; let result2 = result.filter(item => { //老方法 let s2 = new Set(arr2); if (s2.has(item)) { return true; } else { return false; } }); console.log(result2); //[4, 5] let result3 = result.filter(item => new Set(arr2).has(item)); //新方法 console.log(result3); //[4, 5] //3. 并集 let union = [...new Set([...arr, ...arr2])]; console.log(union); //[1, 2, 3, 4, 5, 6] //4. 差集 let diff = result.filter(item => !(new Set(arr2).has(item))); console.log(diff); //[1, 2, 3]
Map,ES6 提供的数据结构,类似于对象,键值对集合。
let m = new Map(); m.set('name', '小王'); //添加元素 m.set('doing', function () { console.log("去吃饭!"); }); //键不限于字符串,各种类型的值(包括对象)都可以当做键。 let exam = { subject: "数学", source: 98 } m.set(exam, ['帽子', 'T恤', '裤子']) console.log("size:" + m.size); //size console.log(m.get('name')); //获取 console.log(m.get(exam)); m.delete('doing'); //删除 for (let v of m) { console.log(v) } m.clear(); //清空
Class 类,通过 class 关键字,可以定义类。
其实就是一个语法糖,让对象原型的写法更加清晰、更像面向对象编程的语法而已。
function Phone (brand, price) { this.brand = brand this.price = price } //添加方法 Phone.prototype.call = function () { console.log("我可以打电话!") } //通过构造函数实例化对象 let NOKIA = new Phone('诺基亚', 999) NOKIA.call() console.log(NOKIA) // ES5 构造函数继承↓ function SmartPhone (brand, price, color, size) { Phone.call(this, brand, price) this.color = color this.size = size } //设置子级构造函数的原型 SmartPhone.prototype = new Phone SmartPhone.prototype.construtor = SmartPhone //声明子类的方法 SmartPhone.prototype.photo = function () { console.log("我可以拍照!") } let Realme = new SmartPhone('真我', 2499, '黑色', '5.5inch') Realme.call() Realme.photo() console.log(Realme)
class Phone { constructor(brand, price) { this.brand = brand this.price = price } call () { console.log("我可以打电话!") } } let Jinli = new Phone("金立", 288) Jinli.call() console.log(Jinli) //类继承 class SmartPhone extends Phone { constructor(brand, price, color, size) { super(brand, price) this.color = color this.size = size } //重写 call () { console.log("我可以视频电话!") } photo () { console.log("我可以拍照!") } } let Xiaomi = new SmartPhone("小米", 1999, "银色", '6.0inch') Xiaomi.call() Xiaomi.photo() console.log(Xiaomi)
class Phone { get price () { console.log("价格属性被读取了") return 999 } set price (newVal) { console.log(`价格属性被修改了,值为${newVal}`) } } let s = new Phone(); console.log(s.price) //输出:价格属性被读取了 999 s.price = 288 //输出:价格属性被修改了,值为288
+ 静态成员:
ES6 的数值扩展:
// Number.EPSILON 是JavaScript表示的最小精度 function equal (a, b) { if (Math.abs(a - b) < Number.EPSILON) { //Math.abs求差值的绝对值 return true } else { return true } } console.log(0.1 + 0.2 === 0.3) console.log(equal(0.1 + 0.2, 0.3)) // Number.isFinite 检测是否为有限数 console.log(Number.isFinite(100)) console.log(Number.isFinite(100 / 0)) console.log(Number.isFinite(Infinity)) // Number.isNaN 检测是否为NaN console.log(Number.isNaN(123)) // Number.parseInt 字符串转整数 console.log(Number.parseInt('521love')) console.log(Number.parseFloat('3.14派')) // Number.isInteger 判断是否为整数 console.log(Number.isInteger(5)) console.log(Number.isInteger(2.5)) // Math.trunc 将小数部分抹掉 console.log(Math.trunc(3.5)) // Math.sign 判断是正数、负数还是零 console.log(Math.sign(100)) console.log(Math.sign(0)) console.log(Math.sign(-100))
ES6 的对象方法扩展:
//判断两个值是否完全相等 console.log(Object.is(120, 120)) let obj1 = { name: "zhangsan" } let obj2 = { age: 18 } //对象合并 console.log(Object.assign(obj1, obj2)) // Object.setPrototypeOf 设置原型对象 // Object.getPrototypeOf 获取原型对象
ES10 的字符串方法扩展:
str.trimStart()、str.trimEnd()
模块化,将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
ES6 之前的模块化规范:CommonJS:NodeJS、Browserify;AMD:requireJS;CMD:seaJS。
优点:防止命名冲突、代码复用、高维护性。
模块化功能主要由两个命令组成:
export 命令用于规定模块的对外接口
import 命令用于输入其他模块提供的功能
//1. 通用的导入方式 // import * as m1 from "./m1.js" // import * as m2 from "./m2.js" // import * as m3 from "./m3.js" //2. 解构赋值形式 // import { name, say } from "./m1.js" // import { name as n, say } from "./m2.js" // import { default as m3 } from "./m3.js" //3. 简便形式 针对默认暴露 import m3 from "./m3.js" console.log(m3) // m1.js // export let name = '肖红' // export function say () { // console.log('hello~') // } // m2,js 统一暴露 // let name = '肖红' // function say () { // console.log('hello~') // } // export { name, say } // m3.js 默认暴露 export default { name: '肖红', say: function () { console.log('hello~') } }
或者使用入口文件形式:
//demo.html <script src="./index.js" type="module"></script> //index.js 入口文件 //模块引入 import * as m1 from './m1.js' import * as m2 from './m2.js' import * as m3 from './m3.js'
考虑兼容性,使用 Babel:
npm 包管理器
import $ from 'jquery' //const $ = require('jquery') //修改背景颜色为粉色 $('body').css('background', 'pink')
async 函数和 await 表达式,可以让异步代码像同步代码一样
//1. async函数的返回值为promise对象 //2. promise对象的结果由async函数执行的返回值决定 async function fn () { return new Promise((resolve, reject) => { // resolve('成功的数据') reject('失败的错误') }) } const result = fn() result.then(value => { console.log(value) }, reason => { console.warn(reason) })
//1. await必须写在async函数中 //2. await右侧的表达式一般为promise对象 //3. await返回的是promise成功的值 const p = new Promise((resolve, reject) => { reject('失败的错误') }) async function main () { try { let result = await p; console.log(result) } catch (e) { console.log(e) } } main()
const fs = require("fs"); function readWeiXue () { return new Promise((resolve, reject) => { fs.readFile("./为学.md", (err, data) => { if (err) reject(err); resolve(data); }) }) } function readChaYangShi () { return new Promise((resolve, reject) => { fs.readFile("./插秧诗.md", (err, data) => { if (err) reject(err); resolve(data); }) }) } function readGuanShu () { return new Promise((resolve, reject) => { fs.readFile("./观书.md", (err, data) => { if (err) reject(err); resolve(data); }) }) } async function main () { let weixue = await readWeiXue(); let chayang = await readChaYangShi(); let guanshu = await readGuanShu(); } main();
function sendAjax (url) { return new Promise((resolve, reject) => { //1. 创建对象 const x = new XMLHttpRequest(); //2. 初始化 x.open('GET', url); //3. 发送 x.send(); //4. 事件绑定 x.onreadystatechange = function () { if (x.readyState === 4) { if (x.status >= 200 && x.status < 300) { resolve(x.response); } else { reject(x.status); } } } }) } //Promise then 方法测试 // sendAjax("https://api.apiopen.top/api/getTime").then(value => { // console.log(value) // }, reason => { // console.warn(reason) // }) //async 与 await 测试 axios async function main () { //发送 AJAX 请求 let result = await sendAjax("https://api.apiopen.top/api/getTime"); console.log(result) // //再次测试 let tianqi = await sendAjax("https://www.tianqiapi.com/api") console.log(tianqi) } main();
私有属性, #
class Person { //公有属性 name; //私有属性 #age; constructor(name, age) { this.name = name; this.#age = age; } say () { console.log(`我叫${this.name},今年${this.#age}`) } } const p = new Person("肖红", 18); console.log(p.name); //输出 肖红 console.log(p.age); //报错 p.say(); //输出 我叫肖红,今年18
可选链操作符,?.
和 C# 的 ?. 相同,检查是否为 NULL
动态import
//静态导入,浪费资源 // import * as m1 from "./hello.js" //点击按钮时,动态导入 const btn = document.getElementById('btn') btn.onclick = function () { import('./hello.js').then(module => { module.hello(); }) } //hello.js function hello () { alert('Hello') }
绝对全局对象,globalThis,相当于window
学习来源:https://www.bilibili.com/video/BV1uK411H7on?p=11&spm_id_from=pageDriver ,ES6之后仅挑重点记