ES5
- 如果一个
变量
或者其他表达式
不在 “当前的作用域” - 那么会继续沿着作用域链向上查找直到全局作用域(global或浏览器中的window)
- 自由变量的查找是在定义的作用域向上级寻找,非执行地!
全局作用域
- 变量在函数或者代码块 {} 外定义,即为全局作用域
- 没有使用 var 定义的变量拥有全局作用域,但是可以被 delete ( 实际 window/global 属性 ),而全局变量不可以
// 此处可调用
function myFunction() {
x = "es"
// 此处可调用
}
函数作用域
- 函数内部定义的变量,对外是封闭的,外层作用域无法直接访问函数内部
- 想读取函数内的变量,必须借助 return 或者闭包
function bar() {
var testValue = 'inner'
}
console.log(testValue) // ReferenceError: testValue is not defined
块状作用域
- 关于什么是块,认识 {} 即可
if (true) {
let a = 1
}
console.log(a) // a is not defined
动态作用域
- this 在执行时开始寻找作用域,箭头函数取上级作用域
function fn() {
console.log(this)
}
fn() // window
fn.call({ x: 100 }) // { x: 100 }
fn.bind({ x: 100 })() // {x: 100}
- 隐式转换
- 当运算符在运算时两边数据类型不统一会自动将数据进行一个类型转换,称为 隐式转换
- ==:等同 ~ 比较运算符,两边值类型不同的时候,先进行类型转换,再比较
- ===:恒等 ~ 严格比较运算符,不做类型转换,类型不同就是不等
- 常规场景:有一种情况可使用 ==,其余使用 === ~
if (a == null) {} if (a == udnefined) {}
console.log(100 == '100') // true
console.log(0 == '') // true
console.log(0 == false) // true
console.log(false == '') // true
console.log(null == undefined) // true
- truly falsely
- 经过两次非运算:truly 变量为 true,falsely 变量为 false
- if 判断其实是判断是否为 trully 变量
- && 返回 falsely 变量,都是 truly 返回最后一个
- || 返回 truly 变量,都是 truly 返回第一个,都是 falsely 返回最后一个
console.log(!!0) // false
console.log(!!NaN) // false
console.log(!!'') // false
console.log(!!null) // false
console.log(!!undefined) // false
console.log(!!false) // false
console.log(NaN && 100) // NAN
console.log(100 && 200) // 200
console.log(NaN || 100) // 100
console.log(100 || 200) // 100
console.log(NaN || undefined) // undefined
- typeof
- null 属于特殊引用类型,指针为空地址
- Class 实际是 function 语法糖
console.log(typeof undefined) // undefined
console.log(typeof 'abc') // string
console.log(typeof 100) // number
console.log(typeof true) // boolean
console.log(typeof Symbol('zhangsan')) // symbol
console.log(typeof null) // object
console.log(typeof ['a', 'b']) // object
console.log(typeof { x: 100 }) // object
console.log(typeof function fn() {}) // function
console.log(typeof Object) // function
- createDocumentFragment :文档片段插入
const frag = document.createDocumentFragment()
for (let i = 0; i < 10; i++) {
const li = document.createElement('li')
frag.appendChild(li)
}
document.body.appendChild(frag)
- onload 需要等待所有资源加载完毕执行,DOMContentLoaded 为DOM渲染完成执行
- window.requestAnimationFrame:浏览器自动调节 60帧/s
const box = document.getElementById('box')
let position = 0
let speed = 2
function animate() {
position += speed
if (position > 200 || position < 0) {
speed = -speed
}
box.style.transform = `translateX(${position}px)`
window.requestAnimationFrame(animate) // 请求下一帧动画
}
window.requestAnimationFrame(animate)
- 闭包
-
函数作为参数被传入或者作为返回值被返回,或者说函数内部创建的函数返回内部的变量
-
防止内存泄漏
- 在不再需要使用闭包时,手动解除对闭包的引用
- 使用模块化的方式
- 将包含闭包的变量赋值为 null
- 内部变量使用 WeakMap 或 WeakSet
-
原子操作
-
const increase = (a, b, c, d) => {
return a + b + c + d
}
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args)
} else {
return function (...moreArgs) {
return curried.apply(this, args.concat(moreArgs))
}
}
}
}
const curriedAdd = curry(increase)
console.log(curriedAdd(10)(20)(30)(40)) // 100
ES6
- let
- 不属于顶层对象 window
- 不允许重复声明
- 不存在变量提升
- 拥有块级作用域( 必须有 {} )
var a = 5
b = 6
let c = 7
console.log(window.a) // 5 设计缺陷:var声明全局变量和顶层对象window进行了挂钩;
console.log(window.b) // 6 // 相当于给 window 顶层对象属性赋值,window.b = 6
console.log(window.c) // undefined
- const :和 let 一致 ,差异点必须定义初始值,不可改变原值(引用类型指地址)
- 解构:对象、数组、字符串
const [a, [b, c], d = 4] = [1, [2, 3]] // 左右结构必须一致
console.log(a, b, c, d) // 1 2 3 4
const user = {
name: 'zhangsan',
age: 10
}
let { age: uage, name: uname } = user // 别名
let { age, name } = user // key
function foo([a, b, c]) {
console.log(a, b, c) // 参数解构 1 2 3
}
foo([1, 2, 3])
- 函数扩展
- 允许 toString()
- 增加了默认值
- 函数有 length 属性即参数个数,默认值不计算在当中
- 拥有函数名:匿名函数 和 bind 有区别
function foo(x, y, z = 1) {} // 默认值
function foo1(x = 1, y = 2, z = 3) {}
console.log(foo1.length) // 0
function foo2(x, y, z = 1) {}
console.log(foo2.length) // 2
console.log(foo.name) // foo
console.log(new Function().name) // anonymous
console.log(foo4.bind({}).name) // bound foo
- rest:剩余运算符,可用于解构(参数、字符串、对象、数组)、合并、拷贝
const arr = [...arr1, ...arr2] // 合并
const obj = { ...obj1 } // 拷贝
foo(...arr) // 解构
function fn(x, ...args) {} // 剩余属性
const { key1, ...rest } = obj // 剩余参数
- 箭头函数
- 不可作为构造函数
- 不可使用 arguments
- 箭头函数不存在 this,或者说 this 指向定义时所在对象,而非调用时的对象(取上级作用域)
- 不存在预加载(类似变量提升)
const sum = (x, y) => x + y
ES7 / es2016
- 内容包含:幂运算符 **
- includes
- 两个参数:包含内容、开始寻找的索引位置(负数从后开始寻找)
- 可用于数组、字符串,无法查找复杂数据类型, 如二维数组,对象数组
const arr = [1, 2, 3, NaN]
console.log(arr.indexOf(NaN)) // -1
console.log(arr.includes(NaN)) // true
const arr2 = ['es6', 'esnext',]
console.log(arr10.includes('es6')) // true
console.log(arr10.includes('es6', 1)) // false
ES8 / es2017
- 内容包含:async、await、Object.defineProperty、Object.values、padStart、padEnd
ES9 / 2018
- 内容包含:Promise.finally
- Symbol.asyncIterator :异步可迭代协议
- for await:遍历过程中依次执行每一个异步函数,而不是瞬间全部执行
function fn(time) {
return new Promise(resolve => {
setTimeout(() => {
resolve({
value: time,
done: false
})
}, time)
})
}
const arr = [fn(1000), fn(2000), fn(3000)]
arr[Symbol.asyncIterator] = function () {
let nextIndex = 0
return {
next() {
return nextIndex < arr.length
? arr[nextIndex++]
: Promise.resolve({ value: undefined, done: true })
}
}
}
// ! 将整个异步函数转换为一个函数表达式
!(async function test() {
for await (let item of arr) {
console.log(item) // 依此输出 1000 2000 3000
}
})()
ES10 / 2019
- 内容包含:fromEntries、flat、faltMap
- Function.prototype.toString : 在 Function 原型上添加
toString
方法 - try catch :允许省去
catch
绑定括号和参数 - JSON superset :支持在 es 中允许 json 使用分隔符
const json = 'var str = "hello" \u2029 function foo(){console.log(str)}'
eval(json) // 行分隔符 \2028,段分隔符 \2029
foo() // hello
- JSON.stringify :解决 unicode 字符串转换缺陷问题,即便输入错误会转换为普通的字符串储存
const str = '\uD83D\uDE0E' // emoji 表情
console.log(JSON.stringify(str)) // "😎"
ES11 / 2020
- 动态导入:常用于结合异步组件和 webpack 代码分割功能实现路由懒加载
const obtn = document.querySelector('#btn')
obtn.addEventListener('click', () => {
import('url').then(mod => {})
})
- BigInt
- 新的原始数据类型,通过 数字
+n
或BigInt(val)
声明 - 最大安全数
2 ** 53
|Number.MAX_SAFE_INTEGER
- 只有字符串可以储存比最大安全数还大的单位,可以将
BigInt
类型 进行toString()
- 新的原始数据类型,通过 数字
const bigInt = 10n
const bigInt2 = BigInt(100n)
console.log(1n == 1) // true
console.log(1n === 1) // false
- globalThis :提供了一个标准的方式来获取不同环境下的全局 this 对象
- 可选链
&&
?
const obj = {
fn() {
console.log('hello')
}
}
obj && obj.fn && obj.fn()
obj?.fn?.()
- 空值合并运输算符 :
??
只有当值为 undefined 或 null 才会默认获取默认值
const a = 0 ?? 1
console.log(a) // 0
const b = '' ?? 'hi'
console.log(b) // 空
const c = false ?? false
console.log(c) // false
其他
-
Iterator、Generator:https://blog.csdn.net/DGogoing/article/details/131855491
-
Proxy:https://blog.csdn.net/DGogoing/article/details/131794107
-
Symbol、Set、WeakSet、MAP、WeakMap:https://blog.csdn.net/DGogoing/article/details/131711988
-
Object 相关:https://blog.csdn.net/DGogoing/article/details/131692060
-
Number、Math:https://blog.csdn.net/DGogoing/article/details/130633881
-
Promise:https://blog.csdn.net/DGogoing/article/details/131227784
-
Array:https://blog.csdn.net/DGogoing/article/details/131218261
-
String:https://blog.csdn.net/DGogoing/article/details/131217999