knowledge

标准库文档

目录

  1. ECMAScript标准(部分)

    1. 属性描述
    2. Object
    3. Function
    4. Array
    5. String
    6. Number
    7. JSON
    8. Date
    9. Math
    10. 严格模式
  2. ES6

    1. ECMAScript 2015新增

      1. letconst
      2. 箭头函数
      3. 简写对象的属性、方法
      4. 计算对象的属性名或方法名
      5. 字符串的扩展
      6. 解构赋值、默认参数、剩余参数、展开元素
      7. ES6 Module
      8. Promise
      9. 可迭代对象、异步可迭代对象
      10. for-of
      11. for-await-of(ECMAScript 2018)
      12. 生成器(generators)
      13. async-await(ECMAScript 2017)
      14. classclass-extends
      15. super
      16. new.target
      17. Symbol
      18. SetMapWeakSetWeakMap
      19. 数值的扩展
      20. Proxy
      21. Reflect
      22. BigInt(ECMAScript 2019)
    2. ECMAScript 2016新增
    3. ECMAScript 2017新增
    4. ECMAScript 2018新增
    5. ECMAScript 2019新增
    6. ECMAScript 2020新增
    7. ECMAScript 2021新增
  3. Web API标准(部分)

    1. 文档对象模型(DOM)

      1. document
      2. Canvas
    2. 浏览器对象模型(BOM)

      1. history
      2. Blob
      3. Observers

        1. IntersectionObserver
        2. MutationObserver
        3. PerformanceObserver
        4. ResizeObserver
        5. ReportingObserver
      4. Performance
      5. console
      6. FormData
      7. fetch
      8. Headers
      9. Request
      10. Response
      11. WebSocket
  4. jQuery标准(部分)

    1. Deferred
    2. jQuery事件类型
    3. jQuery事件处理程序的事件对象
  5. 其他

    1. JS模块化方案
    2. JS特殊字符
    3. this替代
  6. CSS标准

    1. 选择器类型
    2. CSS变量(CSS Custom properties,CSS variables)

ECMAScript标准(部分)

对象的API,大部分都是针对可枚举自身(不在原型链上)的属性;复制相关的API,都是浅复制。

属性描述

对象的每一个属性都对应一个「属性描述」对象,必须是数据属性访问器属性两种形式之一。

  1. 数据属性:

    1. configurable(默认:false

      是否能修改(除了value之外的)描述符、是否能delete对象的该属性。

      configurablefalse:除了允许writabletrue修改为false之外,不允许修改描述符(除了value之外,其他描述名都不可以修改:configurableenumerablewritablegetset)。

    2. enumerable(默认:false

      是否可枚举。

    3. writable(默认:false

      该属性是否能被赋值运算符=改变。

    4. value(默认:undefined

      对象的该属性值。

  2. 访问器属性:

    1. configurable
    2. enumerable
    3. get(默认:undefined

      该属性的getter方法,此方法返回值为对象的该属性值。

    4. set(默认:undefined

      该属性的setter方法,此方法接受一个参数,参数值为对象的该属性赋值运算符=右边的值。

    不使用Object.defineProperty/defineProperties的写法 ```javascript var obj = { get foo () { return 'getter' }, set foo (value) { console.log('setter: ' + value) } } // 等价于: var obj = Object.defineProperty({}, 'foo', { get: function () { return 'getter' }, set: function (value) { console.log('setter: ' + value) }, configurable: true, enumerable: true }) // 或等价于: var obj = Object.defineProperties({}, { foo: { get: function () { return 'getter' }, set: function (value) { console.log('setter: ' + value) }, configurable: true, enumerable: true } }) obj.foo // "getter" obj.foo = 123 // => "setter: 123" obj.foo // "getter" obj.foo.a = 1 // 对字符串"getter"进行a属性赋值(基本包装类型),然后销毁 obj.foo.a // undefined。对字符串"getter"取a属性(基本包装类型) ```

    建议:使用更精确的set/get函数(e.g. setBargetBar),减少使用 settergettersetget)。

  1. 不使用Object.defineProperty/defineProperties/create设置属性描述的新建属性(如:给一个对象直接新增属性=、或新建对象),这些属性的configurableenumerablewritabletruevaluegetset为直接设置的内容(若getset未设置,则为undefined)。
  2. 直接赋值修改属性(=)不会导致属性描述被修改:configurableenumerablewritable

Object

来自:MDN:Object

  1. Object构造函数:

    1. Object.preventExtensions(对象)

      1. 描述:不可扩展对象。
      2. 返回:修改的对象。

      不可扩展:不能添加新的属性(是否可以删除/修改已有属性,由属性的属性描述决定)。

    2. Object.seal(对象)

      1. 描述:密封对象。
      2. 返回:修改的对象。

      密封:先调用Object.preventExtensions(对象),再把对象的所有属性标记为configurable: false

    3. Object.freeze(对象)

      1. 描述:冻结对象。
      2. 返回:修改的对象。

      冻结:先调用Object.seal(对象),再把对象的所有属性标记为writable: false

    4. Object.isExtensible(对象)

      1. 描述:判断是否可扩展。
      2. 返回:true/false
    5. Object.isSealed(对象)

      1. 描述:判断是否密封。
      2. 返回:true/false
    6. Object.isFrozen(对象)

      1. 描述:判断是否冻结。
      2. 返回:true/false

    冻结(freeze) > 密封(seal) > 不可扩展(preventExtensions)

    1. Object.assign(目标对象, 多个源对象)(ECMAScript 2015)

      1. 描述:向目标对象浅复制多个源对象(或数组)的所有自有(不在原型链上)可枚举属性(用=来赋值)。
      2. 返回:修改的目标对象。

      若想要深复制,使用deepmerge

    2. Object.getPrototypeOf(对象)

      1. 描述:返回对象的原型链([[Prototype]])。
      2. 返回:一个对象。

      等价于:(非标准)对象.__proto__

    3. Object.setPrototypeOf(目标对象, 原型对象)(ECMAScript 2015)

      1. 描述:原型对象作为目标对象的原型链的引用指向([[Prototype]]
      2. 返回:修改的目标对象。

      等价于:(非标准)目标对象.__proto__ = 原型对象

    4. Object.create(原型对象[, 属性描述对象])

      1. 描述:新建对象,原型对象作为原型链的引用指向([[Prototype]]),属性描述对象作为自有(不在原型链上)属性。
      2. 返回:一个对象。
    5. Object.defineProperty(对象, 属性名, 属性描述)

      1. 描述:新建或修改对象的自有(不在原型链上)属性。
      2. 返回:修改的对象。
      e.g. ```javascript const obj = {} Object.defineProperty(obj, 'foo', { value: 123, writable: true, enumerable: true, configurable: true }) let _bar Object.defineProperty(obj, 'bar', { get: function () { return _bar }, set: function (val) { _bar = val }, enumerable: true, configurable: true }) ```
    6. Object.defineProperties(对象, 属性描述对象)

      1. 描述:新建或修改对象的多个自有(不在原型链上)属性。
      2. 返回:修改的对象。
      e.g. ```javascript const obj = {} let _bar Object.defineProperties(obj, { foo: { value: 123, writable: true, enumerable: true, configurable: true }, bar: { get: function () { return _bar }, set: function (val) { _bar = val }, enumerable: true, configurable: true } }) ```
    7. Object.getOwnPropertyDescriptor(对象, 属性名)

      1. 描述:返回自有(不在原型链上)属性的属性描述。
      2. 返回:属性描述;若不存在属性,则undefined
      e.g. ```javascript const obj = { foo: 123 } Object.getOwnPropertyDescriptor(obj, 'foo') // { // value: 123, // writable: true, // enumerable: true, // configurable: true // } ```
    8. Object.getOwnPropertyDescriptors(对象)(ECMAScript 2017)

      1. 描述:返回属性描述对象,包含所有自有(不在原型链上)属性的属性描述。
      2. 返回:属性描述对象。
      e.g. ```javascript const obj = { foo: 123, get bar() { return 'abc' } } Object.getOwnPropertyDescriptors(obj) // { // foo: { // value: 123, // writable: true, // enumerable: true, // configurable: true // }, // bar: { // get: [Function: get bar], // set: undefined, // enumerable: true, // configurable: true // } // } ```
    9. Object.is(第一个值, 第二个值)(ECMAScript 2015)

      1. 描述:来判断两个值是否是同一个值。
      2. 返回:true/false
    10. Object.entries(对象)(ECMAScript 2017)

      1. 描述:返回所有自有(不在原型链上)可枚举属性的键-值数组组成的数组。
      2. 返回:一个数组。

      e.g.

      1. Object.entries({ a: 'x', b: 42 }) // [['a', 'x'], ['b', 42]]
      2. Object.entries(['a', 'b']) // [['0', 'a'], ['1', 'b']]
      3. 把生成的二维数组转化为字符串:

        // 二维数组转为 => a=b,c=4,e=f
        function stringify (arr, separator1 = '=', separator2 = ',') {
          return arr.reduce((a, b) => {
            return a.concat(b.join(separator1))
          }, []).join(separator2)
        }
        
        console.log(stringify(Object.entries({ a: 'b', 'c': 4, 'e': 'f' }))) // => a=b,c=4,e=f
        

    Object.entriesObject.fromEntries是相反的。

    1. Object.fromEntries(可迭代对象)(ECMAScript 2019)

      1. 描述:把键-值列表转换为一个对象。
      2. 返回:一个对象。

      e.g. Object.fromEntries(new Map([ ['foo', 'bar'], ['baz', 42] ])); // {foo: "bar", baz: 42}Object.fromEntries([ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]); // {0: "a", 1: "b", 2: "c"}

    2. Object.values(对象)(ECMAScript 2017)

      1. 描述:返回所有自有(不在原型链上)可枚举属性的属性值组成的数组。
      2. 返回:一个数组。
    3. Object.keys(对象)

      1. 描述:返回所有自有(不在原型链上)可枚举属性的属性名组成的数组。
      2. 返回:一个数组。
    4. Object.getOwnPropertyNames(对象)

      1. 描述:返回所有自有(不在原型链上)可枚举、不可枚举属性的属性名组成的数组(不包括Symbol类型的属性)。
      2. 返回:一个数组。
    5. Object.getOwnPropertySymbols(对象)

      1. 描述:返回所有自有(不在原型链上)的Symbol类型的属性名组成的数组。
      2. 返回:一个数组。
    6. Object.length等于1

  2. Object原型链(继承给所有实例):

    1. Object.prototype.constructor等于Object
    2. Object.prototype.hasOwnProperty(属性名)

      1. 描述:判断是否是自有(不在原型链上)属性。
      2. 返回:true/false

      对象.hasOwnProperty(属性名)建议代替用:Object.prototype.hasOwnProperty.call(对象, 属性名)

    3. Object.prototype.isPrototypeOf(对象)

      1. 描述:判断实例是否在对象的整条原型链([[Prototype]])上。
      2. 返回:true/false
      • 对象 instanceof 构造函数

        1. 描述:判断构造函数.prototype是否存在于对象的整条原型链([[Prototype]])上。
        2. 返回:true/false
      // e.g.
      Object.prototype.isPrototypeOf([]); // true
      [] instanceof Object;               // true
      

      对象1.isPrototypeOf(对象2)建议代替用:Object.prototype.isPrototypeOf.call(对象1, 对象2)

    4. Object.prototype.propertyIsEnumerable(属性名)

      1. 描述:判断是否是可枚举的自有(不在原型链上)属性。
      2. 返回:true/false

      对象.propertyIsEnumerable(属性名)建议代替用:Object.prototype.propertyIsEnumerable.call(对象, 属性名)

    5. Object.prototype.toString()

      1. 描述:返回表示该对象的字符串。
      2. 返回:一个字符串。
    6. Object.prototype.toLocaleString()

      1. 描述:调用toString。用于被本地化对象方法覆盖。
      2. 返回:一个字符串。
    7. Object.prototype.valueOf()

      1. 描述:返回原始值。
      2. 返回:原始值。

Function

来自:MDN:Function

  1. Function构造函数:

    1. Function.length等于1
  2. Function原型链(继承给所有实例):

    1. Function.prototype.constructor等于Function
    2. Function.prototype.length:函数期望的参数数量(是定义的形参数量,不是调用时传入的实参数量)

      默认参数(之后的参数都不计入)、剩余参数 不计入参数数量;形参的解构仅算一个参数数量。

      e.g. ```javascript var a = (i, j, k) => {}; console.log(a.length); // => 3 function b(i, j, k, l) {} console.log(b.length); // => 4 function c(func) { console.log(func.length); } c((i, j) => {}); // => 2 c(function (i, j, k) {}); // => 3 ```
    3. Function.prototype.name:函数的名字
    4. Function.prototype.call(this替代[, 多个参数])

      1. 描述:指定当前作用域this和多个参数进行的函数调用。
      2. 返回:函数的返回值。
    5. Function.prototype.apply(this替代[, 参数数组])

      1. 描述:指定当前作用域this和参数(数组形式)进行的函数调用。
      2. 返回:函数的返回值。
    • 若实例需要使用其他原型链上的方法,则可以使用构造函数.prototype.方法.call/apply(实例[, 参数])

      e.g. arguments不是Array类型所以无法调用原型链上的Array.prototype.方法,但可通过Array.prototype.方法.call(arguments, 参数)调用。

    1. Function.prototype.bind(this替代[, 多个参数])

      1. 描述:创建新函数,当被调用时,当前作用域this被替代,并设置参数的值(不可改变,新函数的参数填补在原函数去除已设置参数的后面)。
      2. 返回:一个新函数。

      已被bind而新创建的函数,再次使用bind创建新的函数无法改变第一次bind设置的this值。

    因为箭头函数没有创建自己的this,而是向上查找上级作用域的this,所以Function.prototype.call/apply/bind无法指定箭头函数使用的this(this修改无效),但仍然可以添加参数。

    1. Function.prototype.toString()

      1. 描述:返回表示当前函数源代码的字符串。
      2. 返回:一个字符串。
      打印(consolealert等)一个方法时,会自动调用方法的toString转换为字符串后输出 ```javascript function a () {} a.toString = () => `a's toString`; function b () { function c () {} c.toString = () => `c's toString`; return c; } b.toString = () => `b's toString`; alert(a); // a's toString console.log(b); // b's toString console.log(b()); // c's toString ```

      同理,当需要打印某些类型的变量时(除了undefinednull没有属性;某些类型不允许某些打印),会调用变量的toString

Array

来自:MDN:Array

ES5对空位处理不一,ES6把空位都处理为undefinedempty

  1. Array构造函数:

    1. Array.from(类似数组[, 处理方法[, this替代]])(ECMAScript 2015)

      1. 描述:从类似数组的对象可迭代对象创建新的数组实例。处理方法会对新创建的数组执行map操作。
      2. 返回:一个数组。

      类似数组的对象:拥有length属性的对象。e.g. { '0': 'a', '1': 'b', '2': 'c', length: 3 }

    2. Array.isArray(值)

      1. 描述:确定是否为数组。
      2. 返回:true/false
    3. Array.of(数组的每一项)(ECMAScript 2015)

      1. 描述:根据参数创建数组。
      2. 返回:一个数组。

      Array构造函数的区别在对单个参数的返回值:Array.of(3); // [3]new Array(3); // [, , ,]

    4. Array.length等于1

  2. Array原型链(继承给所有实例):

    1. Array.prototype.constructor等于Array
    2. Array.prototype.length:元素个数
    3. 改变调用对象(mutator方法):

      1. Array.prototype.push(添加的多项)

        1. 描述:将一个或多个元素添加到数组的末尾。
        2. 返回:数组新长度。
      2. Array.prototype.pop()

        1. 描述:从数组中删除最后一个元素。
        2. 返回:从数组中删除的元素;若数组为空,则undefined
      3. Array.prototype.unshift(添加的多项)

        1. 描述:将一个或多个元素添加到数组的开头。
        2. 返回:数组新长度。
      4. Array.prototype.shift()

        1. 描述:从数组中删除第一个元素。
        2. 返回:从数组中删除的元素;若数组为空,则undefined
      5. Array.prototype.reverse()

        1. 描述:颠倒数组中元素的位置。
        2. 返回:修改后的数组。
      6. Array.prototype.sort([排序方法])

        听说V8使用的是TimSort排序算法实现sort

        1. 描述:排序数组。
        2. 返回:修改后的数组。
        排序方法 1. `function (a, b) {/* 返回小于0,a在b前;返回等于0,位置不变;返回大于0,a在b后 */}`。 2. 若是比较数字,`function (a, b) {return a - b;}`是升序。 3. 不同浏览器、Node.js等JS运行时环境 内核的排序算法不一致,甚至前后参数的顺序也不一致。因此不要依赖排序方法内单独参数判断。 ```javascript // 在不同浏览器、Windows的Node.js、macOS的Node.js 打印下面内容: var list = [1, 7, 2, 4, 5, 9, 10, 2] list.sort((a, b) => { console.log(`a:${a}|b:${b}`) return a - b }) ```
      7. Array.prototype.splice(开始索引[, 删除数量[, 添加的多项]])

        1. 描述:删除现有元素(,并在开始索引添加新元素)。
        2. 返回:删除元素的数组;若没有删除,则[]
        1. 若删除数量为空,则删除索引之后的所有项。
        2. arr.splice(位置1, 数量1, ...arr.splice(位置2, 数量2)),则先进行参数的执行(第二个删除),被删除后新生成的数组再进行前面的删除并选择位置1进行插入。
      8. Array.prototype.copyWithin(目标索引[, 开始索引[, 结束索引]])(ECMAScript 2015)

        1. 描述:从目标索引的位置开始被浅复制数组的开始索引到结束索引(不包括)的元素。
        2. 返回:修改后的数组(数组长度不变)。
      9. Array.prototype.fill(填充的值[, 开始索引[, 结束索引]])(ECMAScript 2015)

        1. 描述:用填充的值去填充数组中从开始索引到结束索引(不包括)的元素。
        2. 返回:修改后的数组。

        填充进的内容都是浅复制:若填充的值是引用数据类型,则填充的位置都指向同一个内存地址。

    4. 不改变调用对象(accessor方法):

      1. Array.prototype.concat(多个数组)

        1. 描述:合并多个数组(浅复制)。
        2. 返回:合并的新数组。

        e.g. [1, 2].concat(3, [4, 5]) // [1, 2, 3, 4, 5]

      2. Array.prototype.join([分割内容])

        1. 描述:将数组的所有元素连接成字符串。
        2. 返回:字符串。

        参数为空,默认:,;参数为'',则元素之间没有间隙。

      3. Array.prototype.slice([开始索引[, 结束索引]])

        1. 描述:浅复制从开始索引到结束索引(不包括)的数组内容。
        2. 返回:提取元素的新数组;若无内容,则[]
        1. Array.prototype.slice.call(可迭代对象):把可迭代对象转化为数组(非数组的可迭代对象:「TypedArray」MapSetargumentsNodeListString生成器等)。
        2. Array.prototype.slice.call(可迭代对象[, 开始索引[, 结束索引]])返回等于:可迭代对象转化为数组.slice([开始索引[, 结束索引]])
      4. Array.prototype.indexOf(查找的元素[, 开始索引])

        1. 描述:向后查找数组中第一个给定元素。
        2. 返回:索引;若不存在(或查找的元素是NaN),则-1

        开始索引默认:0

      5. Array.prototype.lastIndexOf(查找的元素[, 开始索引])

        1. 描述:向前查找数组中第一个给定元素。
        2. 返回:索引;若不存在(或查找的元素是NaN),则-1

        开始索引默认:数组长度-1。

      因为Array.prototype.indexOf/lastIndexOf是用===进行判断,又NaN !== NaN,所以查找NaN总是返回-1

      1. Array.prototype.includes(查找的元素[, 开始索引])(ECMAScript 2016)

        1. 描述:判断当前数组是否包含给定元素。
        2. 返回:true/false
      2. Array.prototype.toString()

        1. 描述:对每项调用toString,再调用Array.prototype.join连接。
        2. 返回:字符串。
      3. Array.prototype.toLocaleString()

        1. 描述:对每项调用toLocaleString,再调用Array.prototype.join连接。
        2. 返回:字符串。
      4. Array.prototype.flat([数字,默认1])(ECMAScript 2019)

        会移除数组中的空项。

        1. 描述:按照数字深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个。
        2. 返回:一个新数组。
      5. Array.prototype.flatMap(映射方法[, this替代])(ECMAScript 2019)

        1. 描述:首先使用映射方法映射每个元素,然后将结果压缩成一个新数组。
        2. 返回:一个新数组(其中每个元素都是回调函数的结果,并且结构深度depth值为1)。
      6. 遍历方法:

        async-awaitPromise配合的异步Array方法,查看:循环遍历的最后

        1. Array.prototype.forEach(回调函数(当前值, 索引, 数组整体)[, this替代])

          1. 描述:对数组的每个元素执行一次提供的函数。跳过空位。
          2. 返回:undefined

          回调函数return无意义;空位不执行回调函数。

        2. Array.prototype.map(回调函数(当前值, 索引, 数组整体)[, this替代])

          1. 描述:数组中的每个元素调用提供的函数,组成新的数组。跳过空位(保留空位至新数组)。
          2. 返回:一个新的数组。

          回调函数return的值为新数组每个项的值(若return本项,则浅复制);空位不执行回调函数,保留空位至新数组。

        3. Array.prototype.filter(回调函数(当前值, 索引, 数组整体)[, this替代])

          1. 描述:使用提供的函数测试所有元素,并创建包含所有通过测试的元素的新数组(浅复制)。跳过空位(新数组丢弃空位)。
          2. 返回:一个新的数组;若都不通过,则[]

          回调函数return的值为true,则把原项添加进新数组(浅复制),为false则丢弃;空位不执行回调函数,新数组丢弃空位。

        4. Array.prototype.every(回调函数(当前值, 索引, 数组整体)[, this替代])

          1. 描述:测试数组中是否所有元素都通过提供的函数(空数组或全空位数组,返回true)。跳过空位。
          2. 返回:true/false

          回调函数return的值为true,则继续判断下一项,为false则不再继续;空位不执行回调函数。

        5. Array.prototype.some(回调函数(当前值, 索引, 数组整体)[, this替代])

          1. 描述:测试数组中是否有一个元素通过提供的函数(空数组或全空位数组,返回false)。跳过空位。
          2. 返回:true/false

          回调函数return的值为false,则继续判断下一项,为true则不再继续;空位不执行回调函数。

        6. Array.prototype.find(回调函数(当前值, 索引, 数组整体)[, this替代])(ECMAScript 2015)

          1. 描述:查找数组中通过提供的函数的第一个元素。空位当做undefined
          2. 返回:一个元素;若都不通过,则undefined

          回调函数return的值为true,则找到并返回该项的值,为false则继续判断下一项;空位的项的值作为undefined执行回调函数。

        7. Array.prototype.findIndex(回调函数(当前值, 索引, 数组整体)[, this替代])(ECMAScript 2015)

          1. 描述:查找数组中通过提供的函数的第一个元素的索引。空位当做undefined
          2. 返回:索引;若都不通过,则-1

          回调函数return的值为true,则找到并返回该项的索引,为false则继续判断下一项;空位的项的值作为undefined执行回调函数。

        8. Array.prototype.reduce(回调函数(上一次调用返回的值, 当前值, 索引, 数组整体)[, 第一次调用回调函数的第一个参数])

          1. 描述:向后对数组应用提供的函数。跳过空位。
          2. 返回:函数累计处理的最后一个结果。

          空位不执行回调函数。

        9. Array.prototype.reduceRight(回调函数(上一次调用返回的值, 当前值, 索引, 数组整体)[, 第一次调用回调函数的第一个参数])

          1. 描述:向前对数组应用提供的函数。跳过空位。
          2. 返回:函数累计处理的最后一个结果。

          空位不执行回调函数。

        10. Array.prototype.values()(ECMAScript 2015)

          1. 描述:返回新的Array迭代器对象,该对象包含数组每个索引的值。
          2. 返回:一个Array迭代器对象。

          Array.prototype.values === Array.prototype[Symbol.iterator]

        11. Array.prototype.keys()(ECMAScript 2015)

          1. 描述:返回新的Array迭代器,它包含数组中每个索引的键。
          2. 返回:一个Array迭代器对象。
        12. Array.prototype.entries()(ECMAScript 2015)

          1. 描述:返回新的Array迭代器对象(包含数组中每个索引的键-值)。
          2. 返回:一个Array迭代器对象。

String

来自:MDN:String

JS内部,字符以UCS-2(UTF-16的子级)的格式储存。UTF-16结合了定长和变长两种编码方法,大部分字符使用两个字节编码,字符代码超出Math.pow(16, 4) - 1的使用四个字节。

对于那些需要4个字节储存的字符(Unicode码点大于0xFFFF的字符),JS会认为它们是2个字符(ES6之前)。对于ES6的语法内容或方法,4个字节储存的字符会正确按照单个字符处理。

  1. String构造函数:

    1. String.fromCharCode(多个Unicode数字)

      1. 描述:使用Unicode值创建字符串(无法识别Unicode码点大于0xFFFF的字符)。
      2. 返回:一个字符串。

      可以通过\u+4位16进制数的Unicode值输出字符串。如:'\u00a9' === '©'

    2. String.fromCodePoint(多个代码点序列数字)(ECMAScript 2015)

      1. 描述:使用代码点序列创建字符串(支持Unicode码点大于0xFFFF的字符)。
      2. 返回:一个字符串。
    3. String.raw({ row: 可迭代对象 }[, 多个值])String.raw`模板字符串`

      1. 描述:获取模板字符串的原始字面量值(将所有变量替换,且把\转义成\\)。
      2. 返回:一个字符串。
    4. String.length等于1

  2. String原型链(继承给所有实例):

    1. String.prototype.constructor等于String
    2. String.prototype.length:字符串长度

      字符串长度不一定等于字符数:

      var emoji = "😄";
      console.log(emoji.length); // 2
      
      var adlam = "𞤲𞥋𞤣𞤫";
      console.log(adlam.length); // 8
      
      var formula = "∀𝑥∈ℝ,𝑥²≥0";
      console.log(formula.length); // 11
      
    3. 跟HTML无关的方法:

      String的方法均不改变调用对象(accessor方法)。

      1. String.prototype.substr(开始索引[, 提取长度])

        1. 描述:复制从开始索引的指定长度的字符串内容。
        2. 返回:截取的字符串。

        若开始索引为负数,则加上字符串长度;若提取长度为0或负数,则返回''

      2. String.prototype.substring(开始索引[, 结束索引])

        1. 描述:复制从开始索引到结束索引(不包括)的字符串内容。
        2. 返回:截取的字符串。

        若参数为负数或NaN,则转换为0;若参数大于长度,则为转换为长度;若结束索引小于开始索引,则参数前后替换位置。

      3. String.prototype.slice(开始索引[, 结束索引])

        1. 描述:复制从开始索引到结束索引(不包括)的字符串内容。
        2. 返回:截取的字符串。

        若参数为负数,则加上字符串长度;若结束索引比开始索引小,则返回''

      4. String.prototype.split([分割内容[, 限定分割数量]])

        1. 描述:将字符串分割成数组。
        2. 返回:一个数组。

        分割内容可以是正则表达式。若包含捕获括号的正则表达式,则匹配的每一个捕获括号的结果(包括undefined),都会单独添加到输出数组中。如:

        'a1b22c'.split(/\d/)         //  ["a", "b", "", "c"]
        'a1b22c'.split(/(\d)/)       // ["a", "1", "b", "2", "", "2", "c"]
        'a1b22c'.split(/(\d)(\d)/)   //  ["a1b", "2", "2", "c"]
        'a1b22c'.split(/(\d)?(\d)/)  // ["a", undefined, "1", "b", "2", "2", "c"]
        
      5. String.prototype.indexOf(查找的元素[, 开始索引])

        1. 描述:向后查找字符串中第一个给定元素(查找到的元素首部为返回的索引)。
        2. 返回:索引;若不存在,则-1

        开始索引默认:0

      6. String.prototype.lastIndexOf(查找的元素[, 开始索引])

        1. 描述:向前查找字符串中第一个给定元素(查找到的元素首部为返回的索引)。
        2. 返回:索引;若不存在,则-1

        开始索引默认:数组长度。

      7. String.prototype.includes(查找的元素[, 开始索引])(ECMAScript 2015)

        1. 描述:判断当前字符串是否包含给定元素。
        2. 返回:true/false
      8. String.prototype.startsWith(查找的元素[, 开始索引])(ECMAScript 2015)

        1. 描述:判断当前字符串是否以给定元素作为开头。
        2. 返回:true/false
      9. String.prototype.endsWith(查找的元素[, 结束索引])(ECMAScript 2015)

        1. 描述:判断当前字符串是否以给定元素作为结尾。
        2. 返回:true/false
      10. String.prototype.charAt(索引)

        1. 描述:返回特定位置的1个字符(对于拥有2个字符-4个字节的字,只能分别各返回1个字符-2个字节,导致乱码)。
        2. 返回:一个字符;若超出范围或空字符,则''
      11. String.prototype.charCodeAt(索引)

        1. 描述:返回特定位置的1个字符的Unicode值(对于拥有2个字符-4个字节的字,只能分别各返回1个字符-2个字节的Unicode值)。
        2. 返回:一个整数(小于Math.pow(16, 4));若超出范围或空字符,则NaN

        e.g. '💩©'.charCodeAt(0) // 55357'💩©'.charCodeAt(1) // 56489'💩©'.charCodeAt(3) // 169

      12. String.prototype.codePointAt(索引)(ECMAScript 2015)

        1. 描述:返回特定位置的字符的完整Unicode值(2或4个字节),或2个字符中的第2个字符。
        2. 返回:一个整数(小于Math.pow(16, 4));若超出范围或空字符,则undefined

        e.g. '💩©'.codePointAt(0) // 128169'💩©'.codePointAt(1) // 56489'💩©'.codePointAt(3) // 169

      13. String.prototype.trim()

        1. 描述:删除两端的空白字符。
        2. 返回:修改后的字符串。
      14. String.prototype.trimStart/trimLeft()(ECMAScript 2019)

        1. 描述:字符串的开头删除空格。
        2. 返回:修改后的字符串。
      15. String.prototype.trimEnd/trimRight()(ECMAScript 2019)

        1. 描述:字符串的末端删除空格。
        2. 返回:修改后的字符串。
      16. String.prototype.repeat()

        1. 描述:字符串重复0到正无穷次。
        2. 返回:修改后的字符串。
      17. String.prototype.padStart(目标长度数字[, 填充字符串])(ECMAScript 2017)

        1. 描述:字符串开头填充指定的填充字符串(不够则循环重复,太长则截断,默认:' '),直到长度达到目标长度数字(若目标长度数字小于等于原字符串长度,则不改变原字符串)。
        2. 返回:修改后的字符串。
      18. String.prototype.padEnd(目标长度数字[, 填充字符串])(ECMAScript 2017)

        1. 描述:字符串尾部填充指定的填充字符串(不够则循环重复,太长则截断,默认:' '),直到长度达到目标长度数字(若目标长度数字小于等于原字符串长度,则不改变原字符串)。
        2. 返回:修改后的字符串。
      19. String.prototype.replace(正则或字符串, 替换字符串或替换方法)

        1. 描述:新的内容来替换被匹配的内容(字符串仅能替换第一个匹配,正则可以按正则表达式匹配)。
        2. 返回:修改后的字符串。
      20. String.prototype.replaceAll(正则或字符串, 替换字符串或替换方法)(ECMAScript 2021)

        1. 描述:新的内容来替换被匹配的内容(字符串和正则可以替换所有匹配。当使用正则时,必须设置全局g标志)。
        2. 返回:修改后的字符串。
      21. String.prototype.search(正则表达式)

        1. 描述:向后查找字符串中第一个匹配内容。
        2. 返回:索引;若不匹配,则-1
      22. String.prototype.match(正则表达式)

        1. 描述:使用正则表达式与字符串相比较。
        2. 返回:一个匹配结果的数组;若不匹配,则null
      23. String.prototype.matchAll(正则表达式)(ECMAScript 2020)

        1. 描述:使用正则表达式与字符串相比较(正则必须设置全局g标志)。
        2. 返回:一个迭代器(不可重用,结果耗尽需要再次调用方法,获取一个新的迭代器)。
      24. String.prototype.toLowerCase()

        1. 描述:转换为小写。
        2. 返回:修改后的字符串。
      25. String.prototype.toUpperCase()

        1. 描述:转换为大写。
        2. 返回:修改后的字符串。
      26. String.prototype.toLocaleLowerCase()

        1. 描述:根据任何本地化特定的大小写映射,转换为小写。
        2. 返回:修改后的字符串。
      27. String.prototype.toLocaleUpperCase()

        1. 描述:根据任何本地化特定的大小写映射,转换为大写。
        2. 返回:修改后的字符串。
      28. String.prototype.concat(多个字符串)

        1. 描述:连接多个字符串。不影响原字符串。
        2. 返回:连接的新字符串。

        因为性能和语法简洁原因,建议使用赋值操作符+代替。

      29. String.prototype.valueOf()

        1. 描述:返回String对象的原始值(primitive value)。
        2. 返回:一个字符串。
      30. String.prototype.toString()

        1. 描述:返回指定对象的字符串形式。
        2. 返回:一个字符串。

        String.prototype.valueOf()返回值一致。

      31. String.prototype.localeCompare(比较的元素[, locales[, options]])

        1. 描述:判断字符串的排列顺序(编码中的位置)是否在给定元素的前面、后面或相同。
        2. 返回:若在前,则负数;若在后,则正数;若相同,则0
      32. String.prototype.normalize([Unicode正规形式])

        1. 描述:按照指定的一种Unicode正规形式将当前字符串正规化。
        2. 返回:修改后的字符串。

        e.g. '\u01D1'.normalize() === '\u004F\u030C'.normalize()

    4. HTML标签包裹方法:

      1. String.prototype.anchor()
      2. String.prototype.big()
      3. String.prototype.blink()
      4. String.prototype.bold()
      5. String.prototype.fixed()
      6. String.prototype.fontcolor()
      7. String.prototype.fontsize()
      8. String.prototype.italics()
      9. String.prototype.link()
      10. String.prototype.small()
      11. String.prototype.strike()
      12. String.prototype.sub()
      13. String.prototype.sup()

Number

来自:MDN:Number

JS采用IEEE 754标准,数值存储为固定64位(双精度浮点数),数值精度最多可以达到53个2进制位 >参考:[JavaScript 浮点数陷阱及解法](https://github.com/camsong/blog/issues/9)。 1. 整数 1. 若整数大于或等于`Math.pow(2, 53)`或小于或等于`-Math.pow(2, 53)`,则会得到不精确的数。 >不精确的数会等于一个跳跃过的数,如:`9179200084836087807`输出的是`9179200084836088000`,因此会`9179200084836087807 === 9179200084836088000`和`'9179200084836087807' == 9179200084836088000`(用来判断不精确数是否相同)。 2. 若整数大于或等于`Math.pow(2, 1024)`,则JS无法表示,会返回`Infinity`。 >因此接口返回的id等,最好用字符串返回,才不会因为超过了JS中最大的安全整数而导致问题。 - 解决:ES6使用`BigInt`,ES5使用[按位计算的大数加减法](https://github.com/realgeoffrey/knowledge/blob/master/网站前端/JS方法积累/实用方法/README.md#原生js大数加减法按位计算不考虑小数和负数) 2. 浮点数的计算可能导致结果出现奇怪小数、浮点数的四舍五入都可能不准确 浮点数的计算或四舍五入之后,不要进行精确的等于/不等于比较,容易出纰漏。 - 解决:[用整数进行小数的四则运算](https://github.com/realgeoffrey/knowledge/blob/master/网站前端/JS方法积累/实用方法/README.md#原生js用整数进行小数的四则运算避免浮点数运算误差)

部分是ES6。

  1. Number构造函数:

    1. 属性

      1. Number.EPSILON:两个可表示数之间的最小间隔(表示可接受的最小误差范围)。

        Math.abs(0.2 - 0.3 + 0.1) < Number.EPSILON; // true

      2. 能够准确地表示和正确地比较的安全整数:

        1. Number.MAX_SAFE_INTEGER:JS中最大的安全整数。

          Number.MAX_SAFE_INTEGER === Math.pow(2, 53) - 1; // true

        2. Number.MIN_SAFE_INTEGER:JS中最小的安全整数。

          Number.MIN_SAFE_INTEGER === -(Math.pow(2, 53) - 1); // true

        • Number.MAX_SAFE_INTEGER === -Number.MIN_SAFE_INTEGER; // true
      3. Number.MAX_VALUE:JS中能表示的最大数值。

        -Number.MAX_VALUE:JS中能表示的最小数值。

      4. Number.MIN_VALUE:JS中能表示的最小正数。

        -Number.MIN_VALUE:JS中能表示的最大负数。

      5. Number.NaNNaN
      6. 溢出数:

        1. Number.POSITIVE_INFINITY:正无穷大。

          Number.POSITIVE_INFINITY === Infinity; // true

        2. Number.NEGATIVE_INFINITY:负无穷大。

          Number.NEGATIVE_INFINITY === -Infinity; // true InfinityNaN都是Number数据类型。

    2. 方法

      1. Number.isNaN(值)

        1. 描述:判断是否为NaN且类型为Number
        2. 返回:true/false

        isNaN(值)会先Number(值)再判断;Number.isNaN(值)若值不是数字类型则返回false

      2. Number.isFinite(值)

        1. 描述:判断是否为有穷数且类型为Number
        2. 返回:true/false

        isFinite(值)会先Number(值)再判断;Number.isFinite(值)若值不是数字类型则返回false

      3. Number.isInteger(值)

        1. 描述:判断是否为整数且类型为Number
        2. 返回:true/false

        NaN正负Infinity不是整数。

      4. Number.isSafeInteger(值)

        1. 描述:判断是否为安全整数且类型为Number
        2. 返回:true/false

        安全整数范围:[-(Math.pow(2, 53) - 1), Math.pow(2, 53) - 1]

      5. Number.parseIntparseInt

        ~~「浮点数」(2个按位非运算符~)等价于parseInt(「浮点数」),且前者效率更高。

      6. Number.parseFloatparseFloat

  2. Number原型链(继承给所有实例):

    1. Number.prototype.toFixed([数字])

      1. 描述:指定小数点后数字个数(默认:0),省去的四舍五入(不准确),没有的小数位置补0(e.g. (1.1).toFixed(2) === '1.10')。
      2. 返回:一个字符串。

      若要去除toFixed出现的末尾补0,则可以直接Number(字符串)

      // 保留小数点后n位,四舍五入(不准确),位数不够,不补0,返回数字类型
      function formatFloat(num: number, places: number = 0): number {
       return Math.round(num * Math.pow(10, places)) / Math.pow(10, places);
      }
      
    2. Number.prototype.toExponential([数字])

      1. 描述:用指数形式,指定小数点后数字个数(默认:达到已有位数),省去的四舍五入(不准确)。
      2. 返回:一个字符串。
    3. Number.prototype.toPrecision([数字])

      1. 描述:指定精确位数(默认则类似Number.prototype.toString()),省去的四舍五入(不准确)。(数字范围:[1, 100]的整数)
      2. 返回:一个字符串。

      在某些情况下会以指数表示法返回。

    4. Number.prototype.toString([数字])

      1. 描述:10进制数转化为指定进制数的字符串(默认:10进制)。
      2. 返回:一个字符串。
      其他进制的字符串转化为10进制数:parseInt(其他进制的字符串, 其他进制) e.g. ```javascript const num2 = 1234567890 // 10进制 console.log(num2.toString(16)) // 10进制->2至36进制 const str16 = '499602d2' // 2至36进制 console.log(parseInt(str16, 16)) // 2至36进制->10进制 ``` [不同进制数互相转换](https://github.com/realgeoffrey/knowledge/blob/master/网站前端/JS方法积累/实用方法/README.md#原生js不同进制数互相转换)
    5. Number.prototype.valueOf()

      1. 描述:返回原始值数字。
      2. 返回:一个数字。
    6. Number.prototype.toLocaleString([locales[ , options]])

      参数文档:MDN: Intl.NumberFormat() constructor

      1. 描述:返回格式化之后的字符串。
      2. 返回:一个字符串。

    数字直接调用Number原型链上方法的写法:

    1. 10.toString(2) // SyntaxError: Unexpected token ILLEGAL
    2. 会转化为小数点

      10..toString(2)
      10.0.toString(2)
      
      // "1010"
      
    3. 通过额外的括号或方括号

      10['toString'](2);
      (10)['toString'](2);
      (10).toString(2)
      
      // "1010"
      
    4. 10 .toString(2) // "1010"

      JSON

      来自:MDN:JSON

  3. JSON.parse(JSON字符串[, 处理方法])

    1. 描述:将JSON字符串解析为JS值。处理方法会改造转换完毕的JS值。
    2. 返回:JS值。
    1. 处理方法,由最内层开始,依次向外遍历:(键, 值) => {/* return的内容替代「值」成为此「键」的值,没有return则删除此「键」(会产生数组的空位);最顶层时,键为空字符串,返回的内容为整个JSON.parse表达式返回的值 */}
    2. 一般需要try-catch包裹
  4. JSON.stringify(JS值[, 处理方法或需要的属性名组成的数组[, 缩进空格数量或缩进字符串]])

    1. 描述:将JS值自有(不在原型链上)可枚举属性解析为JSON字符串。
    2. 返回:JSON字符串。
    1. 非数组对象的属性不保证以特定的顺序出现在序列化后的字符串中。
    2. Boolean、Number、String的基本包装类型在序列化过程中会自动转换成对应的原始值。
    3. 值为:undefined方法Symbol类型的值

      1. 非数组中:属性名-值整个被忽略
      2. 数组中:被转换成null
    4. 不支持BigInt类型的值(TypeError: Do not know how to serialize a BigInt)。
    5. 所有Symbol类型的属性键都会被忽略。
    6. 不可枚举的属性被忽略。

Date

来自:MDN:Date

  1. 调用构造函数:

    1. new Date([毫秒/时间字符串/年, 月[, 日[, 时[, 分[, 秒[, 毫秒]]]]]])

      创建Date实例(默认:当前时间)。

      特例:iOS中的new Date('2013-10-21')报错,必须改为new Date('2013/10/21')

    2. Date(参数无效)

      创建当前时间的字符串。

    无字面量格式。若参数超出了合理范围,则会调整到相邻的时间。

当前时间:所在系统的时间(系统修改成什么时间就返回什么时间)。

  1. Date构造函数:

    1. Date.now()

      1. 描述:自1970-01-01 00:00:00 UTC到当前时间的毫秒。
      2. 返回:一个数字。
    2. Date.parse(时间字符串)

      1. 描述:自1970-01-01 00:00:00 UTC到时间字符串的毫秒。
      2. 返回:一个数字;若参数不合法,则NaN
    3. Date.UTC(年, 月[, 日[, 时[, 分[, 秒[, 毫秒]]]]])

      1. 描述:自1970-01-01 00:00:00 UTC到参数日期的毫秒。
      2. 返回:一个数字。
    4. Date.length等于7

  2. Date原型链(继承给所有实例):

    1. getter:

      返回:一个数字。

      1. Date.prototype.getTime()

        描述:自1970-01-01 00:00:00 UTC到Date对象时间的毫秒。

      2. Date.prototype.getTimezoneOffset()

        描述:UTC相对于当前时区的时间差值(分钟)。

      3. Date.prototype.getFullYear()

        描述:年。

      4. Date.prototype.getMonth()

        描述:[0, 11]月。

      5. Date.prototype.getDate()

        描述:[1, 31]日。

      6. Date.prototype.getHours()

        描述:[0, 23]时。

      7. Date.prototype.getMinutes()

        描述:[0, 59]分。

      8. Date.prototype.getSeconds()

        描述:[0, 59]秒。

      9. Date.prototype.getMilliseconds()

        描述:[0, 999]毫秒。

      10. Date.prototype.getDay()

        描述:[0, 6]星期。

        0:周天;1:周一;6:周六。

      11. Date.prototype.getUTCFullYear()

        描述:年(UTC)。

      12. Date.prototype.getUTCMonth()

        描述:[0, 11]月(UTC)。

      13. Date.prototype.getUTCDate()

        描述:[1, 31]日(UTC)。

      14. Date.prototype.getUTCHours()

        描述:[0, 23]时(UTC)。

      15. Date.prototype.getUTCMinutes()

        描述:[0, 59]分(UTC)。

      16. Date.prototype.getUTCSeconds()

        描述:[0, 59]秒(UTC)。

      17. Date.prototype.getUTCMilliseconds()

        描述:[0, 999]毫秒(UTC)。

      18. Date.prototype.getUTCDay()

        描述:[0, 6]星期(UTC)。

        0:周天;1:周一;6:周六。

      e.g. ```javascript // 时间戳 => 20190414 周天 09:01:22 function formatDate (timestamp = Date.now()) { function pad (num = 0) { num = Number(num) if (num < 10) { num = '0' + num } return num } const date = new Date(timestamp) const year = date.getFullYear() const month = pad(date.getMonth() + 1) const day = pad(date.getDate()) const weekday = ['天', '一', '二', '三', '四', '五', '六'][date.getDay()] const hour = pad(date.getHours()) const minute = pad(date.getMinutes()) const second = pad(date.getSeconds()) return `${year}${month}${day} 周${weekday} ${hour}:${minute}:${second}` } /* 使用测试 */ formatDate() ```
    2. setter:

      返回:一个数字(自1970-01-01 00:00:00 UTC到Date对象时间的毫秒)。

      (除了setTime之外,)若参数超出了合理范围,则调整到相邻的时间(负数则减少1年/月/日/时/分/秒/毫秒,正数超过范围则增加1年/月/日/时/分/秒/毫秒)。

      1. Date.prototype.setTime(距1970-01-01 00:00:00 UTC的毫秒)

        描述:设置时间。

      2. Date.prototype.setFullYear(年[, 月[, 日]])

        描述:设置年。

      3. Date.prototype.setMonth(月[, 日])

        描述:设置月。

      4. Date.prototype.setDate(日)

        描述:设置日。

      5. Date.prototype.setHours(时[, 分[, 秒[, 毫秒]]])

        描述:设置时。

      6. Date.prototype.setMinutes(分[, 秒[, 毫秒]])

        描述:设置分。

      7. Date.prototype.setSeconds(秒[, 毫秒])

        描述:设置秒。

      8. Date.prototype.setMilliseconds(毫秒)

        描述:设置毫秒。

      9. Date.prototype.setUTCFullYear(年[, 月[, 日]])

        描述:设置年(UTC)。

      10. Date.prototype.setUTCMonth(月[, 日])

        描述:设置月(UTC)。

      11. Date.prototype.setUTCDate(日)

        描述:设置日(UTC)。

      12. Date.prototype.setUTCHours(时[, 分[, 秒[, 毫秒]]])

        描述:设置时(UTC)。

      13. Date.prototype.setUTCMinutes(分[, 秒[, 毫秒]])

        描述:设置分(UTC)。

      14. Date.prototype.setUTCSeconds(秒[, 毫秒])

        描述:设置秒(UTC)。

      15. Date.prototype.setUTCMilliseconds(毫秒)

        描述:设置毫秒(UTC)。

    3. 转换

      1. 转化为字符串:

        1. Date.prototype.toDateString()
        2. Date.prototype.toISOString()
        3. Date.prototype.toJSON()
        4. Date.prototype.toLocaleDateString()
        5. Date.prototype.toLocaleString()
        6. Date.prototype.toLocaleTimeString()
        7. Date.prototype.toString()
        8. Date.prototype.toTimeString()
        9. Date.prototype.toUTCString()
      2. 转换为数字:

        1. Date.prototype.valueOf()

Math

来自:MDN:Math

部分是ES6。

  1. 方法

    对参数先进行Number(参数)再进行方法;若参数无法转化为数字,则返回NaN

    1. Math.abs(数字)

      返回:数字的绝对值。

    2. Math.ceil(数字)

      返回:数字向上取整后的整数值。

    3. Math.floor(数字)

      返回:数字向下取整后的整数值。

    4. Math.round(数字)

      返回:数字四舍五入(不准确)后的整数值。

    5. Math.random()

      返回:[0,1)的伪随机数。

    6. Math.max(多个数字)

      返回:多个数字中的最大值。

    7. Math.min(多个数字)

      返回:多个数字中的最小值。

    8. Math.pow(基数, 指数)

      返回:基数的指数次幂。

    9. Math.sqrt(数字)

      返回:数字的平方根。

    10. Math.log(数字)

      返回:数字的自然对数。

    11. Math.exp(数字)

      返回:e的数字指数的值。

    1 * 弧度 === 1 * (180 / Math.PI)角度

    1. Math.sin(弧度)

      返回:弧度的正弦值。

    2. Math.asin(数字)

      返回:数字的反正弦值(弧度)。

    3. Math.cos(弧度)

      返回:弧度的余弦值。

    4. Math.acos(数字)

      返回:数字的反余弦值(弧度)。

    5. Math.tan(弧度)

      返回:弧度的正切值。

    6. Math.atan(数字)

      返回:数字的反正切值(弧度)。

    7. Math.atan2(数字1, 数字2)

      返回:数字2/数字1的反正切值(弧度)。

    8. Math.trunc(数字)

      返回:去除数字的小数部分,返回整数部分。

    9. Math.sign(数字)

      返回:根据数字是正数、负数、0-0,分别返回+1-10-0

    10. Math.cbrt(数字)

      返回:数字的立方根。

    11. Math.hypot(多个数字)

      返回:所有数字各自的平方和的平方根。

  2. 属性

    1. Math.PI

      描述:圆周率,约等于:3.14159。

    2. Math.E

      描述:欧拉常数,自然对数的底数, 约等于:2.718。

    3. Math.LN2

      描述:2的自然对数, 约等于:0.693。

    4. Math.LN10

      描述:10的自然对数, 约等于:2.303。

    5. Math.LOG2E

      描述:以2为底E的对数, 约等于:1.443。

    6. Math.LOG10E

      描述:以10为底E的对数, 约等于:0.434。

    7. Math.SQRT1_2

      描述:1/2的平方根, 约等于:0.707。

    8. Math.SQRT2

      描述:2的平方根,约等于:1.414。

严格模式

来自:MDN:严格模式

  1. 作用范围:全局(一个代码块<script>内)或函数作用域。

    合并一个全局的严格模式与其他非严格模式的代码,会导致所有合并代码均为严格模式。

    • 特殊:只要函数的参数使用了默认参数解构赋值剩余参数,就不能在函数体内显式指定严格模式。
  2. 开启方式:作用域加上"use strict";;ES6 Module默认要求、ES6的class默认要求。

    请确保"use strict"出现在脚本或函数的最顶部,否则严格模式可能无法启用。严格模式被开启后,无法再关闭。

    • 声明时是严格模式,调用执行时才按照严格模式执行(与调用位置无关)。

      e.g. ```javascript var a = 2 function foo () { console.log(this.a) } function bar () { 'use strict' console.log(this.a) } ;(function () { 'use strict' foo() // => 2。foo是在非严格模式下定义的,所以按照非严格模式执行 bar() // TypeError: Cannot read property 'a' of undefined }()) ```

      建议不要混用严格模式、非严格模式(但使用第三方库时难以避免)。

  3. 影响

    1. 消除静默失败,改为错误抛出。
    2. 修复了JS引擎难以执行优化的错误,(有时候)相同代码运行得更快。
    3. 禁用在ECMAScript的未来版本中可能会定义的一些语法。
  4. 相对于非严格模式,增加的限制(违背则抛出错误):

    1. 将拼写错误转成异常

      1. 不允许意外创建全局变量。
      2. 不允许对不可写只读不可扩展的属性赋值或删除(引起非严格模式静默失败的情况)。
      3. 不允许重名属性名、参数名。
      4. 不允许0数字'\0数字'代表8进制。

        0o数字是ES6支持的8进制数。

      5. 不允许给基本数据类型设置属性。

        基本数据类型:UndefinedNullBooleanNumberStringSymbolBigInt

    2. 简化变量使用

      1. 不允许使用with
      2. 不允许删除变量。
    3. 安全

      1. eval不会在它的外层作用域引入变量。
      2. 不允许evalarguments被绑定或赋值。
      3. arguments属性不与参数同步更新。

        可以分别修改arguments属性或参数,两者不会同步。

      4. 不可删除、赋值、读取:函数名.caller函数名.argumentsarguments.callerarguments.callee
      5. 没有调用对象的直接调用时,this指向undefined而不指向全局对象
      6. this替代this为传入的值(不会转化为基本包装类型;传入null/undefined就为null/undefined)。

        在非严格模式,使用this替代:若是基本数据类型(除了undefined/null之外),则this为那个值的基本包装类型;若不传或传入undefined/null,则this为全局对象。

    4. 为未来的ES铺平道路

      1. 增加一些字符成为保留关键字(不能作为变量名或方法名或类名)。

        implementsinterfaceletpackageprivateprotectedpublicstaticyield

      2. 不允许在语句块(iffor)中使用函数声明。


ES6

参考:1.5万字概括ES6全部特性(已更新ES2020)

ES6是一个历史名词:一般指ES2015;也泛指ES5.1版以后的JS下一代标准,涵盖ES2015、ES2016、ES2017、ES2018、ES2019、ES2020等。

虽然用babel转译ES6,但依然有部分机型/浏览器无法解析转译后的ES5代码,且越新的语法内容越多设备不支持。

ECMAScript 2015新增

letconst

  1. letconst(与var的区别):

    1. (除了全局、函数作用域之外,)拥有块级作用域(声明变量仅在块级作用域中有效,离开块级作用域删除)。

      1. {/* 块级作用域 */}
      2. with(){/* 块级作用域 */}
      3. if(){/* 块级作用域 */}
      4. for、for-in、for-of(/* 块级作用域-父级 */){/* 块级作用域-子级 */}

        • 针对2个块级作用域,当闭包发生时(已经执行完毕,但异步任务返回父级作用域的变量):

          1. 若父级作用域使用var创建的变量,则返回该变量最终值(与外部值相同)。
          2. 若父级作用域使用letconst 无法改变值)创建的变量,则返回每一次循环时变量的值(外部不存在该变量)。
          e.g. ```javascript for (let i = 1; setTimeout(() => { console.log('let i1:', i)}, 50), i < 3; i++) { // => 1 => 2 => 3 setTimeout(() => { console.log('let i2:', i) // => 1 => 2 }, 1000) } for (var i = 1; setTimeout(() => { console.log('var i1:', i)}, 50), i < 3; i++) { // => 3 => 3 => 3 setTimeout(() => { console.log('var i2:', i) // => 3 => 3 }, 1000) } let i // 或`var i` for (i = 1; setTimeout(() => { console.log('i1:', i)}, 50), i < 3; i++) { // => 3 => 3 => 3 setTimeout(() => { console.log('i2:', i) // => 3 => 3 }, 1000) } ```

      除了forfor-infor-of的父级块级作用域和子级块级作用域有嵌套作用域关系,其他的块级作用域(包括循环forfor-infor-ofwhiledo-while的每一次迭代)都是互相独立,无法传递变量。

      1. while(){/* 块级作用域 */}do{/* 块级作用域 */}while()
      2. try{/* 块级作用域 */}catch(e){/* 块级作用域 */}finally{/* 块级作用域 */}
      3. switch(){/* 块级作用域 */}
      ES6之前可以用的块级作用域:with(不安全、不推荐使用)、try-catch ```javascript { // ES6的块级作用域 let a = 2 console.log(a) // => 2 } console.log(a) // => ReferenceError: a is not defined { try { throw undefined } catch (a) { // ES6之前的块级作用域模拟 a = 2 console.log(a) // => 2 } } console.log(a) // => ReferenceError: a is not defined ```
    2. 声明的全局变量不是 window 的属性。
    3. 暂时性死区(temporal dead zone):声明的变量直到控制流到达该变量被定义的代码行时才会被装载,所以在声明前使用会触发错误。

      必要时提升,但没有提升的作用。在初始化之前,变量处于临时死区中并不可被访问。

    4. 在同一作用域重复定义变量会抛出一个语法错误。
  2. const

    1. let基本一致。
    2. 只能在声明时赋值,之后修改会引发语法错误。

使用选择:用letconst完全代替var(不再使用 var);优先const,当确定需改变的变量才改用let

箭头函数

箭头函数是匿名函数,适合非方法函数(匿名函数、函数表达式)。

  1. 写法

    1. 函数体没有大括号,隐式返回表达式内容

      参数 => 表达式(一个或多个参数) => 表达式

      表达式是对象字面量时(期望返回这个对象字面量时),用()包裹,如:() => ({ a:1 })

    2. 函数体有大括号,不会自动返回内容(默认返回:undefined),需要显式return

      参数 => {块语句}

    3. 无参数

      () => 表达式_ => 表达式

    4. 没有内部名字的写法
    5. 与其他方法声明一样支持:形参的解构、默认参数、剩余参数,闭包等。
  2. 不会创建箭头函数自己的thisargumentssupernew.target,根据词法作用域的方式向上遍历查找。

    1. this

      不会创建自己的this(与function关键字、简写的方法不同),而使用封闭执行上下文最近的一个this值。因此对于this替代也无法改变箭头函数体内使用的this

      e.g. ```javascript function foo1 () { // 创建this return () => { // 不创建this return () => { // 不创建this return () => { // 不创建this console.log('1:', this.id1) // this指向foo1方法的this(父级创建) } } } } var f1 = foo1.call({ id1: 1 }) f1.call({ id1: 2 })()() // => 1: 1 f1().call({ id1: 3 })() // => 1: 1 f1()().call({ id1: 4 }) // => 1: 1 var foo2 = () => { // 不创建this return () => { // 不创建this return () => { // 不创建this return () => { // 不创建this console.log('2:', this.id2) // this指向全局对象window(父级若没有创建,则this指向全局) } } } } var f2 = foo2.call({ id2: 1 }) f2.call({ id2: 2 })()() // => 2: undefined f2().call({ id2: 3 })() // => 2: undefined f2()().call({ id2: 4 }) // => 2: undefined var foo3 = () => { // 不创建this console.log('3:', this.id3) // this指向全局对象window } foo3.bind({ id3: 1 })() // => 3: undefined foo3.call({ id3: 2 }) // => 3: undefined ```
  3. 不能作为构造函数(不能对箭头函数使用 new 创建实例)。
  4. 不能用作生成器(不能在箭头函数方法体内使用yield)。
  5. 没有原型属性prototype

简写对象的属性、方法

  1. 简写属性

    对象直接写变量:属性名为变量名, 属性值为变量的值。

    e.g. ```javascript var a = 'foo'; var b = 42; var c = { d: 'e' }; var obj = { a, b, c }; // 等价于:var obj = { a: a, b: b, c: c }; function f (x, y) { return { x, y }; // 等价于:return { x: x, y: y }; } ```
  2. 简写方法

     var obj = { // 可以使用计算属性名
       property1 (parameters) {},       // 等价于(普通方法): property1: function (parameters) {}
       * property2 (parameters) {},     // 等价于(生成器方法): property2: function * (parameters) {}
       async property3 (parameters) {}, // 等价于(async方法): property3: async function (parameters) {}
    
       get property4 () { return this.otherProp },      // 属性的取值器(getter)只能用这种简写方法方式
       set property4 (data) { this.otherProp = data }   // 属性的赋值器(setter)只能用这种简写方法方式
     }
    
    1. 简写的属性方法不能作为构造函数(不能对简写的属性方法使用new)。
    2. 简写的方法与function关键字一样产生this作用域。
    并非所有情况都可以用简写 ```javascript // 以下情况不适合用简写 var obj = { a: _.debounce(function () { // 使用apply的地方不能用箭头函数 console.log(this) }, 500) } ```

计算对象的属性名或方法名

[JS表达式](若JS表达式的值不是字符串,则会调用它的toString方法)

e.g. ```javascript var a = 'a b c' var b = { 'toString': () => 'bbb' } var obj = { // 不可以和简写属性一起使用 [a]: 1, // 可以和简写方法一起使用 [1 + a] () {}, [b]: function () {} } class Classname { [a] () {} } obj['a b c'] // 1 obj['1a b c'] // ƒ [1 + a] () {} obj['bbb'] // ƒ () {} Classname.prototype['a b c'] // ƒ [a] () {} ```

字符串的扩展

  1. 模板字符串(template literals)

    `内容`(返回字符串)

    1. 模板占位符

      ${部分JS表达式}(返回字符串),内部还可嵌套模板字符串:${部分JS表达式 + `另一个模板字符串` }

      若模板占位符内的结果是对象,则转换为字符串(值.toString())输出。

      • 不支持:

        1. 自动转义特殊字符
        2. XSS预防
        3. 格式化特定语言的数字、日期
        4. 循环语句、条件语句
    2. 转义

      除了字符串字面量转义内容'"不需要转义),还需转义:\` \${

    3. 多行书写

      空格、新行、缩进,原样输出至生成的字符串。

    4. String.raw`模板字符串`

      等价于:String.raw({ row: 可迭代对象 }[, 多个值])

      获取模板字符串的原始字面量值(将所有变量替换,且把\转义成\\)。

    5. 标签模板(tagged template literals)

      e.g. ```javascript function myTag (strings, ...exp) { console.log(strings) console.log(exp) } var person = 'Mike' var age = 28 myTag`that ${person} is a ${age}` // => ['that ', ' is a ', '', raw: ['that ', ' is a ', '']] // => ['Mike', 28] myTag`${'hello,'} that ${person} is a ${age}${222}` // => ['', ' that ', ' is a ', '', '', raw: ['', ' that ', ' is a ', '', '']] // => ['hello,', 'Mike', 28, 222] ```
  2. Unicode加强

    \u{代码点序列}

    e.g. '\u{1F4A9}' === '💩' === '\ud83d\udca9'

  3. 可以被for-of按完整字符遍历,forfor-in只能按1个字符-2个字节遍历。

解构赋值、默认参数、剩余参数、展开元素

默认参数用=设置默认值,对象的解构用:换变量名;Typescript用:定义形状。

  1. 解构赋值(destructuring assignment)

    1. 浅复制。
    2. 针对对象,解构自身和整条原型链([[Prototype]])上的(枚举+不枚举)属性(特殊:解构的剩余参数模式仅解构自身的属性)。
    1. 可迭代对象的解构:

      • 声明或赋值或函数形参:

        [多个变量名]=可迭代对象

      1. 可以嵌套任意深度的数组。

        e.g. [a, [b, [c]], d] = [null, [1, ['c']], {4: 'd'}]; // 等价于:a=null;b=1;c='c';d={4:'d'};

      2. 可以留空位跳过被解构数组中的元素。

        e.g. [a, , d] = [null, [1, ['c']], {4: 'd'}]; // 等价于:a=null;d={4:'d'};

      3. 解构内部支持:默认参数剩余参数(可嵌套)。

        e.g. ```javascript var [a, ...b] = [] // -> a等于undefined b等于[] var [c, ...d] = [1] // -> c等于1 d等于[] var [e, ...f] = [1, 2, 3] // -> e等于1 f等于[2, 3] var [g, ...[h, ...i]] = [1, 2, 3, 4] // -> g等于1 h等于2 i等于[3, 4] ```
    2. 对象的解构(ECMAScript 2018):

      • 声明或赋值或函数形参

        1. 声明:var {对象名}=对象(对象名为变量名)或var {对象名:对象值}=对象(对象值为变量名)
        2. 赋值:({对象名}=对象)(对象名为变量名)或({对象名:对象值}=对象)(对象值为变量名)

      e.g. ({a, b: c} = {a: 'a的值', b: 'c的值'}); // 等价于:a='a的值';c='c的值';(没有b的赋值)

      1. 可以嵌套任意深度的对象。

        e.g. ```javascript const user = { education: { degree: 'Masters' } } var { education: { degree } } = user // 仅定义degree var { education: { degree }, education } = user // 定义degree 和 education function a ({ education: { degree } }) { // 仅定义degree } a(user) ```
      2. 解构内部支持:默认参数剩余参数(剩余参数仅解构自身(不在原型链上)的属性,且剩余参数仅能作用于...变量名、不能再嵌套解构)。

        e.g. ```javascript var { a, ...b } = {} // -> a等于undefined b等于{} var { c, ...d } = { c: 1 } // -> c等于1 d等于{} var { e, ...f } = { f: 1, g: 2 } // -> e等于undefined f等于{ f: 1, g: 2 } ```
      3. 可以使用:计算对象的属性名或方法名。
      4. 可以对有特殊属性名的对象进行解构。

        e.g. var { '.a_b': a } = { '.a_b': 11 }; a === 11

    3. 基本数据类型的解构:

      1. nullundefined报错TypeError: null或undefined is not iterable (cannot read property Symbol(Symbol.iterator))
      2. 其他类型

        1. [变量名]=其他类型

          1. 字符串按顺序每一个字符赋值给每一个变量
          2. 除了字符串(可迭代对象)之外报错TypeError: undefined is not a function
        2. {变量名}=其他类型

          返回undefined,变量为默认参数值。

    4. 形参的解构:

      除了仅适用解构变量、不支持解构内部的剩余参数再嵌套解构之外,与非形参的解构一致。

      e.g. 1. 若需要解构形参是对象,则最佳实践:属性设置默认值、整个对象设置默认值`{}`。 >如:`{x = 0, y = 0} = {}`。 2. 若需要解构形参是数组,则最佳实践:项设置默认值、整个数组设置默认值`[]`。 >如:`[x = 0, y = 0] = []`。 ```typescript // 写法一(better than 写法二) function m1({x = 0, y = 0} = {}) { // 若传入的是undefined或不传参,则解构:{x = 0, y = 0} = {};否则解构:{x = 0, y = 0} = 传入的值 return [x, y]; } // 写法二(better than 没有加后面的默认值) function m2({x, y} = { x: 0, y: 0 }) { // 若传入的是undefined或不传参,则解构:{x, y} = { x: 0, y: 0 };否则解构:{x, y} = 传入的值 return [x, y]; } // 函数没有参数的情况 m1(); // [0, 0] m2(); // [0, 0] // x 和 y 都有值的情况 m1({x: 3, y: 8}); // [3, 8] m2({x: 3, y: 8}); // [3, 8] // x 有值,y 无值的情况 m1({x: 3}); // [3, 0] m2({x: 3}); // [3, undefined] // x 和 y 都无值的情况 m1({}); // [0, 0]; m2({}); // [undefined, undefined] m1({z: 3}); // [0, 0] m2({z: 3}); // [undefined, undefined] // 可迭代对象同理 function m3([x = 0, y = 0] = []) { return [x, y]; } m3(); // [0, 0] m3([1, 2]); // [1, 2] // typescript同理 function m1({x = 0, y = 0}: {x?: number; y?: number} = {}) { return [x, y]; } ```
    • 若解构没有对应值,则变量赋值为undefined
    • 避免被当做块语句导致错误。
  2. 默认参数(default parameters)

    形参名=JS值

    1. JS值可以使用前置的形参变量。
    2. 不设定默认参数,等效于设定形参名=undefined
    3. 当且仅当对应参数为undefined时才使用默认参数(不传参等效于传参为undefined)。
    4. 函数的默认参数
    5. 解构内部可以使用剩余参数;剩余参数可以被解构。
  3. 剩余参数(rest parameters)

    ...变量名(生成数组或对象,若没有项也生成[]{}

    1. 仅有最后一个参数可以被标记为剩余参数。
    2. 解构内部可以使用剩余参数;剩余参数可以被解构。
    e.g. ```javascript function a({ b, ...c }, ...d) { console.log(b, c, d); } a({ b: 1111, c: "asdasd", d: "asdasd" }, "asdasd", { asd: 123123 }); // => 1111 {c: "asdasd", d: "asdasd"} ["asdasd", {asd: 123123}] ```

ES标准规定:使用形参的解构默认参数剩余参数的函数体内,禁止使用 “use strict”

  1. 展开元素(spread operator)

    可迭代对象对象值或变量名的自身(不在原型链上)的属性,全部拆分出使用(浅复制)。

    1. 可迭代对象

      ...可迭代对象的值或变量名(非可迭代对象则报错TypeError: 某 is not iterable (cannot read property Symbol(Symbol.iterator))

      1. ...[]不产生任何效果。e.g. [...[]] // []
      2. 仅对可迭代的项能够展开,如:var a = []; a[1] = 'a1'; a['a'] = 'a2'; [...a] // [undefined, "a1"]
    2. 对象(ECMAScript 2018)

      ...对象的值或变量名(基本数据类型则不产生任何效果)

      1. ...{}...undefined不产生任何效果。e.g. {...{}} // {}{...undefined} // {}
      2. 仅对可枚举的项能够展开。

在某种程度上,剩余参数展开元素相反:剩余参数会收集多个元素和「压缩」成一个单一的元素,产生新的变量;展开元素会「展开」变成多个元素,产生用逗号分隔的参数序列。

ES6 Module

参考:阮一峰:Module 的语法阮一峰:Module 的加载实现

一个模块就是一个独立的文件。

.js.mjs文件、<script>遵循相同模块规则。

  1. export

    模块可以导出多个内容,导出变量名不能重复(因此default只能导出一次)。

    default可以当作导出的默认变量。

    1. export 声明语句
    2. export {变量[, 变量]}
    3. export {变量 as 外号变量[, 变量 as 外号变量]}

      避免重命名;可以同一个变量使用多个外号变量。

    4. export {变量[, 变量]} 或 {变量 as 外号变量[, 变量 as 外号变量]} 或 * form '模块'

      export * form '模块'导出除了default的内容,可以用export { default } from '模块'单独导出default

      将其他模块的变量导入再导出,但本模块无法使用。

      e.g. 跨模块常量案例: ```javascript /* 单个常量文件 */ // constants/db.js export const db = { url: 'http://my.couchdbserver.local:5984', admin_username: 'admin', admin_password: 'admin password' }; // constants/user.js export const users = ['root', 'admin', 'staff', 'ceo', 'chief', 'moderator']; /* 合并到文件 */ // constants/index.js export { db } from './db'; export { users } from './users'; /* 要使用的文件引入 */ // script.js import { db, users } from './constants/index'; ```

    导出default和导出{变量}的区别:Stack Overflow: When should I use curly braces for ES6 import?

    1. export default 表达式 === export {变量 as default}

      e.g. ```javascript /* 表达式 */ number + 1 function () {} ok ? 'YES' : 'NO' Array.from(words).reverse().join('') /* 是语句,不是表达式 var a = 1 流控制不会生效,请使用三元表达式 if ... */ ```

    不允许:export 值或变量名或方法名或类名。必须输出接口名声明{变量名或方法名或类名})。

  2. import

    1. import {导出的变量[, 导出的变量]} from '模块'

      不允许 import {default} from '模块',因为default是关键字,不能作为变量名;允许import {default as 外号变量} from '模块'

    2. import {导出的变量 as 外号变量[, 导出的变量 as 外号变量]} from '模块'

      避免重命名。

      • 语法不支持直接在导入时解构

        e.g. import { 变量: { 解构变量 } } from '模块'import { 变量 as 外号变量 : { 解构变量 } } from '模块'、等。

    3. import 外号变量 from '模块' === import {default as 外号变量} from '模块'

      仅接受模块导出的default内容。

      不能直接解构default 需要2行代码进行: ```javascript import x, { c } from "./x"; const { a, b } = x; // ./x.js export default { a: 'a', b: 'b' } export const c = 'c' ```
    4. import * as Module实例 from '模块'

      导出的变量(包括default)都成为Module实例的属性(相当于导出命名空间),以Module实例.导出的变量使用。Module实例Module实例.导出的变量都是只读的,不可以赋值改变。

    5. import '模块'

      不引入模块里导出的内容,仅执行该模块代码。

使用ES6 Module前提 1. 浏览器 1. 开启浏览器Module功能: 1. Chrome地址输入`chrome:flags`,打开`Experimental Web Platform`。 2. Firefox地址输入`about:config`,打开`dom.moduleScripts.enabled`。 3. Edge 地址输入`about:flags`,打开`Experimental JavaScript Features`。 2. 在`

Promise

  1. Promise实例拥有2个隐藏属性:

    1. [[PromiseStatus]]:状态(pendingresolvedrejected
    2. [[PromiseValue]]:返回值
  2. Promise构造函数:

    1. new Promise((resolve, reject) => {/* resolve(参数) 或 reject(参数) */}) // 第一参数必填且必须是方法

      创建一个Promise实例。调用方法内部的resolve则类似Promise.resolve(参数),调用方法内部的reject则类似Promise.reject(参数)

      1. 在Promise实例内部抛出错误被Promise实例获取,则返回失败状态,值为错误信息,函数体内不再继续向下执行,不会向上抛出错误。
      2. 调用resolvereject虽然已经确定了状态,但还会继续向下执行剩余函数体,之后抛出的错误不计算在Promise内,会向上抛出错误。
    2. Promise.all(可迭代对象)

      可迭代对象都完成则完成,有任一失败则失败。

      向下链式传递的Promise实例[[PromiseValue]]为:所有成功项Promise实例[[PromiseValue]]组成的数组、或第一个失败项Promise实例[[PromiseValue]]

    Promise.allPromise.any是相反的。

    1. Promise.any(可迭代对象)(ECMAScript 2021)

      若只要其中的一个成功,则返回那个已经成功的promise;若可迭代对象中没有一个成功(即所有的promises都失败),则返回一个失败的promise和AggregateError类型(用于把单一的错误集合在一起)的实例。

    2. Promise.race(可迭代对象)

      可迭代对象首个完成则完成,首个失败则失败。

    3. Promise.allSettled(可迭代对象)(ECMAScript 2020)

      类似Promise.all,区别在于会等待参数全部处理完毕后再统一返回,不会短路。

    4. 手动创建完成/失败的Promise实例

      1. Promise.resolve(参数) // 等价于:new Promise(resolve => resolve(参数))

        • 不同参数类型对应的返回内容:

          1. Promise实例:原封不动返回这个Promise实例。
          2. 拥有then属性方法的对象:将这个对象转为Promise实例,然后立即执行这个对象的then方法。
          3. 其他:完成状态的Promise实例,参数作为Promise实例[[PromiseValue]]
      2. Promise.reject(参数) // 等价于:new Promise((resolve, reject) => reject(参数))

        失败状态的Promise实例,参数作为Promise实例[[PromiseValue]]

  1. new Promise(回调)的回调、Promise.all/race/any/allSettled([回调])的回调、Promise.resolve/reject(),都是同步任务。
  2. Promise.prototype.then/catch/finally(回调)的回调,都是异步任务(microtask)。
  1. Promise原型链(继承给所有实例)

    1. Promise.prototype.then(resolve回调函数, reject回调函数)

      Promise实例完成/失败则执行对应回调。接受前一个链式return的值的[[PromiseValue]]作为参数;回调函数return的值作为Promise实例继续向下链式传递。

    2. Promise.prototype.catch(reject回调函数)

      Promise实例失败则执行回调(Promise实例成功则跳过不执行)。接受前一个链式return的值的[[PromiseValue]]作为参数;回调函数return的值作为Promise实例继续向下链式传递。

      因为链式的需要,建议then不要添加第二个参数,而都用catch处理失败情况。

    then/catch)链式调用:后面链式内容根据前面回调函数返回值判断是否执行,参数和状态为前面链式返回的Promise实例[[PromiseValue]][[PromiseStatus]]。每次链式调用thencatch都会产生一个新的Promise实例,新生成的Promise实例就是thencatch的返回(若返回非Promise类型则返回值类似包裹着Promise.resolve(参数),若回调函数内抛出错误则返回rejected

    1. Promise.prototype.finally(函数)(ECMAScript 2018)

      1. 无论Promise实例最终状态如何(完成/失败)都会执行函数;
      2. 不接受任何参数、无法知道Promise实例的完成/失败状态;
      3. finally的回调函数return的值只有失败状态(如:return Promise.reject(信息))才作为Promise实例向下链式传递,否则向下链式传递的上一个链式的Promise实例(上一个状态可以是完成/失败)。
e.g. ```javascript const promiseObj = new Promise((resolve, reject) => { resolve(data); // 或失败:reject(err) }) .then((data) => { if (data.result === 0) { // 业务逻辑判断 // 可以继续return另一个Promise } else { throw new Error(data.message) // 或:return Promise.reject(data.message); } }) .catch((msg) => { console.warn(msg); // 统一处理错误,还可以向外抛出失败状态:throw new Error(msg)或return Promise.reject(msg) }) .finally(() => { // 无论如何都执行 }) promiseObj.then((data) => { // 上面的Promise得出结果之后进行 }); ```

可迭代对象、异步可迭代对象

  1. 可迭代对象(iterable):数据结构拥有[Symbol.iterator]属性方法(迭代器接口),调用返回迭代器。

    • 可迭代对象的作用语法:

      1. for-of
      2. ...可迭代对象
      3. yield * 可迭代对象
      4. 可迭代对象的解构赋值

      返回的值:调用可迭代对象的[Symbol.iterator]方法,获得迭代器,再遍历调用迭代器的next方法获得对象的value值,返回,直到对象的done属性为true。

  2. 迭代器(iterator,遍历器):对象实现next方法(returnthrow方法可选),该方法返回包含donevalue属性的对象。

  3. 异步可迭代对象(asynchronous iterable):数据结构拥有[Symbol.asyncIterator]属性方法(异步迭代器接口),调用返回异步迭代器。
  4. 异步迭代器(asynchronous iterator,异步遍历器):类似迭代器,区别是next方法返回一个Promise实例(其完成之后返回包含donevalue属性的对象)。
e.g. ```javascript const arr = ['a', 'b'] // 数组,是可迭代对象 const iter = arr[Symbol.iterator]() // 拥有next方法返回done、value属性组成的对象,是迭代器 iter.next() // { value: 'a', done: false } iter.next() // { value: 'b', done: false } iter.next() // { value: undefined, done: true } ```
  1. 原生的可迭代对象:Array「TypedArray」MapSetargumentsNodeListString生成器
  2. 自定义:可迭代对象、异步可迭代对象 ```javascript const obj1 = { // 可迭代对象 [Symbol.iterator] () { let i = 0 return { // 迭代器 next () { i++ if (i < 10) { return { done: false, value: i } } else { return { done: true, value: undefined } } } } } } const iter1 = obj1[Symbol.iterator]() // 迭代器 iter1.next() // {done: false, value: 1} const obj2 = { // 可迭代对象 [Symbol.iterator]: function * () { yield 1 yield 2 yield 3 } } const iter2 = obj2[Symbol.iterator]() // 迭代器 iter2.next() // {done: false, value: 1} const obj3 = { // 异步可迭代对象 [Symbol.asyncIterator]: () => { const items = 'for-await-of'.split('') return { next: () => { return new Promise(resolve => { setTimeout(() => { resolve({ done: items.length === 0, value: items.shift() }) }, 500) }) } } } } const iter3 = obj3[Symbol.asyncIterator]() // 异步迭代器 iter3.next() // Promise实例,完成后值为{done: false, value: 'f'} ```

for-of

for-in建议仅遍历对象。

  1. 遍历可迭代对象自身的项
  2. 可以正确响应breakcontinuereturn
若要额外获得每一项的key 1. 额外变量自增记录。 2. 改用`Array/Map/Set.prototype.forEach`。 3. `for (let [key, value] of Object.entries(可迭代对象)) {}`。

for-await-of(ECMAScript 2018)

遍历可迭代对象或异步可迭代对象自身的项。调用自定义迭代钩子,并为每个不同属性的值执行语句。

e.g. ```javascript async function process (iterable) { // 传入 可迭代对象 或 异步可迭代对象 for await (let val of iterable) { // val:(异步)可迭代对象的(异步)迭代器执行next返回的(完成了的)对象中的value属性值 console.log(val) } } process(['a', 'b', 'c']) // microtask输出:'a' 'b' 'c' // 异步可迭代对象 const asyncIterable = { [Symbol.asyncIterator]: () => { const items = '异步可迭代对象'.split('') return { next: () => { return new Promise(resolve => { setTimeout(() => { resolve({ done: items.length === 0, value: items.shift() }) }, 500) }) } } } } process(asyncIterable) // microtask每隔500输出:'异' '步' '可' '迭' '代' '对' '象' ```

生成器(generators)

调用的生成器,是可迭代对象、也是迭代器。生成器内建[Symbol.iterator]next实现。

  1. function *声明、yield语句。
  2. 执行步骤:

    1. 调用生成器,返回一个生成器对象,函数体冻结不执行任何代码。
    2. 每次调用生成器对象的next,函数解冻并运行至下一个yield(或return),再次冻结。

      1. 返回值的valueyieldreturn后的表达式,且是惰性求值,只有执行到时才会执行表达式。

        1. 若函数体执行完毕(return),则doneture;否则donefalse
        2. 若函数体执行完毕之后继续调用next,则返回固定的{ value: undefined, done: true }
      2. yield的返回值,是下一次调用next传入的参数(默认:undefined)。

        因此第一次调用next的传参没有意义。

    e.g. ```javascript function * helloWorldGenerator () { alert(yield 'hello') var a = 'very' + (yield 'world') return a } var hw1 = helloWorldGenerator() // 不执行任何函数体内代码 hw1.next() // 执行至第一个`yield`之前,`yield`冻结(未产生返回值);把`yield`后的表达式的值作为value,`next`返回:{ value: 'hello', done: false } hw1.next() // 上次冻结处`yield`返回值为此处`next`传入参数;执行至下一个`yield`之前:`alert(undefined)`;把`yield`后的表达式的值作为value,`next`返回:{ value: 'world', done: false }, hw1.next() // 上次冻结处`yield`返回值为此处`next`传入参数;执行至`return`:`var a = 'very' + undefined`;把`return`后的表达式的值作为value,`next`返回:{ value: 'veryundefined', done: true } hw1.next() // 无函数体执行,`next`返回:{ value: undefined, done: true } hw1.next() // 无函数体执行,`next`返回:{ value: undefined, done: true } var hw2 = helloWorldGenerator() hw2.next(1) // 返回:{ value: 'hello', done: false } hw2.next(2) // 执行:`alert(2)`,返回:{ value: 'world', done: false } hw2.next(3) // 执行:`var a = 'very' + 3`,返回:{ value: 'very3', done: true } hw2.next(4) // 返回:{ value: undefined, done: true } hw2.next(5) // 返回:{ value: undefined, done: true } ```

建议使用async-await替代生成器。

async-await(ECMAScript 2017)

是生成器的语法糖:将定义generator函数的星号*替换成async,将yield替换成await

  1. 执行步骤:

    1. 内置执行器,调用即可执行直到遇到awaitawait后若是方法则同步执行该方法),等待await完成后(Promise)继续执行剩余函数体;

      await后的剩余函数体:对这个async而言是同步的执行的代码,因此可以被try-catch捕获错误;对JS事件循环而言是异步任务microtask。

    2. await后的表达式类似包裹着Promise.resolve(表达式)

      await返回的是后面的[[PromiseValue]]。如:若a = await Promise.resolve(值),则a === 值a不是Promise实例)。 1. 若`var a = await Promise.resolve('值value')`,则`a === '值value'`。 2. 若`var a = await Promise.reject('值value')`,则不会往下执行,不会执行到`var a = `的赋值操作。
    3. async固定返回Promise实例(若返回非Promise实例,则返回值类似包裹着Promise.resolve(返回值)),在函数体返回前,是未完成状态;

      若因为函数体内没有await而去除async标志,要注意此时的函数返回由原来返回Promise实例可能变成非Promise实例,影响调用函数之后是否可以链式调用Promise原型链方法(then/catch/finally)。

    4. 返回:

      1. await返回失败的Promise或async内部的错误(均表现为向上抛出错误异常,异常均可用try-catch捕获化解),不再继续向下执行函数体,导致async返回值为失败的Promise,Promise实例[[PromiseValue]]为错误/失败信息;

        async方法内部未捕获的失败Promise实例,不会被async内部处理(try-catch包裹也不会处理)。未捕获的失败Promise实例会向全局抛出。

      2. 否则直到函数体执行完毕,根据async返回值决定Promise状态。

      async function func () { setTimeout(() => { 错误 }, 0) }不会捕获异步操作中的错误(同理,在try-catchPromise等语法中的异步错误也无法被捕获,但可以捕获awaitreject)。可以在异步回调内部再包一层try-catch、或用windowerror事件捕获。

  2. 使用形式 ```javascript // 函数声明 async function foo1 () {} foo1().then(...) // 函数表达式 const foo2 = async function () {} foo2().then(...) // 箭头函数 const foo3 = async () => {} foo3().then(...) // 对象的方法 let obj = { async foo4 () {} } obj.foo4().then(...) // Class的方法 class Storage { constructor () { this.cachePromise = caches.open('avatars') } async getAvatar (name) { const cache = await this.cachePromise return cache.match(`/avatars/${name}.jpg`) } } const storage = new Storage() storage.getAvatar('jake').then(…) // 回调函数(匿名函数) dom.addEventListener('click', async function () { console.log(1) await new Promise(() => {}) console.log(2) }) // 自执行匿名函数 ;(async function () {}()) ```
e.g. ```javascript // 模拟异步操作 function asyncFunc (ms = 1000) { return new Promise((resolve, reject) => { if (Math.random() > 0.5) { setTimeout(resolve.bind(null, { code: 200, msg: '成功信息xx' }), ms) } else { setTimeout(reject.bind(null, new Error('失败信息xx')), ms) } }) } async function a () { try { console.log('1. 同步执行') let result = await asyncFunc() // await方法抛出错误或返回失败的Promise,则不再向下执行,直接进入错误处理的catch;否则函数向下执行 console.log('2. 异步执行。会在上一行代码的await处等待Promise结果成功后才会执行,如果上一行代码的await返回失败,则上面就会抛出错误,错误没有被解决则此行代码不会被执行') // let [result2, result3] = await Promise.all([asyncFunc(), asyncFunc()]) // 同时触发 if (result && result.code === 200) { // 业务逻辑判断 // 可以继续await一个方法 console.log(result.msg) } else { throw new Error('返回值不满足判断条件') // 或:return Promise.reject('返回值不满足判断条件'); } } catch (e) { console.warn(e.message) // 统一处理错误,还可以向外抛出失败状态:throw new Error(msg)或return Promise.reject(msg) } finally { // 无论如何都执行 } } /* 使用测试 */ a().then(() => {}, () => {}) // async方法返回的是Promise实例;若方法体内抛出错误则状态失败,否则状态完成(包括默认返回的undefined);返回值或抛出异常值为向下传递的值 ```

classclass-extends

构造函数(原型链)的语法糖。class的数据类型是function

  1. 类声明时:

    1. 类内部定义的static属性/方法直接是类的属性
    2. 类内部定义的所有方法都在类.prototype
    3. 类内部定义的属性是实例的属性

    类声明时,类内部定义的属性/方法都不可枚举(类内部定义的静态属性是可枚举)、且方法都在严格模式下运行。

  2. 类内部的方法(尤其是constructor)内能新增实例的属性/方法类.prototype.属性/方法

    实例化时(constructor)、或实例化之后(实例调用方法)触发:

    1. this.新增属性 = 新值:新增实例的属性/方法
    2. this.__proto__.新增属性 = 新值:新增类.prototype.属性/方法
  3. 类声明完毕之后:

    1. 可以在类.prototype上再添加的属性/方法:

      1. 类.prototype.新增属性 = 新值
      2. Object.assign(类.prototype, { 新增属性: 新值 })
      3. Object.defineProperty(类.prototype, '新增属性', 数据属性或访问器属性)(或Object.defineProperties
    2. 可以在上再添加静态方法:

      类.新增属性 = 新值

      新增的内容为:可枚举(若属性描述为不可枚举则不可枚举)、在严格模式下运行。

  4. 必须用new调用类,否则报错TypeError: Class constructor 类名 cannot be invoked without 'new'
  5. this指向:

    1. 内部定义的函数(包括箭头函数)的this指向实例或类名(static)
    2. 外部定义

      1. 外部定义的非箭头函数的this指向实例或类名(static)
      2. 外部定义的箭头函数的this指向window或global(严格模式为undefined)
  6. 类不存在变量提升(要先声明类才能使用)。

    原因:类可以继承、且类可以表达式写法,必须保证子类在父类之后定义。 ```javascript let Foo = class {}; class Bar extends Foo {} // 若变量提升,则Foo还未定义,导致出错 ```
// 类声明
class 类名 {  // typeof 类名 === 'function'; 类名.name === '类名'
  // 内部方法在严格模式下运行
  // 没有`function`、没有`,`

  // 无法引用到 constructor(除了 子类在其构造函数内使用`super()`执行父类的构造函数 之外)
  // `类名.constructor === Object.constructor`(不知道指向哪里)
  // `类名 === 类名.prototype.constructor === 实例.__proto__.constructor`(指向类本身,而不指向内部的`constructor`方法)
  // constructor不是静态方法,`static constructor () {}`不是类名的构造函数
  constructor () {  // 在`new 类名(参数)`时执行
    // this指向实例
  }

  // 类名.prototype.原型链方法1
  // 实例通过原型链调用
  原型链方法1 () {
    // this指向实例
  }

  // 类名.prototype.原型链属性1
  // 实例后会在实例中也创建一个属性
  get 原型链属性1 () {
    // this指向实例
    return
  }
  set 原型链属性1 (value) {
    // this指向实例
  }

  // 实例上的属性(原型和类名上不存在)
  属性1
  属性2 = '初始值'
  属性3 = () => {
    // this指向实例
  }
  属性4 = function () {
    // this指向实例
  }

  // 类名.静态属性/静态方法
  // 可以和非静态属性/非静态方法重名
  static 静态属性1
  static 静态属性2 = '初始值'
  static 静态属性3 = () => {
    // this指向类名
  }
  static 静态属性4 = function () {
    // this指向类名
  }
  static 静态方法1 () {
    // this指向类名
  }

  * [Symbol.iterator] () { // for-of遍历实例时候执行
    // this指向实例
  }
}

// 外部新增的方法默认不在严格模式下运行

// 类名.静态属性5/静态方法2
类名.静态属性5 = ''
类名.静态方法2 = ()=>{
  // this指向window或global(严格模式为undefined)
}
类名.静态方法3 = function () {
  // this指向类名
}

// 类名.prototype.原型链属性1/原型链方法2
// 实例通过原型链调用
类名.prototype.原型链属性1 = ''
类名.prototype.原型链方法2 = ()=>{
  // this指向window或global(严格模式为undefined)
}
类名.prototype.原型链方法3 = function () {
  // this指向实例
}

console.log(Object.getOwnPropertyNames(类名))
// => ["length", "prototype", "静态方法1", "name", "静态属性1", "静态属性2", "静态属性3", "静态属性4", "静态属性5", "静态方法2", "静态方法3"]

// 类表达式
const 类名 = class {}         // 类名.name === '类名'
const 类名 = class 内部类名 {} // 类名.name === '内部类名'


// 类的原型链
类名.prototype.constructor === 类名     // true
new 类名().__proto__ === 类名.prototype // true
// new 类名().__proto__.constructor === new 类名().constructor === 类名 // true

super

  1. 指向当前对象的原型对象(只允许在对象的简写方法中使用,且必须带有属性/方法super.属性/方法)。
  2. class-extends

    1. 子类的构造函数中指向父类构造函数的调用(只允许在子类的构造函数中使用super());
    2. 子类的任意函数中指向父类方法的访问(只允许在子类中使用,且必须带有属性/方法:super.属性/方法)。
    3. super调用的父级方法中的this,均指向子类实例或子类。
    1. 通过super()调用父类构造函数(父类方法中的this指向子类实例)。

      给子类的实例添加父类的实例的属性

    2. 引用

      1. 通过super.属性/方法访问父类.prototype.属性/方法(父类方法中的this指向子类实例)。
      2. 在静态方法中,通过super.属性/方法访问为父类.静态属性/静态方法(父类静态方法中的this指向子类)
    3. 赋值(等价于this.属性 = 新值

      1. super.属性 = 新值为子类实例赋值。
      2. 在静态方法中,super.属性 = 新值为子类赋值(静态属性/静态方法)。

new.target

  1. 返回new命令作用于的那个构造函数。

    若子类继承父类,则super调用父级时,new.target指向子类。

  2. 若函数不是通过 new 命令调用,则返回undefined
  3. 若在函数外部使用,则报错SyntaxError: new.target expression is not allowed here
e.g. ```javascript class Father { constructor() { console.log(new.target.name); } } class Son extends Father { constructor() { super() console.log(new.target.name); } } new Father() // => Father new Son() // => Son => Son new.target // Uncaught SyntaxError: new.target expression is not allowed here ```

Symbol

Symbol([描述])Symbol.for([描述])Symbol.标准属性

描述若是对象,则调用其toString方法,返回值为描述内容。

新增的基本数据类型。可用作对象的属性键(唯一作用),能避免命名冲突的风险(创建一个Symbol类型的值与其他任何值不相等)。

  1. 作为属性键

    1. 不被大部分遍历方法返回:

      for-inObject.entries/values/keys/getOwnPropertyNamesJSON.stringify

    2. 能够返回:

      Object.getOwnPropertySymbols、对象的展开元素、Map类型的遍历、Reflect.ownKeys

  2. 不可更改。
  3. 不可字符串拼接(+`${Symbol类型的值}`)。
  4. 是基本数据类型,不能添加属性。

SetMapWeakSetWeakMap

  1. Set

    不重复值的集合(通过类似===判断是否相同,额外能判断NaN === NaN成立)。

    1. 遍历方法遍历的顺序按照插入的顺序。
    2. 可以直接用for-of遍历、直接用...Set类型的值拆分。

      每项输出

    方法、属性 1. `new Set(可迭代对象)` 2. `Set.prototype.size` 3. `Set.prototype.has(值)` 4. `Set.prototype.add(值)` 5. `Set.prototype.delete(值)` 6. `Set.prototype.clear()` 7. `Set.prototype.forEach(回调函数(当前值, 索引也是当前值, Set整体)[, this替代])` 8. `Set.prototype.keys()` 9. `Set.prototype.values()` 10. `Set.prototype.entries()`
  2. Map

    类似对象的hash结构,键-值的可以是任何值(对象的键只能是StringSymbol类型,若不是,则会使用键.toString()转换后的字符串作为键)。

    1. 遍历方法遍历的顺序按照插入的顺序。
    2. 可以直接用for-of遍历、直接用...Map类型的值拆分。

      每项输出[键, 值]

    3. Symbol类型的键名也可以遍历。
    方法、属性 1. `new Map(内部项为 「可迭代对象 或 长度为2的数组」 的 可迭代对象)` >
    >e.g. > >```javascript >var a = new Map( > new Set([ > ['a', 'b'], > ['c', 'd'] > ]) >) > >var b = new Map( > [ > new String('ab'), > new String('cd') > ] >) > >var c = new Map( > [ > ['a', 'b'], > ['c', 'd'] > ] >) >``` >
    2. `Map.prototype.size` 3. `Map.prototype.has(键)` 4. `Map.prototype.get(键)` 5. `Map.prototype.set(键, 值)` 6. `Map.prototype.delete(键)` 7. `Map.prototype.clear()` 8. `Map.prototype.forEach(回调函数(当前值, 当前键, Map整体)[, this替代])` 9. `Map.prototype.keys()` 10. `Map.prototype.values()` 11. `Map.prototype.entries()`
  3. WeakSet

    Set类似(不重复的值的集合)。

    1. 参数的成员值必须是:引用数据类型。
    2. 成员不可枚举、不可遍历。
    3. 弱引用:WeakSet的成员值引用的对象不计算被WeakSet引用次数。若其成员值引用的对象被垃圾回收机制释放,则这个成员被移除。
    仅支持的方法 1. `new WeakSet(可迭代对象)` 2. `WeakSet.prototype.has(值)` 3. `WeakSet.prototype.add(值)` 4. `WeakSet.prototype.delete(值)`
  4. WeakMap

    Map类似(键可以是任何值)。

    1. 参数的成员键必须是:引用数据类型。
    2. 成员不可枚举、不可遍历。
    3. 弱引用:WeakMap的成员键所指向的对象不计算被WeakMap引用次数。若其成员键引用的对象被垃圾回收机制释放,则这个成员被移除。
    仅支持的方法 1. `new WeakMap(内部项为 「可迭代对象 或 长度为2的数组」 的 可迭代对象)` 2. `WeakMap.prototype.has(键)` 3. `WeakMap.prototype.get(键)` 4. `WeakMap.prototype.set(键, 值)` 5. `WeakMap.prototype.delete(键)`

数值的扩展

  1. 新增2进制、8进制写法

    1. 2进制:

      0b二进制数0B二进制数

    2. 8进制:

      0o八进制数0O八进制数

      0八进制数(ES5,不推荐)

  2. NumberMath对象的扩展

Proxy

new Proxy(target, handler)

拦截原始语言功能。

handler可用的拦截属性方法 1. `get` 2. `set` 3. `has` 4. `ownKeys` 5. `getOwnPropertyDescriptor` 6. `defineProperty` 7. `preventExtensions` 8. `getPrototypeOf` 9. `isExtensible` 10. `setPrototypeOf` 11. `apply` 12. `construct`

Reflect

操作对象的默认行为。

Proxy的handler方法一一对应的静态函数 1. `Reflect.get` 2. `Reflect.set` 3. `Reflect.has` 4. `Reflect.ownKeys` 5. `Reflect.getOwnPropertyDescriptor` 6. `Reflect.defineProperty` 7. `Reflect.preventExtensions` 8. `Reflect.getPrototypeOf` 9. `Reflect.isExtensible` 10. `Reflect.setPrototypeOf` 11. `Reflect.apply` 12. `Reflect.construct`

BigInt(ECMAScript 2019)

  1. 支持各种进制数。

ECMAScript 2016新增

  1. 新增:Array.prototype.includes
  2. 新增:**幂运算符

    类似于Math.pow。e.g. 2 ** 3 === 8 /* 2的3次方 */

ECMAScript 2017新增

  1. 新增:async-await语法
  2. 新增:Object.entriesObject.valuesObject.getOwnPropertyDescriptors
  3. 新增:String.prototype.padStartString.prototype.padEnd
  4. 新增:支持函数参数列表和调用中的尾逗号(e.g. function func(a, b, c,) {}; func(1, 2,)
  5. 新增:SharedArrayBufferAtomics(共享内存位置读取和写入)

ECMAScript 2018新增

  1. 新增:对象的解构赋值、对象的展开元素
  2. 新增:正则表达式:命名捕获组、Unicode转义、反向断言、dotAll模式
  3. 新增:Promise.prototype.finally
  4. 新增:for-await-of
  5. 移除带标签的模版字符串中转义序列的语法限制

    遇到不合法的字符串转义返回undefined,并且从raw上可获取原字符串。

ECMAScript 2019新增

  1. 新增:行分隔符(U+2028)和段分隔符(U+2029)符号现在允许在字符串文字中,与JSON匹配
  2. 更改:JSON.stringify

    可返回不符合UTF-8标准的字符串。

  3. 新增:String.prototype.trimStartString.prototype.trimEnd
  4. 新增:Object.fromEntries
  5. 更改:Array.prototype.sort稳定性

    排序关键字相同的项目其排序前后的顺序不变,默认为稳定。

  6. 新增:Array.prototype.flatArray.prototype.flatMap

    扁平化数组,返回新数组;映射且扁平化数组,返回新数组(只能展开一层数组)。

  7. 更改:Function.prototype.toString现在返回精确字符,包括空格和注释,函数原始代码(与编码一致)。
  8. 更改:try-catch可以使用catch(e){}catch{};修改 catch 绑定
  9. 新增:Symbol.prototype.description

ECMAScript 2020新增

  1. 新增:BigInt

    可以超过Number.MIN_SAFE_INTEGERNumber.MAX_SAFE_INTEGER

  2. 新增:Promise.allSettled
  3. 新增:可选链?.(若操作符前是undefined/null则返回undefined,否则返回右边的属性值)

    e.g. null?.anull?.['a'+'b']null?.[0]null?.()

    1. 可选链不能用于赋值

      e.g. object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment

    2. 当在表达式中使用可选链时,若左操作数是nullundefined,表达式将不会被计算

      e.g. object?.[x++]; // 若object为null或undefined,则x++不会进行执行

  4. 新增:空值合并运算符??(若操作符左边的值是undefined/null则使用操作符后面的值)
  5. 新增:动态引入import()(返回Promise实例)
  6. 新增:globalThis

     // ECMAScript 2020之前的解决方案
     const getGlobal = function(){
       if(typeof self !== 'undefined') return self
       if(typeof window !== 'undefined') return window
       if(typeof global !== 'undefined') return global
       throw new Error('unable to locate global object')
     }
    
     // ECMAScript 2020内置
     globalThis
    
  7. 新增:String.prototype.matchAll
  8. 更改:for-in标准化遍历顺序

    不同的引擎已就如何迭代属性达成一致,从而使行为标准化。

ECMAScript 2021新增

  1. 新增:String.prototype.replaceAll
  2. 新增:Promise.any
  3. 新增:||=&&=??=

    1. a ||= b等价于a || (a = b)
    2. a &&= b等价于a && (a = b)
    3. a ??= b等价于a ?? (a = b)
  4. 新增:WeakRef
  5. 新增:_分隔数字

    e.g. 1_00 === 1001_00 === 10_0


Web API标准(部分)

文档对象模型(DOM)

document

来自:MDN:document

  1. 获取DOM

    1. 方法

      1. document.querySelector(CSS选择器)

        1. dom.querySelector(CSS选择器)
        2. 从自己开始(包括自己)查找最近的一个祖先元素dom.closest(CSS选择器)
      2. document.querySelectorAll(CSS选择器)

        dom.querySelectorAll(CSS选择器)

      3. document.getElementById(Id名)
      4. document.getElementsByTagName(标签名)

        document.getElementsByTagNameNS(命名空间, 标签名)

      5. document.getElementsByClassName(类名)
      6. document.getElementsByName(name属性)
    2. 属性(只读)

      1. document.documentElement

        返回文档的根元素(如:HTML的<html>)。

        document.getElementsByTagName('html')[0] === document.documentElement

      2. document.body

        (可写)返回文档的<body><frameset>

        document.getElementsByTagName('body')[0] === document.body

      3. document.scrollingElement

        返回document.documentElementdocument.body

        document.scrollingElement === document.documentElement || document.body

      4. document.head

        返回文档中<head>

        document.getElementsByTagName('head')[0] === document.head

      5. document.styleSheets

        返回文档中<style><link rel="stylesheet">组成的数组。

      6. document.scripts

        返回文档中<script>组成的数组。

      7. document.images

        返回文档中<img>组成的数组。

      8. document.links

        返回文档中具有href属性的<area><a>组成的数组。

      9. document.embeds

        返回文档中<embed>组成的数组。

      10. document.forms

        返回文档中<form>组成的数组。

  2. document.execCommand(命令的名称, false, 额外参数)

    操作contenteditable="true"的DOM文本选区覆盖的内容。

    操作的内容会读取原本已经应用的CSS内容。

    • document.queryCommandState(命令的名称)

      检查当前光标所在地方是否有某种样式,返回true/false

Canvas

来自:MDN:Canvas

<canvas id="j=canvas"></canvas>

<script>
  const canvas = document.getElementById('j-canvas')
  const ctx = canvas.getContext('2d')
</script>
html2canvas踩坑 1. 在iOS,针对`font-size: 0`或`line-height: 0`会产生一些错误渲染问题。 2. 用``代替 ~~`background-image`等css背景~~,解决图片模糊问题。 3. 注意`scale`参数,可以设置为固定(如:2)来覆盖默认的 ~~`window.devicePixelRatio`~~,避免canvas渲染过大。 4. 注意设置固定的`width`、`windowWidth`、`height`、`windowHeight`,避免高分辨率的浏览器canvas渲染过大。 考虑保证:`width === windowWidth`、`height === windowHeight`。 e.g. ```javascript html2canvas(document.getElementById("j-html2canvas"), { scale: 2, windowWidth: 640, windowHeight: 1136, width: 640, height: 1136 }).then(canvas => { let url = ""; if (isAndroid) { url = canvas.toDataURL("image/webp"); } else { url = canvas.toDataURL("image/jpeg", 0.8); } }); ```

浏览器对象模型(BOM)

window

location

location中改变路由或刷新页面都会改变document.referrer

screen

history

来自:MDN:history

  1. 属性

    1. history.length

      返回(只读)浏览历史记录的数量。

    2. history.state

      返回(只读)当前页面的state对象。

    3. history.scrollRestoration

      返回/设置重新加载页面时是否滚动到之前位置。auto(默认)滚动至之前位置;manual滚动至页面顶部。

  2. 方法

    1. history.go(数字)

      跳转跨度几个浏览历史记录,正数向前、负数向后、0或不传参则刷新当前页面。

    2. history.back()

      等价于:history.go(-1)

    3. history.forward()

      等价于:history.go(1)

    4. history.pushState(state对象, 标题字符串, URL字符串)

      不触发页面刷新、不触发hashchange事件,若设置跨域网址则报错。不会改变document.referrer

      添加并切换到一个最新的浏览历史记录,地址栏变成URL字符串。

    5. history.replaceState(state对象, 标题字符串, URL字符串)

      不触发页面刷新、不触发hashchange事件,若设置跨域网址则报错。不会改变document.referrer

      覆盖现在所在的浏览历史记录,地址栏变成URL字符串。

    1. state对象

      • 可以是任何类型的值。可填null
      1. history.state返回的值。
      2. window的popstate事件触发时,回调函数的参数的state属性。
      3. history.pushStatehistory.replaceState的第一个参数。
    2. 标题字符串:页面标题。但所有浏览器目前都忽略这个值,可填null
    3. URL字符串:修改浏览器的地址栏,必须同域。
    4. history.go/back/forward对于document.referrer

      1. 若导致重新载入页面(之前是重新载入而记录进history),则改变document.referrer
      2. 若没有导致重新载入页面(之前是history.pushState/replaceState而记录进history),则不会改变document.referrer

小tips-一种移动端模拟实现返回拦截的方案

Blob

Blob(binary large object,二进制大型对象):用2进制的方式处理文件(展示、下载、传输)。

  1. Blob

    1. 创建实例:new Blob([数组[, options]])

      1. 数组

        一个由ArrayBufferArrayBufferViewBlobDOMString等对象混合构成的数组。

      2. options

        1. type:被放入到Blob实例中的数组内容的MIME类型
        2. endings
    2. 实例的属性:

      1. .size:数据大小(字节)。
      2. .type:实例包含数据的MIME类型
  2. 创建Blob URL(伪协议):URL.createObjectURL(Blob实例)

    因为File基于Blob,所以也可以:URL.createObjectURL(File实例)

    返回URL对象的DOMString(blob:http://地址blob:https://地址)。

    可用于Blob实例内容的访问、下载,如:文件下载,图片展示。

  3. 获取Base64值

    1. Blob实例的Base64值

       const reader = new window.FileReader()  // FileReader实例
       reader.addEventListener('load', (e) => {
         console.log(e.target.result)  // 文件的内容。该属性仅在读取操作完成后才有效,数据的格式取决于使用哪个方法来启动读取操作。
       })
      
       const blob = new Blob(['任意有效值'])
      
       reader.readAsDataURL(blob)         // result:Base64
       // reader.readAsArrayBuffer(blob)  // result:ArrayBuffer数据对象
       // reader.readAsBinaryString(blob) // result:原始二进制数据
       // reader.readAsText(blob)         // result:一个字符串以表示所读取的文件内容
      
    2. 本地文件的Base64值

      input节点.filesFileListFileList的每一项是File实例,File基于Blob

       <input type="file" id="j-input">
      
       <script>
       document.getElementById('j-input').addEventListener('change', function (e) {
         const reader = new window.FileReader()  // FileReader实例
         reader.addEventListener('load', (e) => {
           console.log(e.target.result)  // 文件的内容。该属性仅在读取操作完成后才有效,数据的格式取决于使用哪个方法来启动读取操作。
         })
      
         const file = e.target.files[0]
      
         reader.readAsDataURL(file)         // result:Base64
         // reader.readAsArrayBuffer(file)  // result:ArrayBuffer数据对象
         // reader.readAsBinaryString(file) // result:原始二进制数据
         // reader.readAsText(file)         // result:一个字符串以表示所读取的文件内容
       })
       </script>
      

    其他:canvas实例.toDataURL方法返回Base64值;btoa/atob可以编码/解码Base64字符串。

本地文件上传后展示预览,可以用Blob URLBase64写入节点的src中(如:<img><video><audio>)。

IntersectionObserver

参考:MDN:Intersection Observer API

// 提供异步观察目标元素与其祖先元素或顶级文档视窗(viewport)交叉状态的方法
// 异步、不随着目标元素的滚动同步触发
// 规格写明,IntersectionObserver的实现,应该采用requestIdleCallback(),即只有线程空闲下来,才会执行观察者
// 这个观察者的优先级非常低,只在其他任务执行完,浏览器有了空闲才会执行
const io = new window.IntersectionObserver(
  // 在target和root的交集越过threshold时被执行(大于时执行一次,小于时执行一次,不断往复);初始化observe某dom时执行(observe同一个dom多次,仅第一次触发回调;unobserve后再observe同个dom,会再次触发回调)
  (entries, options) => {
    // entries:观察元素的`IntersectionObserverEntry`实例数组(异步触发,一次触发entries可能有1个或多个项,取决于执行前判定已触发的观察个数)
    //   intersectionRect   目标元素和视窗(根)相交的矩形信息 可以称为相交区域
    //   boundingClientRect 目标元素的矩形信息
    //   intersectionRatio  相交区域和目标元素的比例值   intersectionRect/boundingClientRect 不可见时小于等于0
    //   isIntersecting     目标元素可见性变化(只能间隔变化:这一次true,下一次必须false,循环往复) Boolean值 可见为true。有兼容性问题,可用`entries[项].intersectionRatio > threshold`代替(true:可见、false:可见)
    //   rootBounds         根元素的矩形信息,没有指定根元素就是当前视窗的矩形信息
    //   target             观察的目标元素
    //   time               返回一个记录从实例化IntersectionObserver到交叉被触发的时间的时间戳

    // options:实例化IntersectionObserver时的第二个参数
  },
  {
    // root       观察的相对物:浏览器视口 或 观察的目标元素的祖先元素。默认:null
    // threshold  交叉比例,决定何时触发回调函数,类型:number | Array<number>。默认:[0]
    // rootMargin 用来扩大/缩小交集计算区域。默认:'0px 0px 0px 0px'
  }
)

// 属性(实例化IntersectionObserver时的第二个参数中的属性)
io.root
io.thresholds
io.rootMargin

// 方法
io.observe(dom1)   // 开始观察,接受一个DOM节点对象(一个IntersectionObserver实例对同一个DOM多次观察,与一次观察效果相同)
io.observe(dom2)

io.unobserve(dom1) // 停止观察 接受一个element元素

io.takeRecords()   // 返回已检测到但尚未由观察者的回调函数处理的entries(即将传给回调函数的第一个参数)。若调用此函数,则不会再触发尚未触发的回调函数。通常在disconnect之前调用,来处理尚未异步处理的回调

io.disconnect()    // 关闭观察者

Demo: DOM展示或消失执行方法(IntersectionObserver)

MutationObserver

参考:MDN:MutationObserver

// 提供观察DOM所做更改的能力
// 是异步任务中的microtask
const mo = new window.MutationObserver(
  // 观察到DOM发生变化时被执行
  (records, observer) => {
    // records:独立DOM变化的`MutationRecord`实例数组(异步触发,一次触发records可能有1个或多个项,取决于执行前判定已触发的观察个数)
    //   type 变化类型。attributes|childList|characterData
    //   target
    //   addedNodes
    //   removedNodes
    //   previousSibling
    //   nextSibling
    //   attributeName
    //   attributeNamespace
    //   oldValue

    // observer:本实例(mo === observer)
  }
)

// 方法
mo.observe(  // 开始观察
  dom1, // 接受观察的DOM
  { // attributes、childList、characterData至少有一个必须为true
    attributes: true,               // 观察属性变化。默认:false
    childList: true,                // 观察添加或删除子节点。默认:false
    characterData: true             // 观察文本的变化

    // attributeFilter: ['属性名'],  // 要观察的特定属性名称的数组。默认:所有属性名
    // attributeOldValue: true,     // 包含有改动的属性的上一个值
    // characterDataOldValue: true, // 包含有改动的文本的上一个值

    // subtree: true                // 以上所有配置都同时观察后代节点。默认:false
  }
)
mo.observe(
  dom2,
  {
    attributes: true,
    childList: true,
    characterData: true

    // attributeFilter: ['属性名'],
    // attributeOldValue: true,
    // characterDataOldValue: true,

    // subtree: true
  }
)
// e.g. lazysizes 使用 mo.observe( document.documentElement, { childList: true, subtree: true, attributes: true } ) 来监听整个文档的变化

mo.takeRecords() // 返回已检测到但尚未由观察者的回调函数处理的records(即将传给回调函数的第一个参数)。若调用此函数,则不会再触发尚未触发的回调函数。通常在disconnect之前调用,来处理尚未异步处理的回调

mo.disconnect()  // 关闭观察者(没有unobserve方法,只能全部关闭)

PerformanceObserver

参考:MDN:PerformanceObserver

// 监测性能度量事件,包含:
//   1. 测量请求(Request)和响应(Response)之间的处理时间(浏览器)
//   2. 在从数据库中检索数据时计算持续时间。(Node.js)
//   3. 抽象精确的时间信息,使用 Paint Timing API,比如 First Paint 或 First Contentful Paint 时间
//   4. 使用"User Timing API"、"Navigation Timing API"、"Network Information API"、"Resource Timing API"和"Paint Timing API"访问性能指标
// 在 Web Worker 中可用
// 异步
var po = new window.PerformanceObserver(    // Node.js:`const { performance } = require('perf_hooks')`
  // 在浏览器的性能时间轴记录下一个新的 performance entries 的时候将会被通知
  (entryList, observer) => {
    // entryList:性能观察条目的`PerformanceObserverEntryList`实例
    //   以下均返回`PerformanceEntry`(`PerformanceMark`、`PerformanceMeasure`、`PerformanceFrameTiming`、`PerformanceNavigationTiming`、`PerformanceResourceTiming`)实例数组(异步触发,一次触发entryList可能有1个或多个`PerformanceEntry`实例,取决于执行前判定已触发的观察个数)
    //   getEntries()
    //   getEntriesByType()
    //   getEntriesByName()

    // observer: 本实例(po === observer)
  }
)

// (构造函数)属性
window.PerformanceObserver.supportedEntryTypes  // entryTypes支持的值的数组

// 方法
po.observe({
  entryTypes: [
    // window.PerformanceObserver.supportedEntryTypes的项
  ]
})

po.takeRecords() // 返回已检测到但尚未由观察者的回调函数处理的entryList(即将传给回调函数的第一个参数)。若调用此函数,则不会再触发尚未触发的回调函数。通常在disconnect之前调用,来处理尚未异步处理的回调

po.disconnect()  // 关闭观察者

Performance

  1. navigation-timing

    页面从打开到加载完成的经历图

    统计页面从打开到加载完成的时间数据,基本覆盖所有性能优化参数指标。但无法统计内存占用相关情况。

    1. 标准1(已废弃):window.performance.timing
    2. 标准2:window.performance.getEntriesByType('navigation')[0]
    1. 优化参照

      1. 白屏时间(首元素可见):performance.timing.domLoading - performance.timing.fetchStart

        .html下载完成并开始解析HTM。

      2. 首屏可见:白屏时间 + 首屏渲染时间

        解析到首屏底部的某个DOM(如:MutationObserver或用<script>标记)。

      3. 首屏可交互:performance.timing.domContentLoadedEventEnd - performance.timing.fetchStart

        非异步JS都执行完毕。

      4. 加载完成:performance.timing.loadEventEnd - performance.timing.fetchStart

        触发window的load事件(所有资源加载完毕)。

    2. 结果判断:

      (在控制变量的情况下)埋点上报统计出优化前后的点击/展示的变化。

console

  1. 字符串替换:

    console.log等(字符串包含若干个%某, 多个参数)(若后面参数数量不够前面的%某,则剩下的%某不会转义)

    替代字符串 描述
    %o 替换为DOM节点
    %O 替换为JS对象
    %s 替换为字符串
    %d%i 替换为整数
    %f 替换为浮点数
    %c 定义CSS(后面的都使用这个CSS,直到后面有新的%c被赋值)

    e.g. console.log("0、 %o 1、 %O 2、 %s 3、 %d 4、 %f 5、 %c带颜色%c关闭CSS 6、 若后面参数数量不够前面的%某,则剩下的%某不会转义 %o %O %s %d %i %f %c",$0,{ a: 1, b: false, c: [], d: { e: 1 } }, "字符串", 1.1, 1.1, "color: yellow; font-style: italic; background-color: blue; padding: 2px", "") console字符串替换图

  2. console.table

    适合针对数组、对象打印成表格方式展示。

  3. console.dir

    适合针对DOM、函数打印其属性。

FormData

参考:MDN:FormData

  1. new FormData(<from>元素或空)
  2. FormData.prototype.append/delete/entries/forEach/get/getAll/has/keys/set/values
e.g. ```javascript const formData = new FormData() formData.append(名, 值[, 文件名]) // ...等 ```

fetch

参考:MDN:WorkerOrGlobalScope.fetch()

fetch(地址或Request实例[, 配置]):发起请求,返回Promise实例(Promise实例完成的参数是Response实例)。

配置 1. `method`:请求方法,默认:`'GET'`。 2. `headers`:请求头,`Headers`实例或对象。 3. `body`:请求的body信息,`Blob`、`BufferSource`、`FormData`、`URLSearchParams`或`USVString`对象。 >注意:`GET`或`HEAD`方法的请求不能包含 ~~`body`~~。 4. `mode`:请求的模式,`'cors'`、`'no-cors'`或`'same-origin'`。 5. `credentials`:是否发送cookie,`'include'`、`'same-origin'`、`'omit'`。 6. `cache`:如何处理缓存,`'default'`、`'no-store'`、`'reload'`、`'no-cache'`、`'force-cache'`或`'only-if-cached'`。 7. `redirect`:`'follow'`(自动重定向)、`'error'`(如果产生重定向将自动终止并且抛出一个错误)或`'manual'`(手动处理重定向)。 8. `referrer`:`'client'`、`'no-referrer'`或URL。 9. `referrerPolicy`:指定了HTTP头部referer字段的值。'`no-referrer`'、`'no-referrer-when-downgrade'`、`'origin'`、`'origin-when-cross-origin'`、`'unsafe-url'`。 10. `integrity` 11. `signal` 12. `keepalive`

e.g. fetch("地址", { headers: { 'Content-Type': 'application/json' }, method: "POST", body: JSON.stringify({a: 1, b: 2}) })

fetch是一项新技术,不是 XMLHttpRequest 实现(axios在浏览器是XMLHttpRequest封装实现)。fetchXMLHttpRequest的请求传递的信息和处理逻辑略有不同。

Headers

参考:MDN:Headers

  1. new Headers(对象或Headers实例或空)
  2. Headers.prototype.append/delete/entries/forEach/get/has/keys/set/values

Request

参考:MDN:Request

  1. new Request(地址或Request实例[, 配置])

new Request()参数与于fetch()参数完全一致。

Response

参考:MDN:Response

  1. new Response(body, 配置)

    1. 传参:

      1. bodynullBlobBufferSourceFormDataReadableStreamURLSearchParamsUSVString对象。
      2. 配置

        1. status:response的状态码,如:200
        2. statusText:与状态码关联的状态消息,如:OK
        3. headers:response的任何headers,Headers实例或对象。
    2. 实例的属性:

      .headers.ok.status.statusText.url.type.redirected

    3. 实例的方法:

      .json.text.formData.blob.arrayBuffer.clone、等

    4. 实例实现了Body接口

WebSocket

参考:MDN:WebSocket

  1. new WebSocket(ws服务器URL[, 子协议的字符串或数组])

    1. 原型链属性

      1. .CONNECTING === 0.OPEN === 1.CLOSING === 2.CLOSED === 3
      2. .oncloseonerroronmessageonopen
      3. .binaryType(websocket连接所传输二进制数据的类型:'blob''arraybuffer'
      4. bufferedAmount(未发送至服务器的字节数)
      5. extensions(服务器已选择的扩展值)
      6. protocol(服务器端选中的子协议的字符串或数组,实例化时的第二个参数)
      7. readyState(链接状态:.CONNECTING.OPEN.CLOSING.CLOSED
      8. url(链接的绝对路径)
    2. 原型链方法

      1. .send(文本(String)或 二进制数据(Blob实例或Arraybuffer实例))
      2. .close([状态码[, 关闭原因]])

        状态码:MDN: WebSocket关闭码

    3. 实例事件

      close(或.onclose)、error(或.onerror)、message(或.onmessage)、open(或.onopen

Node.js实现WebSocket的服务端和客户端(不支持浏览器):ws


jQuery标准(部分)

Deferred

参考:阮一峰:jQuery的deferred对象详解阮一峰:jQuery.Deferred对象jQuery:延迟对象

  1. Deferred对象

    1. 创建Deferred对象:

      $.Deferred()

    2. Deferred对象的状态:

      1. 触发状态:

        1. 改变状态:

          .resolve().resolveWith().reject().rejectWith()

        2. 状态不改变,仅发起一个通知:

          .notify()notifyWith()

        • 以上所有方法仅在pending状态有效

          1. .resolve/resolveWith()触发函数:.done.always().then(第一个参数)
          2. .reject/rejectWith()触发函数:.fail.always().then(第二个参数).catch()
          3. .notify/notifyWith()触发函数:.progress().then(第三个参数)
      2. 获得状态:.state()

        返回三者之一:'pending''resolved''rejected'

    3. 当Deferred对象状态改变后(或发起notify通知),根据相应的状态触发回调

      1. 向下传递调用方法的对象本身:.done().fail().progress().always()

        Deferred对象调用则返回Deferred对象;Promise对象调用则返回Promise对象。

        e.g. ```javascript var deferred = $.Deferred() .done(function (msg) { console.log('resolve', msg); }) .fail(function (msg) { console.error('reject', msg); }) .progress(function (msg) { console.log('notify', msg); }) .always(function (msg) { console.log('always', msg); }); // deferred.resolve('信息'); // 执行done,再执行always // deferred.reject('信息'); // 执行fail,再执行always // deferred.notify('信息'); // 执行progress ```
      2. 向下传递回调函数的return内容:.then(解决, 拒绝, 通知).catch(拒绝)

        返回为Promise对象。

        e.g. ```javascript var deferred = $.Deferred(); var promise = deferred .then( function (e) { return e; }, function (e) { return e; }, function (e) { return e; }); promise .done(function (msg) { console.log('resolve', msg); }) .fail(function (msg) { console.error('reject', msg); }) .progress(function (msg) { console.log('notify', msg); }) .always(function (msg) { console.log('always', msg); }); // deferred.resolve('信息'); // 执行then第一个参数,再执行done,最后执行always // deferred.reject('信息'); // 执行then第二个参数,再执行fail,最后执行always // deferred.notify('信息'); // 执行then第三个参数,再执行progress ```
      3. 且判断:jQuery.when(Deferred对象或其他值)

        若传入的不是Deferred对象,则当做立即解决的值:$.Deferred().resolve(参数)

        返回为Promise对象。

    4. 改变为Promise对象:.promise()

  2. Promise对象

    Deferred对象的子集。

    1. 相对于Deferred对象,Promise对象无法改变执行状态:

      1. 屏蔽与改变执行状态有关的方法

        resolveresolveWithrejectrejectWithnotifynotifyWith

      2. 开放与改变执行状态无关的方法

        donefailprogressalwaysthencatchpromisestate

    2. $.ajax返回Promise对象
    3. 允许把所有jQuery对象设置为Promise对象(如:动画方法后接.promise().done(方法),使节点所有动画都结束后调用方法)。

CodePen demo

jQuery事件类型

  1. 浏览器事件

    1. resize

      仅针对$(window)

      1. 监听:$(window).resize(func)$(window).on('resize', func)
      2. 手动触发:$(window).resize()$(window).trigger('resize')
    2. scroll

      不冒泡。仅监听自己DOM的滚动,子节点滚动不触发。

      1. 监听:.scroll(func).on('scroll', func)
      2. 手动触发:.scroll().trigger('scroll')
      可以用其他方式实现阻止scroll冒泡效果 1. CSS:`overscroll-behavior`实现滚动不传播给祖先。 2. 针对WAP的[JS实现](https://github.com/realgeoffrey/knowledge/blob/master/网站前端/JS方法积累/实用方法/README.md#原生js针对wap的阻止滚动冒泡仅dom):在触摸开始时,若发现滚动区域已经处于极限状态时,则手工设置`scrollTop`的值使其未达到极限状态。 3. CSS:父级的`overflow: hidden/scroll`切换。
    3. error(建议用原生事件)

      不冒泡。

      jQuery不推荐on等方式绑定windowerror事件,只通过原生的windowerror定义。

      1. 监听:.on('error', func)
      2. 手动触发:.trigger('error')
    4. load(不可靠、建议用原生事件)

      不冒泡。适用于任何可使用URL关联的元素:<img><link><script><iframe>window

      资源完全加载完毕后触发。

      1. 监听:.on('load', func)
      2. 手动触发:.trigger('load')
    5. ready

      仅针对$(document)

      DOM加载解析完毕后触发。若不在ready后才操作DOM,会导致DOM的properties可能尚未设置完毕,从而获取到DOM默认的properties

      1. 监听:$(document).ready(func)$(func)$().ready(func)
  2. 表单事件

    1. blur

      不冒泡,直接绑定后无法监听子节点blur的冒泡。但可以用事件代理(自动转换为focusout),

      1. 监听:.blur(func).on('blur', func)
      2. 手动触发:.blur().trigger('blur')
    2. focus

      不冒泡,直接绑定后无法监听子节点focus的冒泡。但可以用事件代理(自动转换为focusin),

      1. 监听:.focus(func).on('focus', func)
      2. 手动触发:.focus().trigger('focus')
    3. focusout

      1. 监听:.focusout(func).on('focusout', func)
      2. 手动触发:.focusout().trigger('focusout')
    4. focusin

      1. 监听:.focusin(func).on('focusin', func)
      2. 手动触发:.focusin().trigger('focusin')
    5. change

      按钮选择改变、文本内容修改并且失去焦点、文件选择变化。原始的input事件是有输入内容就触发。

      1. 监听:.change(func).on('change', func)
      2. 手动触发:.change().trigger('change')
    6. select

      鼠标选中输入框的文字。

      1. 监听:.select(func).on('select', func)
      2. 手动触发:.select().trigger('select')
    7. submit

      1. 监听:.submit(func).on('submit', func)
      2. 手动触发:.submit().trigger('submit')
  3. 键盘事件

    1. keydown

      哪一个键被按下。按住不断触发。

      1. 监听:.keydown(func).on('keydown', func)
      2. 手动触发:.keydown().trigger('keydown')
    2. keyup

      哪一个键被按下。按住抬起仅触发一次。

      1. 监听:.keyup(func).on('keyup', func)
      2. 手动触发:.keyup().trigger('keyup')
    3. keypress

      实际输入的文本。按住不断触发。

      1. 监听:.keypress(func).on('keypress', func)
      2. 手动触发:.keypress().trigger('keypress')
  4. 鼠标事件

    mousedownmouseupclickdblclickcontextmenumousemovehovermouseentermouseleavemouseovermouseout

jQuery事件处理程序的事件对象

只有在事件处理程序执行期间,事件对象才会存在;一旦事件处理程序执行完毕,事件对象就会销毁。

约定:/* jQuery(或Zepto)对象包装的DOM元素 */$dom.on(..., function (e) {});this为默认值。

  1. e.originalEvent === window.event
  2. e.currentTarget

    在事件冒泡过程中的当前DOM元素(事件绑定的DOM),e.currentTarget === this

  3. e.target

    最深层被触发的目标元素(捕获的终点、冒泡的起点)。

    ie是事件对象.srcElement

  4. e.delegateTarget

    绑定的宿主。

  5. e.relatedTarget

    在事件中涉及的其它任何DOM元素。

  6. e.pageX/Y

    鼠标相对于文档的左/上边缘的位置。

  7. e.data

    传入处理函数的额外参数。

  8. e.namespace

    事件被触发时包含的命名空间。

  9. e.type

    事件类型名。

  10. e.which

    返回键盘或鼠标(左键:1;中键:2;右键:3)的数字。

  11. e.result

    获取前一个事件的返回值。

  12. e.timeStamp

    触发时的时间戳。

  13. e.eventPhase

    当前事件处理程序所在阶段:0,没有事件正在被处理;1,捕获;2,处于目标;3,冒泡。

  14. e.trusted

    是否为用户触发:true,用户或浏览器触发;false,JS触发。

  15. e.preventDefault()

    默认事件行为将不再触发。

    ie是事件对象.returnValue = false

  16. e.isDefaultPrevented()

    事件对象是否调用过e.preventDefault()

  17. e.stopPropagation()

    阻止事件捕获和冒泡。

    ie是事件对象.cancelBubble = true

  18. e.isPropagationStopped()

    事件对象是否调用过e.stopPropagation()

  19. e.stopImmediatePropagation()

    阻止剩余的事件处理程序执行并且阻止事件捕获和冒泡。

  20. e.isImmediatePropagationStopped()

    事件对象是否调用过e.stopImmediatePropagation()


其他

JS模块化方案

参考:关于AMD,CMD,CommonJS及UMD规范

JS模块化方案图

  1. CommonJS规范
  2. ES6 Module

在webpack打包时,可以在JS文件中混用requireexport,但是不能 混用importmodule.exports。最好统一为某一种规范去使用,不要混用。

  1. UMD规范的简单示例:

     (function (root, factory) {
         if (typeof define === 'function' && define.amd) {
             // AMD. Register as an anonymous module.
             define(['b'], factory);
         } else if (typeof module === 'object' && module.exports) {
             // Node. Does not work with strict CommonJS, but
             // only CommonJS-like environments that support module.exports,
             // like Node.
             module.exports = factory(require('b'));
         } else {
             // Browser globals (root is window)
             root.returnExports = factory(root.b);
         }
     }(typeof self !== 'undefined' ? self : this, function (b) {
         // Use b in some fashion.
    
         // Just return a value to define the module export.
         // This example returns an object, but the module
         // can return a function as the exported value.
         return {};
     }));
    

    可以设置webpack的output.libraryTarget'umd'自动导出UMD规范的代码。

JS特殊字符

转义字符:\

转义字符不会计算在:字符串的length,字符串的replace等。

  1. 字符串字面量:

    来自:MDN:在字符串中使用的特殊字符

    字符 表示的意义(需要转义的特殊字符)
    '\'' "'"
    '\"' '"'
    '\\' '\'
    '\0' null
    '\b' 退格符
    '\f' 换页符
    '\n' 换行符
    '\r' 回车符
    '\t' Tab (制表符)
    '\v' 垂直制表符
    '\一至三个8进制数' 用8进制数指定Unicode的Latin-1
    '\x两个16进制数' 用16进制数指定Unicode的Latin-1
    '\u四个16进制数' 用16进制数指定Unicode
    '\u{一至六个16进制数}' 用16进制数指定Unicode的码位

    可以给其他所有字符前面添加\\会被忽略(不推荐)。e.g. '\a' === 'a'

  2. 模板字符串:

    除了字符串字面量的转义内容('"不需要转义),还需转义:

    字符 表示的意义(需要转义的特殊字符)
    \` `
    \${ ${(单独出现${表示模板占位符的开始)
  3. 正则表达式字面量:

    需要转义的特殊字符:( ) [ ] { } \ / ^ $ | ? * + .

this替代

某些方法允许传入的参数来设置this的指向:

  1. Function.prototype.call/apply/bind
  2. Array.prototype.forEach/map/filter/every/some/find/findIndex
  3. Array.from
  4. Set.prototype.forEach
  5. Map.prototype.forEach
  6. 「TypedArray」.prototype.forEach/map/filter/every/some/find/findIndex
  7. NodeList.prototype.forEach
  8. 「DOMTokenList」.prototype.forEach

CSS标准

选择器类型

  1. CSS选择器

    来自:阮一峰:CSS选择器笔记。参考:W3C:selectors

    1. 基本选择器

      1. *

        通配符选择器,匹配所有元素。

      2. E

        元素选择器,匹配使用E标签的元素。

      3. .className

        类选择器,匹配class属性中包含「className」的元素。

      4. #idName

        ID选择器,匹配id属性等于「idName」的元素。

    2. 关系选择器

      1. E1,E2

        多元素选择器,同时匹配E1元素或E2元素。

      派生选择器:通过依据元素在其位置的上下文关系来定义样式。因此下面4个是派生选择器。

      1. E1 E2

        后代元素选择器,匹配属于E1元素后代的E2元素。

      2. E1>E2

        子元素选择器,匹配E1元素的子元素E2。

      3. E1+E2

        相邻兄弟选择器,匹配紧随E1元素之后的同级元素E2。

      4. E1~E2

        通用兄弟选择器,匹配在E1元素之后的同级E2元素。

    3. 属性选择器

      1. 属性值的引号可加可不加;若属性值含有空格特殊字符,必须用引号包围。
      2. 建议始终用(双)引号包围属性值。
      1. [attrName]

        匹配具有「attrName」属性的元素,不考虑它的值。

      2. [attrName=val]

        匹配「attrName」属性等于「val」的元素。

      3. [attrName~=val]

        匹配「attrName」属性具有多个空格分隔的值、其中一个值等于「val」的元素。

      4. [attrName|=val]

        匹配「attrName」属性等于「val」或以「val-」开头的元素。

        主要用于lang属性,如:”en”、”en-us”、”en-gb”等。

      5. [attrName^=val]

        属性「attrName」的值以「val」开头的元素。

      6. [attrName$=val]

        属性「attrName」的值以「val」结尾的元素。

      7. [attrName*=val]

        属性「attrName」的值包含「val」字符串的元素。

    4. 伪元素选择器

      1. :before

        在元素之前插入生成的内容。

      2. :after

        在元素之后插入生成的内容。

      3. :first-line

        匹配元素的第一行。

      4. :first-letter

        匹配元素的第一个字母。

    5. 伪类选择器

      1. 普通伪类

        1. :link

          匹配未被点击的链接。

        2. :visited

          匹配已被点击的链接。

        3. :active

          匹配鼠标已经对其按下、还没有释放的元素。

        4. :hover

          匹配鼠标悬停其上的元素。

        5. :focus

          匹配获得当前焦点的元素。

        6. :lang(val)

          匹配lang属性等于「val」的元素。

      2. 与用户界面有关的伪类

        1. :enabled

          匹配表单中激活的元素。

        2. :disabled

          匹配表单中禁用的元素。

        3. :checked

          匹配表单中被选中的radio(单选框)或checkbox(复选框)。

        4. ::selection

          匹配用户当前选中的元素(如:鼠标或其他选择设备选中的部分)。

          jQuery选择器无法选中内容;仅能作为CSS选择器添加样式属性。

      3. 结构性伪类

        1. :root

          匹配文档的根元素,对于HTML文档,就是HTML元素。

        2. :nth-child(num)

          匹配其父元素的第num个子元素,第一个编号为1。

        3. :nth-last-child(num)

          匹配其父元素的倒数第num个子元素,倒数第一个编号为1。

        4. :nth-of-type(num)

          :nth-child(num)作用类似,但是仅匹配使用同种标签的元素。

        5. :nth-last-of-type(num)

          :nth-last-child(num)作用类似,但是仅匹配使用同种标签的元素。

        6. :first-child

          匹配父元素的第一个子元素,等同于:nth-child(1)

        7. :last-child

          匹配父元素的最后一个子元素,等同于:nth-last-child(1)

        8. :first-of-type

          匹配父元素下使用同种标签的第一个子元素,等同于:nth-of-type(1)

        9. :last-of-type

          匹配父元素下使用同种标签的最后一个子元素,等同于:nth-last-of-type(1)

        10. :only-child

          匹配父元素下仅有的一个子元素,等同于:first-child:last-child:nth-child(1):nth-last-child(1)

        11. :only-of-type

          匹配父元素下使用同种标签的唯一一个子元素,等同于:first-of-type:last-of-type:nth-of-type(1):nth-last-of-type(1)

        12. :empty

          匹配一个不包含任意子元素的元素。注意:文本节点也被看作子元素。

        13. :not(selector)

          匹配不符合「selector」选择器的元素。注意:「selector」不能再包含:not

        14. :target

          匹配文档URI的片段标识符,对应相同id属性的元素。

  2. jQuery专有选择器

    来自:jQuery:Selectors

    jQuery兼容CSS所有选择器,并进行了扩展。

    因为不是CSS规范的一部分,专有选择器无法利用本机DOM的document.querySelectorAll提升性能。为了提高代码性能,建议使用filternothaseq等jQuery方法以及转化为CSS规范的选择器,来合理使用。

    1. [attrName!=val]

      匹配「attrName」属性不等于「val」的元素。

    2. :first

      匹配文档顺序的第一个元素。

    3. :last

      匹配文档顺序的最后一个元素。

    4. :eq(num)

      匹配文档顺序的第num个元素,0位第一个,-1为倒数第一个。

    5. :even

      匹配文档顺序的偶数元素,索引为0、2、4…。

    6. :odd

      匹配文档顺序的奇数元素,索引为1、3、5…。

    7. :gt(num)

      匹配索引大于(不包括等于)num的元素,0位第一个,-1为倒数第一个。

    8. :lt(num)

      匹配索引小于(不包括等于)num的元素,0位第一个,-1为倒数第一个。

    9. :button

      匹配button, [type=button]的元素。

    10. :file

      匹配['type=file']的元素。

    11. :image

      匹配[type=image]的元素。

    12. :input

      匹配input, textarea, select, button的元素。

    13. :password

      匹配[type=password]的元素。

    14. :radio

      匹配[type=radio]的元素。

    15. :reset

      匹配[type=reset]的元素。

    16. :submit

      匹配[type=submit]的元素。

    17. :text

      匹配[type=text]的元素。

    18. :selected

      匹配选中的元素(适用于<option>)。

    19. :parent

      匹配一个包含任意子元素的元素。注意:文本节点也被看作子元素。

    20. :contains(val)

      匹配含有「val」字符串(区分大小写)的元素,可以是后代包含。

    21. :animated

      匹配此时处于动画进度中的元素。

    22. :has(selector)

      匹配符合「selector」选择器的元素。

    23. :header

      匹配h1, h2, h3, h4, h5, h6的元素。

    24. :hidden

      匹配隐藏的元素。

    25. :visible

      匹配显示的元素。

CSS变量(CSS Custom properties,CSS variables)

  1. 变量名:

    --开头,大小写敏感,不能包含 $[^(% 等字符。

  2. 定义、使用:

     :root {
       /* 全局定义 */
       --main-color: #b13523;    /* 必须定义在某个选择器内部 */
       --main-bg: rgb(255, 255, 255);
       --logo-border-color: rebeccapurple;
       --header-height: 68px;
       --content-padding: 10px 20px;
       --base-line-height: 1.428571429;
       --transition-duration: .35s;
       --external-link: "external link";
     }
    
     p {
       /* 局部定义 */
       --padding: calc(2vh + 20px);
    
       /* 使用 */
       color: var(--main-color);
     }
    
     p a {
       /* 使用 */
       padding: var(--padding, 1px 2px 3px 4px);
       /* 第二个参数表示变量未定义时的默认值(不包括变量值不合法)。参数内部不处理逗号和空格 */
    
       margin: var(--main-color, 10px);  /* 因为变量值不合法,因此:margin: 0; */
     }
    
  3. 用法

    1. 只能用作CSS属性值,不可以用作CSS属性名

       .foo {
         --side: margin-top;
      
         /* 无效 */
         var(--side): 20px;
       }
      
    2. 变量值类型

      1. 字符串:可以与其他字符串拼接
      2. 数值:

        1. 不可以与单位连用,要用calc

           .foo {
             --size: 20;
          
             /* 无效,解析为:font-size: 20 px; */
             font-size: var(--size)px;
          
             /* 有效 */
             margin-top: calc(var(--size) * 1px);
           }
          
        2. 若变量值带有单位,则不能写成字符串。

           /* 无效 */
           .foo {
             --foo: '20px';
             font-size: var(--foo);
           }
          
           /* 有效 */
           .foo {
             --foo: 20px;
             font-size: var(--foo);
           }
          
    3. 嵌套作用域