《JavaScript核心技术开发解密》读书笔记(一)
《JavaScript核心技术开发解密》读书笔记(二)
《JavaScript核心技术开发解密》读书笔记(三)
《JavaScript核心技术开发解密》读书笔记(四)
《JavaScript核心技术开发解密》读书笔记(五)
下面是第十章摘要 - ES6与模块化
es6常用语法知识
1、新的变量声明方式let/const
es6中,新的变量声明方式带来了一些不一样的特性,其中最重要的就是具备了块级作用域并且不再有变量提升。一般来说,声明一个引用可以被改变的变量时用let,声明一个引用不能被改变的变量时用const。
2、箭头函数
特点:
- 箭头函数中的this,就是声明函数时所处上下文中的this,它不会被其他方式所改变。
- 箭头函数只能替换函数表达式,即使用var/let/const声明的函数,而直接使用function声明的函数是不能使用箭头函数替换的。
- 在箭头函数中,没有arguments对象
3、模板字符串
模板字符串使用反引号‘ ` ’将整个字符串包裹起来,变量或者表达式则使用‘
’
来
包
裹
,
{} ’来包裹,
’来包裹,{}中可以放入一个变量、表达式,甚至一个函数。
const name = 'xiaoming'
const str = `my name is ${name}`
4、解析结构(解构赋值)
解析结构是一种从对象或者数组取得值的一种全新的写法。
- 对象解构
var tom = {
name: 'tom',
age: '18'
}
// 传统取值方式
var name = tom.name;
var age = tom.age;
// 解构赋值方式取值
const { name, age } = tom;
// 还可以给变量指定默认值,如果数据中能找到,则变量中的值与数据中相等,如果找不到,则使用默认值
const { name = 'tony', age = '20' } = tom;
// 给变量重命名, 重命名后,name将无法访问,而是通过新的变量名n来访问对应的数据
const { name: n, age } = tom;
嵌套数据解构
const peoples = {
counts: 100,
detail: {
tom: {
name: 'tom',
age: '20',
gender: 1,
job: 'student'
}
}
}
// 获取tom
const { detail: { tom } } = peoples;
// 直接获取tom的age和gender
const { detail: { tom: { age, gender } } } = peoples;
// 相当于
const { detail } = peoples;
const { tom } = detail;
const { age, gender } = tom;
数组解构
const arr = [1, 2, 3];
const [a, b, c] = arr;
// 等价于
const a = arr[0];
const b = arr[1];
const c = arr[2];
注意: 与对象不同的是,数组中变量和值得关系与序列号是一一对应的,这是一个有序的对应关系,而对象则是根数属性名一一对应,这是一个无序的对应关系。
5、展开运算符
在es6中,使用 … 来表示展开运算符,它可以展开数组和对象。
数组展开
const arr1 = [1,2,3];
const arr2 = [...arr1, 4,5];
// 那么arr2就变成了[1,2,3,4,5]
对象展开
const obj1 = {
a: 1,
b: 2
}
const obj2 = {
...obj1,
c: 3,
d: 4
}
// 此时obj2变成了{ a: 1, b: 2, c: 3, d: 4 }
在解构中使用展开运算符
const tom = {
name: 'tom',
age: 18,
gender: 1
}
const { name, ...others } = tom;
// others = { age: 18, gender: 1 }
展开运算符运用于函数传参(只能放置于最后),表示不定参
// 求所有参数之和
const add = (a, b, ...more) => {
return more.reduce((m, n) => m + n) + a + b
}
console.log(add(1, 23, 1, 2, 3, 4, 5)) // 39
Promise
Promise 相关的基础知识
- new Promise 表示创建一个Promise 实例对象
- Promise 函数中的第一个参数为一个回调函数,也可以称之为 executor。通常情况下,在这个函数中,会执行发起请求操作, 并修改结果的状态值。
- 请求结果有三种状态,分别是pending(等待中,表示还没有得到结果)、 resolved (得到了我们想要的结果,可以继续执行),以及 rejected(得到了错误的,或者不是我们期结果,拒绝继续执行)。 请求结果的默认状态为 pending。在executor函数中,可分别使用 resolve与reject 将状态修改为对应的 resolved与rejected。 resolve、reject是executor 函数的两个参数,它们能够将请求结果的具体数据传递出去。
- Promise实例拥有的then方法,可以用来处理请求结果的状态变成resolved时的逻辑。then的第一个参数为一个回调函数,该函数的参数是resolve传递出来的数据。
- Promise实例拥有的catch方法,可用来处理当请求结果的状态变成rejected时的逻辑。catch的第一个参数为一个回调函数,该函数的参数是reject传递出来的数据。
Promise.all: Promise.all接收一个Promise对象组成的数组作为参数,当这个数组中所有的Promise对象状态都变成resolved或者rejected时,它才会去调用then方法。
Promise.race: Promise.race也是以一个Promise对象组成的数组作为参数,不同的是,只要当数组中的其中一个Promise状态变成resolved或者rejected时,就可以调用then方法。
事件循环机制
每一个 JavaScript 程序都拥有唯一的事件循环,大多数代码的执行顺序是可以根据函数调用栈的规则执行的,而 setTimeout/setlnterval 或者不同的事件绑定( click、mousedown 等)中的代码,则通过队列来执行。
setTimeout为任务源,或者任务分发器,由它们将不同的任务分发到不同的任务队列中去。每一个任务源都有对应的任务队列。
任务队列又分为宏任务( macro-task )与微任务( micro-task )两种,在浏览器中,包括:
- macro-task: script(整体代码)、 setTimeout/setlnterval、I/O、UI rendering等。
- micro-task: Promise
注意:在 node.js 中还包括更多的任务队列,此处不做讨论。 来自不同任务源的任务会进到不同的任务队列中,其中 setTimeout与setlnterval是同源的。
事件循环的顺序,决定了 JavaScript 代码的执行顺序。
它从 macro-task 中的 script 开始第一次循环。 此时全局上下文进入函数调用枝, 直到调用栈清空(只剩下全局上下文),在这个过程中,如果遇到任务分发器,就会将任务放人对应队列中去。
第一次循环时,macro-task中其实只有script,因此函数调用栈清空之后,会直接执行所有的micro-task。当所有可执行的micro-task执行完毕之后,就表示第一次事件循环已经结束。
第二次循环会再次从macro-task开始执行。此时macro-task中的script队列中已经没有任务了,但是可能会有其他的队列任务,而micro-task中暂时没有任务。此时会先选择其中一个宏任务队列,例如setTimeout,将该队列中所有任务全部执行完毕,然后再执行此过程中可能产生的微任务。微任务执行完毕之后,再回过头来执行其他宏任务队列中的任务。以此类推,直到所有宏任务队列中的任务都被执行一遍,并清空了微任务,第二次循环就会结束。
如果在第二次循环过程中,产生了新的宏任务队列,或者之前宏任务队列中的任务暂时没有满足执行条件,例如延迟时间不够或者时间没有触发,那么将会继续以同样的顺序重复循环。
class
class是es6为创建对象提供的新的语法糖。
// ES5 - 构造函数
function Person(name, age) {
this.name = name;
this.age = age;
}
// 原型方法
Person.prototype.getName = function () {
return this.name
}
// ES6 - class
class Person {
constructor(name, age) { // 构造函数
this.name = name;
this.age = age;
}
getName() { // 原型方法
return this.name
}
}
继承
使用extends关键字和super方法实现继承
class Student extends Person {
constructor(name, age, gender, classes) {
super(name, age);
this.gender = gender;
this.classes = classes;
}
getGender() {
return this.gender;
}
}
const student = new Student('TOM', 20, 1, 3);
student.getName(); // TOM
student.getGender(); // 1
模块化
每一个文件都是一个独立的模块,一个模块需要对外提供接口,主要使用export命令,一个模块可以引入其他模块(import)
模块化的开发思路,实际上是通过视觉元素、功能性等原则,将代码划分为一个个拥有各自独立职能的模块。通过 ES6的modules 语法,按需将这些模块组合起来,并借助构建工具打包成我们所熟知的 js 文件。
–THE END–