history
Blob
Observers
IntersectionObserver
MutationObserver
PerformanceObserver
ResizeObserver
ReportingObserver
Performance
console
FormData
fetch
Headers
Request
Response
WebSocket
对象的API,大部分都是针对可枚举
且自身(不在原型链上)
的属性;复制相关的API,都是浅复制。
对象的每一个属性都对应一个「属性描述」对象,必须是数据属性
或访问器属性
两种形式之一。
数据属性:
configurable
(默认:false
)
是否能修改(除了value
之外的)描述符、是否能delete
对象的该属性。
configurable
为false
:除了允许writable
的true
修改为false
之外,不允许修改描述符(除了value
之外,其他描述名都不可以修改:、configurable
、enumerable
、writable
、get
)。set
enumerable
(默认:false
)
是否可枚举。
writable
(默认:false
)
该属性是否能被赋值运算符=
改变。
value
(默认:undefined
)
对象的该属性值。
访问器属性:
configurable
enumerable
get
(默认:undefined
)
该属性的getter方法,此方法返回值为对象的该属性值。
set
(默认:undefined
)
该属性的setter方法,此方法接受一个参数,参数值为对象的该属性赋值运算符=
右边的值。
不使用
```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属性(基本包装类型) ```Object.defineProperty/defineProperties的写法
建议:使用更精确的set/get函数(e.g.
setBar
、getBar
),减少使用setter
、getter
(set
、get
)。
- 不使用
Object.defineProperty/defineProperties/create
设置属性描述的新建属性(如:给一个对象直接新增属性=
、或新建对象),这些属性的configurable
、enumerable
、writable
为true
,value
、get
、set
为直接设置的内容(若get
、set
未设置,则为undefined
)。- 直接赋值修改属性(
=
)不会导致属性描述被修改:configurable
、enumerable
、writable
。
属性描述对象:
{ // 属性描述对象
'属性名1': { // 属性描述
描述名1: 描述值1,
描述名2: 描述值2
},
'属性名2': {
描述名1: 描述值1,
描述名2: 描述值2
}
};
属性描述对象 = { 属性名: 属性描述[, 属性名: 属性描述] }
Object.defineProperties()
第二个参数Object.getOwnPropertyDescriptors()
返回值Object.create()
第二个参数属性描述 = { 描述名: 描述值[, 描述名: 描述值] }
。
Object.defineProperty()
第三个参数Object.getOwnPropertyDescriptor()
返回值Object
来自:MDN:Object。
Object
构造函数:
Object.preventExtensions(对象)
不可扩展:不能添加新的属性(是否可以删除/修改已有属性,由属性的属性描述决定)。
Object.seal(对象)
密封:先调用
Object.preventExtensions(对象)
,再把对象的所有属性标记为configurable: false
。
Object.freeze(对象)
冻结:先调用
Object.seal(对象)
,再把对象的所有属性标记为writable: false
。
Object.isExtensible(对象)
true/false
。Object.isSealed(对象)
true/false
。Object.isFrozen(对象)
true/false
。
冻结(freeze)
>密封(seal)
>不可扩展(preventExtensions)
。
Object.assign(目标对象, 多个源对象)
(ECMAScript 2015)
=
来赋值)。若想要深复制,使用deepmerge。
Object.getPrototypeOf(对象)
[[Prototype]]
)。等价于:(非标准)
对象.__proto__
。
Object.setPrototypeOf(目标对象, 原型对象)
(ECMAScript 2015)
[[Prototype]]
)等价于:(非标准)
目标对象.__proto__ = 原型对象
。
Object.create(原型对象[, 属性描述对象])
[[Prototype]]
),属性描述对象作为自有(不在原型链上)属性。Object.defineProperty(对象, 属性名, 属性描述)
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 }) ```
Object.defineProperties(对象, 属性描述对象)
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 } }) ```
Object.getOwnPropertyDescriptor(对象, 属性名)
undefined
。e.g.
```javascript const obj = { foo: 123 } Object.getOwnPropertyDescriptor(obj, 'foo') // { // value: 123, // writable: true, // enumerable: true, // configurable: true // } ```
Object.getOwnPropertyDescriptors(对象)
(ECMAScript 2017)
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 // } // } ```
Object.is(第一个值, 第二个值)
(ECMAScript 2015)
true/false
。Object.entries(对象)
(ECMAScript 2017)
e.g.
Object.entries({ a: 'x', b: 42 }) // [['a', 'x'], ['b', 42]]
Object.entries(['a', 'b']) // [['0', 'a'], ['1', 'b']]
把生成的二维数组转化为字符串:
// 二维数组转为 => 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.entries
与Object.fromEntries
是相反的。
Object.fromEntries(可迭代对象)
(ECMAScript 2019)
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"}
Object.values(对象)
(ECMAScript 2017)
Object.keys(对象)
Object.getOwnPropertyNames(对象)
Symbol
类型的属性)。Object.getOwnPropertySymbols(对象)
Symbol
类型的属性名组成的数组。Object.length
等于1
Object原型链(继承给所有实例):
Object.prototype.constructor
等于Object
Object.prototype.hasOwnProperty(属性名)
true/false
。
对象.hasOwnProperty(属性名)
建议代替用:Object.prototype.hasOwnProperty.call(对象, 属性名)
。
Object.prototype.isPrototypeOf(对象)
[[Prototype]]
)上。true/false
。对象 instanceof 构造函数
构造函数.prototype
是否存在于对象的整条原型链([[Prototype]]
)上。true/false
。// e.g. Object.prototype.isPrototypeOf([]); // true [] instanceof Object; // true
对象1.isPrototypeOf(对象2)
建议代替用:Object.prototype.isPrototypeOf.call(对象1, 对象2)
。
Object.prototype.propertyIsEnumerable(属性名)
true/false
。
对象.propertyIsEnumerable(属性名)
建议代替用:Object.prototype.propertyIsEnumerable.call(对象, 属性名)
。
Object.prototype.toString()
Object.prototype.toLocaleString()
toString
。用于被本地化对象方法覆盖。Object.prototype.valueOf()
Function
来自:MDN:Function。
Function构造函数:
Function.length
等于1
Function原型链(继承给所有实例):
Function.prototype.constructor
等于Function
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 ```
Function.prototype.name
:函数的名字Function.prototype.call(this替代[, 多个参数])
Function.prototype.apply(this替代[, 参数数组])
若实例需要使用其他原型链上的方法,则可以使用
构造函数.prototype.方法.call/apply(实例[, 参数])
e.g.
arguments
不是Array类型所以无法调用原型链上的Array.prototype.方法,但可通过Array.prototype.方法.call(arguments, 参数)
调用。
Function.prototype.bind(this替代[, 多个参数])
已被
bind
而新创建的函数,再次使用bind
创建新的函数无法改变第一次bind
设置的this
值。
因为箭头函数没有创建自己的this,而是向上查找上级作用域的this,所以
Function.prototype.call/apply/bind
无法指定箭头函数使用的this(this修改无效),但仍然可以添加参数。
Function.prototype.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 ```console
、alert
等)一个方法时,会自动调用方法的toString
转换为字符串后输出
同理,当需要打印某些类型的变量时(除了
undefined
、null
没有属性;某些类型不允许某些打印),会调用变量的toString
。
Array
来自:MDN:Array。
ES5对空位处理不一,ES6把空位都处理为undefined
或empty
。
Array构造函数:
Array.from(类似数组[, 处理方法[, this替代]])
(ECMAScript 2015)
类似数组的对象
或可迭代对象
创建新的数组实例。处理方法会对新创建的数组执行map
操作。类似数组的对象:拥有
length
属性的对象。e.g.{ '0': 'a', '1': 'b', '2': 'c', length: 3 }
Array.isArray(值)
true/false
。Array.of(数组的每一项)
(ECMAScript 2015)
与
Array
构造函数的区别在对单个参数的返回值:Array.of(3); // [3]
、new Array(3); // [, , ,]
。
Array.length
等于1
Array原型链(继承给所有实例):
Array.prototype.constructor
等于Array
Array.prototype.length
:元素个数改变调用对象(mutator方法):
Array.prototype.push(添加的多项)
Array.prototype.pop()
undefined
。Array.prototype.unshift(添加的多项)
Array.prototype.shift()
undefined
。Array.prototype.reverse()
Array.prototype.sort([排序方法])
听说V8使用的是
TimSort
排序算法实现sort
。
排序方法
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 }) ```
Array.prototype.splice(开始索引[, 删除数量[, 添加的多项]])
[]
。
- 若删除数量为空,则删除索引之后的所有项。
- 若
arr.splice(位置1, 数量1, ...arr.splice(位置2, 数量2))
,则先进行参数的执行(第二个删除),被删除后新生成的数组再进行前面的删除并选择位置1
进行插入。
Array.prototype.copyWithin(目标索引[, 开始索引[, 结束索引]])
(ECMAScript 2015)
Array.prototype.fill(填充的值[, 开始索引[, 结束索引]])
(ECMAScript 2015)
填充进的内容都是浅复制:若填充的值是引用数据类型,则填充的位置都指向同一个内存地址。
不改变调用对象(accessor方法):
Array.prototype.concat(多个数组)
e.g.
[1, 2].concat(3, [4, 5]) // [1, 2, 3, 4, 5]
Array.prototype.join([分割内容])
参数为空,默认:
,
;参数为''
,则元素之间没有间隙。
Array.prototype.slice([开始索引[, 结束索引]])
[]
。
Array.prototype.slice.call(可迭代对象)
:把可迭代对象转化为数组(非数组的可迭代对象:「TypedArray」
、Map
、Set
、arguments
、NodeList
、String
、生成器
等)。Array.prototype.slice.call(可迭代对象[, 开始索引[, 结束索引]])
返回等于:可迭代对象转化为数组.slice([开始索引[, 结束索引]])
。
Array.prototype.indexOf(查找的元素[, 开始索引])
NaN
),则-1
。开始索引默认:
0
。
Array.prototype.lastIndexOf(查找的元素[, 开始索引])
NaN
),则-1
。开始索引默认:数组长度-1。
因为
Array.prototype.indexOf/lastIndexOf
是用===
进行判断,又NaN !== NaN
,所以查找NaN
总是返回-1
。
Array.prototype.includes(查找的元素[, 开始索引])
(ECMAScript 2016)
true/false
。Array.prototype.toString()
toString
,再调用Array.prototype.join
连接。Array.prototype.toLocaleString()
toLocaleString
,再调用Array.prototype.join
连接。Array.prototype.flat([数字,默认1])
(ECMAScript 2019)
会移除数组中的空项。
Array.prototype.flatMap(映射方法[, this替代])
(ECMAScript 2019)
遍历方法:
与
async-await
或Promise
配合的异步Array方法,查看:循环遍历的最后。
Array.prototype.forEach(回调函数(当前值, 索引, 数组整体)[, this替代])
undefined
。回调函数
return
无意义;空位不执行回调函数。
Array.prototype.map(回调函数(当前值, 索引, 数组整体)[, this替代])
回调函数
return
的值为新数组每个项的值(若return
本项,则浅复制);空位不执行回调函数,保留空位至新数组。
Array.prototype.filter(回调函数(当前值, 索引, 数组整体)[, this替代])
[]
。回调函数
return
的值为true
,则把原项添加进新数组(浅复制),为false
则丢弃;空位不执行回调函数,新数组丢弃空位。
Array.prototype.every(回调函数(当前值, 索引, 数组整体)[, this替代])
true
)。跳过空位。true/false
。回调函数
return
的值为true
,则继续判断下一项,为false
则不再继续;空位不执行回调函数。
Array.prototype.some(回调函数(当前值, 索引, 数组整体)[, this替代])
false
)。跳过空位。true/false
。回调函数
return
的值为false
,则继续判断下一项,为true
则不再继续;空位不执行回调函数。
Array.prototype.find(回调函数(当前值, 索引, 数组整体)[, this替代])
(ECMAScript 2015)
undefined
。undefined
。回调函数
return
的值为true
,则找到并返回该项的值,为false
则继续判断下一项;空位的项的值作为undefined
执行回调函数。
Array.prototype.findIndex(回调函数(当前值, 索引, 数组整体)[, this替代])
(ECMAScript 2015)
undefined
。-1
。回调函数
return
的值为true
,则找到并返回该项的索引,为false
则继续判断下一项;空位的项的值作为undefined
执行回调函数。
Array.prototype.reduce(回调函数(上一次调用返回的值, 当前值, 索引, 数组整体)[, 第一次调用回调函数的第一个参数])
空位不执行回调函数。
Array.prototype.reduceRight(回调函数(上一次调用返回的值, 当前值, 索引, 数组整体)[, 第一次调用回调函数的第一个参数])
空位不执行回调函数。
Array.prototype.values()
(ECMAScript 2015)
Array.prototype.values === Array.prototype[Symbol.iterator]
Array.prototype.keys()
(ECMAScript 2015)
Array.prototype.entries()
(ECMAScript 2015)
String
来自:MDN:String。
JS内部,字符以UCS-2(UTF-16的子级)的格式储存。UTF-16结合了定长和变长两种编码方法,大部分字符使用两个字节编码,字符代码超出Math.pow(16, 4) - 1
的使用四个字节。
对于那些需要4个字节储存的字符(Unicode码点大于0xFFFF
的字符),JS会认为它们是2个字符(ES6之前)。对于ES6的语法内容或方法,4个字节储存的字符会正确按照单个字符处理。
String构造函数:
String.fromCharCode(多个Unicode数字)
0xFFFF
的字符)。可以通过
\u+4位16进制数的Unicode值
输出字符串。如:'\u00a9' === '©'
。
String.fromCodePoint(多个代码点序列数字)
(ECMAScript 2015)
0xFFFF
的字符)。String.raw({ row: 可迭代对象 }[, 多个值])
或 String.raw`模板字符串`
\
转义成\\
)。String.length
等于1
String原型链(继承给所有实例):
String.prototype.constructor
等于String
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
跟HTML无关的方法:
String的方法均不改变调用对象(accessor方法)。
String.prototype.substr(开始索引[, 提取长度])
若开始索引为负数,则加上字符串长度;若提取长度为0或负数,则返回
''
。
String.prototype.substring(开始索引[, 结束索引])
若参数为负数或
NaN
,则转换为0;若参数大于长度,则为转换为长度;若结束索引小于开始索引,则参数前后替换位置。
String.prototype.slice(开始索引[, 结束索引])
若参数为负数,则加上字符串长度;若结束索引比开始索引小,则返回
''
。
String.prototype.split([分割内容[, 限定分割数量]])
分割内容可以是正则表达式。若包含
捕获括号
的正则表达式,则匹配的每一个捕获括号
的结果(包括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"]
String.prototype.indexOf(查找的元素[, 开始索引])
-1
。开始索引默认:
0
。
String.prototype.lastIndexOf(查找的元素[, 开始索引])
-1
。开始索引默认:数组长度。
String.prototype.includes(查找的元素[, 开始索引])
(ECMAScript 2015)
true/false
。String.prototype.startsWith(查找的元素[, 开始索引])
(ECMAScript 2015)
true/false
。String.prototype.endsWith(查找的元素[, 结束索引])
(ECMAScript 2015)
true/false
。String.prototype.charAt(索引)
''
。String.prototype.charCodeAt(索引)
Math.pow(16, 4)
);若超出范围或空字符,则NaN
。e.g.
'💩©'.charCodeAt(0) // 55357
、'💩©'.charCodeAt(1) // 56489
、'💩©'.charCodeAt(3) // 169
String.prototype.codePointAt(索引)
(ECMAScript 2015)
Math.pow(16, 4)
);若超出范围或空字符,则undefined
。e.g.
'💩©'.codePointAt(0) // 128169
、'💩©'.codePointAt(1) // 56489
、'💩©'.codePointAt(3) // 169
String.prototype.trim()
String.prototype.trimStart/trimLeft()
(ECMAScript 2019)
String.prototype.trimEnd/trimRight()
(ECMAScript 2019)
String.prototype.repeat()
String.prototype.padStart(目标长度数字[, 填充字符串])
(ECMAScript 2017)
' '
),直到长度达到目标长度数字(若目标长度数字小于等于原字符串长度,则不改变原字符串)。String.prototype.padEnd(目标长度数字[, 填充字符串])
(ECMAScript 2017)
' '
),直到长度达到目标长度数字(若目标长度数字小于等于原字符串长度,则不改变原字符串)。String.prototype.replace(正则或字符串, 替换字符串或替换方法)
String.prototype.replaceAll(正则或字符串, 替换字符串或替换方法)
(ECMAScript 2021)
g
标志)。String.prototype.search(正则表达式)
-1
。String.prototype.match(正则表达式)
null
。String.prototype.matchAll(正则表达式)
(ECMAScript 2020)
g
标志)。String.prototype.toLowerCase()
String.prototype.toUpperCase()
String.prototype.toLocaleLowerCase()
String.prototype.toLocaleUpperCase()
String.prototype.concat(多个字符串)
因为性能和语法简洁原因,建议使用赋值操作符
+
代替。
String.prototype.valueOf()
String.prototype.toString()
与
String.prototype.valueOf()
返回值一致。
String.prototype.localeCompare(比较的元素[, locales[, options]])
0
。String.prototype.normalize([Unicode正规形式])
e.g.
'\u01D1'.normalize() === '\u004F\u030C'.normalize()
HTML标签包裹方法:
String.prototype.anchor()
String.prototype.big()
String.prototype.blink()
String.prototype.bold()
String.prototype.fixed()
String.prototype.fontcolor()
String.prototype.fontsize()
String.prototype.italics()
String.prototype.link()
String.prototype.small()
String.prototype.strike()
String.prototype.sub()
String.prototype.sup()
Number
来自:MDN:Number。
部分是ES6。
Number构造函数:
属性
Number.EPSILON
:两个可表示数之间的最小间隔(表示可接受的最小误差范围)。
Math.abs(0.2 - 0.3 + 0.1) < Number.EPSILON; // true
能够准确地表示和正确地比较的安全整数:
Number.MAX_SAFE_INTEGER
:JS中最大的安全整数。
Number.MAX_SAFE_INTEGER === Math.pow(2, 53) - 1; // true
Number.MIN_SAFE_INTEGER
:JS中最小的安全整数。
Number.MIN_SAFE_INTEGER === -(Math.pow(2, 53) - 1); // true
Number.MAX_SAFE_INTEGER === -Number.MIN_SAFE_INTEGER; // true
Number.MAX_VALUE
:JS中能表示的最大数值。
-Number.MAX_VALUE
:JS中能表示的最小数值。
Number.MIN_VALUE
:JS中能表示的最小正数。
-Number.MIN_VALUE
:JS中能表示的最大负数。
Number.NaN
:NaN
。溢出数:
Number.POSITIVE_INFINITY
:正无穷大。
Number.POSITIVE_INFINITY === Infinity; // true
Number.NEGATIVE_INFINITY
:负无穷大。
Number.NEGATIVE_INFINITY === -Infinity; // true
Infinity
、NaN
都是Number
数据类型。
方法
Number.isNaN(值)
NaN
且类型为Number
。true/false
。
isNaN(值)
会先Number(值)
再判断;Number.isNaN(值)
若值不是数字类型则返回false
。
Number.isFinite(值)
Number
。true/false
。
isFinite(值)
会先Number(值)
再判断;Number.isFinite(值)
若值不是数字类型则返回false
。
Number.isInteger(值)
Number
。true/false
。
NaN
、正负Infinity
不是整数。
Number.isSafeInteger(值)
Number
。true/false
。安全整数范围:
[-(Math.pow(2, 53) - 1), Math.pow(2, 53) - 1]
。
Number.parseInt
:parseInt
。
~~「浮点数」
(2个按位非运算符~
)等价于parseInt(「浮点数」)
,且前者效率更高。
Number.parseFloat
:parseFloat
。
Number原型链(继承给所有实例):
Number.prototype.toFixed([数字])
0
),省去的四舍五入(不准确),没有的小数位置补0
(e.g. (1.1).toFixed(2) === '1.10'
)。若要去除
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); }
Number.prototype.toExponential([数字])
Number.prototype.toPrecision([数字])
Number.prototype.toString()
),省去的四舍五入(不准确)。(数字范围:[1, 100]
的整数)在某些情况下会以指数表示法返回。
Number.prototype.toString([数字])
其他进制的字符串转化为10进制数:
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不同进制数互相转换)parseInt(其他进制的字符串, 其他进制)
Number.prototype.valueOf()
Number.prototype.toLocaleString([locales[ , options]])
数字直接调用Number原型链上方法的写法:
10.toString(2) // SyntaxError: Unexpected token ILLEGAL
会转化为小数点
10..toString(2) 10.0.toString(2) // "1010"
通过额外的括号或方括号
10['toString'](2); (10)['toString'](2); (10).toString(2) // "1010"
10 .toString(2) // "1010"
JSON
来自:MDN:JSON。
JSON.parse(JSON字符串[, 处理方法])
- 处理方法,由最内层开始,依次向外遍历:
(键, 值) => {/* return的内容替代「值」成为此「键」的值,没有return则删除此「键」(会产生数组的空位);最顶层时,键为空字符串,返回的内容为整个JSON.parse表达式返回的值 */}
- 一般需要
try-catch
包裹
JSON.stringify(JS值[, 处理方法或需要的属性名组成的数组[, 缩进空格数量或缩进字符串]])
- 非数组对象的属性不保证以特定的顺序出现在序列化后的字符串中。
- Boolean、Number、String的基本包装类型在序列化过程中会自动转换成对应的原始值。
值为:
undefined
、方法
、Symbol
类型的值
- 非数组中:属性名-值整个被忽略
- 数组中:被转换成
null
- 不支持
BigInt
类型的值(TypeError: Do not know how to serialize a BigInt
)。- 所有
Symbol
类型的属性键都会被忽略。- 不可枚举的属性被忽略。
Date
来自:MDN:Date。
调用构造函数:
new Date([毫秒/时间字符串/年, 月[, 日[, 时[, 分[, 秒[, 毫秒]]]]]])
创建Date实例(默认:当前时间)。
特例:iOS中的
new Date('2013-10-21')
报错,必须改为new Date('2013/10/21')
。
Date(参数无效)
创建当前时间的字符串。
无字面量格式。若参数超出了合理范围,则会调整到相邻的时间。
当前时间:所在系统的时间(系统修改成什么时间就返回什么时间)。
Date构造函数:
Date.now()
Date.parse(时间字符串)
NaN
。Date.UTC(年, 月[, 日[, 时[, 分[, 秒[, 毫秒]]]]])
Date.length
等于7
Date原型链(继承给所有实例):
getter:
返回:一个数字。
Date.prototype.getTime()
描述:自1970-01-01 00:00:00 UTC到Date对象时间的毫秒。
Date.prototype.getTimezoneOffset()
描述:UTC相对于当前时区的时间差值(分钟)。
Date.prototype.getFullYear()
描述:年。
Date.prototype.getMonth()
描述:[0, 11]
月。
Date.prototype.getDate()
描述:[1, 31]
日。
Date.prototype.getHours()
描述:[0, 23]
时。
Date.prototype.getMinutes()
描述:[0, 59]
分。
Date.prototype.getSeconds()
描述:[0, 59]
秒。
Date.prototype.getMilliseconds()
描述:[0, 999]
毫秒。
Date.prototype.getDay()
描述:[0, 6]
星期。
0
:周天;1
:周一;6
:周六。
Date.prototype.getUTCFullYear()
描述:年(UTC)。
Date.prototype.getUTCMonth()
描述:[0, 11]
月(UTC)。
Date.prototype.getUTCDate()
描述:[1, 31]
日(UTC)。
Date.prototype.getUTCHours()
描述:[0, 23]
时(UTC)。
Date.prototype.getUTCMinutes()
描述:[0, 59]
分(UTC)。
Date.prototype.getUTCSeconds()
描述:[0, 59]
秒(UTC)。
Date.prototype.getUTCMilliseconds()
描述:[0, 999]
毫秒(UTC)。
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() ```
setter:
返回:一个数字(自1970-01-01 00:00:00 UTC到Date对象时间的毫秒)。
(除了
setTime
之外,)若参数超出了合理范围,则调整到相邻的时间(负数则减少1年/月/日/时/分/秒/毫秒,正数超过范围则增加1年/月/日/时/分/秒/毫秒)。
Date.prototype.setTime(距1970-01-01 00:00:00 UTC的毫秒)
描述:设置时间。
Date.prototype.setFullYear(年[, 月[, 日]])
描述:设置年。
Date.prototype.setMonth(月[, 日])
描述:设置月。
Date.prototype.setDate(日)
描述:设置日。
Date.prototype.setHours(时[, 分[, 秒[, 毫秒]]])
描述:设置时。
Date.prototype.setMinutes(分[, 秒[, 毫秒]])
描述:设置分。
Date.prototype.setSeconds(秒[, 毫秒])
描述:设置秒。
Date.prototype.setMilliseconds(毫秒)
描述:设置毫秒。
Date.prototype.setUTCFullYear(年[, 月[, 日]])
描述:设置年(UTC)。
Date.prototype.setUTCMonth(月[, 日])
描述:设置月(UTC)。
Date.prototype.setUTCDate(日)
描述:设置日(UTC)。
Date.prototype.setUTCHours(时[, 分[, 秒[, 毫秒]]])
描述:设置时(UTC)。
Date.prototype.setUTCMinutes(分[, 秒[, 毫秒]])
描述:设置分(UTC)。
Date.prototype.setUTCSeconds(秒[, 毫秒])
描述:设置秒(UTC)。
Date.prototype.setUTCMilliseconds(毫秒)
描述:设置毫秒(UTC)。
转换
转化为字符串:
Date.prototype.toDateString()
Date.prototype.toISOString()
Date.prototype.toJSON()
Date.prototype.toLocaleDateString()
Date.prototype.toLocaleString()
Date.prototype.toLocaleTimeString()
Date.prototype.toString()
Date.prototype.toTimeString()
Date.prototype.toUTCString()
转换为数字:
Date.prototype.valueOf()
Math
来自:MDN:Math。
部分是ES6。
方法
对参数先进行
Number(参数)
再进行方法;若参数无法转化为数字,则返回NaN
。
Math.abs(数字)
返回:数字的绝对值。
Math.ceil(数字)
返回:数字向上取整后的整数值。
Math.floor(数字)
返回:数字向下取整后的整数值。
Math.round(数字)
返回:数字四舍五入(不准确)后的整数值。
Math.random()
返回:[0,1)
的伪随机数。
Math.max(多个数字)
返回:多个数字中的最大值。
Math.min(多个数字)
返回:多个数字中的最小值。
Math.pow(基数, 指数)
返回:基数的指数次幂。
Math.sqrt(数字)
返回:数字的平方根。
Math.log(数字)
返回:数字的自然对数。
Math.exp(数字)
返回:e的数字指数的值。
1 * 弧度 === 1 * (180 / Math.PI)角度
。
Math.sin(弧度)
返回:弧度的正弦值。
Math.asin(数字)
返回:数字的反正弦值(弧度)。
Math.cos(弧度)
返回:弧度的余弦值。
Math.acos(数字)
返回:数字的反余弦值(弧度)。
Math.tan(弧度)
返回:弧度的正切值。
Math.atan(数字)
返回:数字的反正切值(弧度)。
Math.atan2(数字1, 数字2)
返回:数字2/数字1的反正切值(弧度)。
Math.trunc(数字)
返回:去除数字的小数部分,返回整数部分。
Math.sign(数字)
返回:根据数字是正数、负数、0
、-0
,分别返回+1
、-1
、0
、-0
。
Math.cbrt(数字)
返回:数字的立方根。
Math.hypot(多个数字)
返回:所有数字各自的平方和的平方根。
属性
Math.PI
描述:圆周率,约等于:3.14159。
Math.E
描述:欧拉常数,自然对数的底数, 约等于:2.718。
Math.LN2
描述:2的自然对数, 约等于:0.693。
Math.LN10
描述:10的自然对数, 约等于:2.303。
Math.LOG2E
描述:以2为底E的对数, 约等于:1.443。
Math.LOG10E
描述:以10为底E的对数, 约等于:0.434。
Math.SQRT1_2
描述:1/2的平方根, 约等于:0.707。
Math.SQRT2
描述:2的平方根,约等于:1.414。
来自:MDN:严格模式。
作用范围:全局(一个代码块<script>
内)或函数作用域。
合并一个全局的严格模式与其他非严格模式的代码,会导致所有合并代码均为严格模式。
默认参数
或解构赋值
或剩余参数
,就不能在函数体内显式指定严格模式。开启方式:作用域加上"use strict";
;ES6 Module默认要求、ES6的class
默认要求。
请确保
"use strict"
出现在脚本或函数的最顶部,否则严格模式可能无法启用。严格模式被开启后,无法再关闭。
声明时是严格模式,调用执行时才按照严格模式执行(与调用位置无关)。
建议不要混用严格模式、非严格模式(但使用第三方库时难以避免)。
影响
相对于非严格模式,增加的限制(违背则抛出错误):
将拼写错误转成异常
不可写
或只读
或不可扩展
的属性赋值或删除(引起非严格模式静默失败的情况)。不允许0数字
、'\0数字'
代表8进制。
0o数字
是ES6支持的8进制数。
不允许给基本数据类型设置属性。
基本数据类型:
Undefined
、Null
、Boolean
、Number
、String
、Symbol
、BigInt
。
简化变量使用
with
。安全
eval
不会在它的外层作用域引入变量。eval
、arguments
被绑定或赋值。arguments
属性不与参数同步更新。
可以分别修改
arguments
属性或参数,两者不会同步。
函数名.caller
、函数名.arguments
、arguments.caller
、arguments.callee
。this
指向undefined
而不指向被this替代后this
为传入的值(不会转化为基本包装类型;传入null/undefined
就为null/undefined
)。
在非严格模式,使用this替代:若是基本数据类型(除了
undefined/null
之外),则this
为那个值的基本包装类型;若不传或传入undefined/null
,则this
为全局对象。
为未来的ES铺平道路
增加一些字符成为保留关键字(不能作为变量名或方法名或类名)。
implements
、interface
、let
、package
、private
、protected
、public
、static
、yield
不允许在语句块(if
、for
)中使用函数声明。
ES6是一个历史名词:一般指ES2015;也泛指ES5.1版以后的JS下一代标准,涵盖ES2015、ES2016、ES2017、ES2018、ES2019、ES2020等。
虽然用babel转译ES6,但依然有部分机型/浏览器无法解析转译后的ES5代码,且越新的语法内容越多设备不支持。
let
、const
let
、const
(与var
的区别):
(除了全局、函数作用域之外,)拥有块级作用域(声明变量仅在块级作用域中有效,离开块级作用域删除)。
{/* 块级作用域 */}
with(){/* 块级作用域 */}
if(){/* 块级作用域 */}
for、for-in、for-of(/* 块级作用域-父级 */){/* 块级作用域-子级 */}
针对2个块级作用域,当闭包发生时(已经执行完毕,但异步任务返回父级作用域的变量):
var
创建的变量,则返回该变量最终值(与外部值相同)。let
(const
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) } ```
除了
for
、for-in
、for-of
的父级块级作用域和子级块级作用域有嵌套作用域关系,其他的块级作用域(包括循环for
、for-in
、for-of
、while
、do-while
的每一次迭代)都是互相独立,无法传递变量。
while(){/* 块级作用域 */}
、do{/* 块级作用域 */}while()
try{/* 块级作用域 */}catch(e){/* 块级作用域 */}finally{/* 块级作用域 */}
switch(){/* 块级作用域 */}
ES6之前可以用的块级作用域:
```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 ```with
(不安全、不推荐使用)、try-catch
window
暂时性死区(temporal dead zone):声明的变量直到控制流到达该变量被定义的代码行时才会被装载,所以在声明前使用会触发错误。
必要时提升,但没有提升的作用。在初始化之前,变量处于临时死区中并不可被访问。
const
let
基本一致。变量声明的6种方式
var
、function
let
、const
、class
、import
使用选择:用
let
、const
完全代替var
(不再使用);优先var
const
,当确定需改变的变量才改用let
。
箭头函数是匿名函数,适合非方法函数(匿名函数、函数表达式)。
写法
函数体没有大括号,隐式返回表达式内容
参数 => 表达式
或 (一个或多个参数) => 表达式
表达式是对象字面量时(期望返回这个对象字面量时),用
()
包裹,如:() => ({ a:1 })
。
函数体有大括号,不会自动返回内容(默认返回:undefined
),需要显式return
参数 => {块语句}
无参数
() => 表达式
或 _ => 表达式
不会创建箭头函数自己的this
、arguments
、super
、new.target
,根据词法作用域的方式向上遍历查找。
this
不会创建自己的this
(与function
关键字、简写的方法不同),而使用封闭执行上下文最近的一个this
值。因此对于this替代也无法改变箭头函数体内使用的this
。
new
yield
)。prototype
。简写属性
对象直接写变量:属性名为变量名, 属性值为变量的值。
简写方法
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)只能用这种简写方法方式
}
new
)。function
关键字一样产生this
作用域。并非所有情况都可以用简写
```javascript // 以下情况不适合用简写 var obj = { a: _.debounce(function () { // 使用apply的地方不能用箭头函数 console.log(this) }, 500) } ```
[JS表达式]
(若JS表达式的值不是字符串,则会调用它的toString
方法)
模板字符串(template literals)
`内容`
(返回字符串)
模板占位符
${部分JS表达式}
(返回字符串),内部还可嵌套模板字符串:${部分JS表达式 + `另一个模板字符串` }
。
若模板占位符内的结果是对象,则转换为字符串(
值.toString()
)输出。
不支持:
转义
除了字符串字面量转义内容('
和"
不需要转义),还需转义:\`
\${
。
多行书写
空格、新行、缩进,原样输出至生成的字符串。
String.raw`模板字符串`
等价于:
String.raw({ row: 可迭代对象 }[, 多个值])
。
获取模板字符串的原始字面量值(将所有变量替换,且把\
转义成\\
)。
标签模板(tagged template literals)
Unicode加强
\u{代码点序列}
e.g.
'\u{1F4A9}' === '💩' === '\ud83d\udca9'
可以被for-of
按完整字符遍历,for
或for-in
只能按1个字符-2个字节遍历。
默认参数用
=
设置默认值,对象的解构用:
换变量名;Typescript用:
定义形状。
解构赋值(destructuring assignment)
- 浅复制。
- 针对对象,解构自身和整条原型链(
[[Prototype]]
)上的(枚举+不枚举)属性(特殊:解构的剩余参数模式仅解构自身的属性)。
可迭代对象的解构:
声明或赋值或函数形参:
[多个变量名]=可迭代对象
可以嵌套任意深度的数组。
e.g.
[a, [b, [c]], d] = [null, [1, ['c']], {4: 'd'}]; // 等价于:a=null;b=1;c='c';d={4:'d'};
可以留空位跳过被解构数组中的元素。
e.g.
[a, , d] = [null, [1, ['c']], {4: 'd'}]; // 等价于:a=null;d={4:'d'};
解构内部支持:默认参数、剩余参数(可嵌套)。
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] ```
对象的解构(ECMAScript 2018):
声明或赋值或函数形参
var {对象名}=对象
(对象名为变量名)或var {对象名:对象值}=对象
(对象值为变量名)({对象名}=对象)
(对象名为变量名)或({对象名:对象值}=对象)
(对象值为变量名)e.g.
({a, b: c} = {a: 'a的值', b: 'c的值'}); // 等价于:a='a的值';c='c的值';(没有b的赋值)
可以嵌套任意深度的对象。
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) ```
解构内部支持:默认参数、剩余参数(剩余参数仅解构自身(不在原型链上)的属性,且剩余参数仅能作用于...变量名
、不能再嵌套解构)。
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 } ```
可以对有特殊属性名的对象进行解构。
e.g.
var { '.a_b': a } = { '.a_b': 11 }; a === 11
基本数据类型的解构:
null
和undefined
报错TypeError: null或undefined is not iterable (cannot read property Symbol(Symbol.iterator))
。其他类型
[变量名]=其他类型
TypeError: undefined is not a function
{变量名}=其他类型
返回undefined
,变量为默认参数值。
形参的解构:
除了仅适用解构变量、不支持解构内部的剩余参数再嵌套解构之外,与非形参的解构一致。
undefined
。默认参数(default parameters)
形参名=JS值
JS值
可以使用前置的形参变量。形参名=undefined
。undefined
时才使用默认参数(不传参等效于传参为undefined
)。剩余参数(rest parameters)
...变量名
(生成数组或对象,若没有项也生成[]
或{}
)
ES标准规定:使用
形参的解构
、默认参数
或剩余参数
的函数体内,禁止使用“use strict”。
展开元素(spread operator)
把可迭代对象
或对象
的值或变量名的自身(不在原型链上)的属性,全部拆分出使用(浅复制)。
可迭代对象
...可迭代对象的值或变量名
(非可迭代对象则报错TypeError: 某 is not iterable (cannot read property Symbol(Symbol.iterator))
)
...[]
不产生任何效果。e.g.[...[]] // []
- 仅对可迭代的项能够展开,如:
var a = []; a[1] = 'a1'; a['a'] = 'a2'; [...a] // [undefined, "a1"]
对象(ECMAScript 2018)
...对象的值或变量名
(基本数据类型则不产生任何效果)
...{}
、...undefined
不产生任何效果。e.g.{...{}} // {}
、{...undefined} // {}
- 仅对可枚举的项能够展开。
在某种程度上,
剩余参数
和展开元素
相反:剩余参数会收集多个元素和「压缩」成一个单一的元素,产生新的变量;展开元素会「展开」变成多个元素,产生用逗号分隔的参数序列。
一个模块就是一个独立的文件。
.js
、.mjs
文件、<script>
遵循相同模块规则。
概述
预编译阶段进行模块加载(静态分析):确定模块的依赖关系、输入和输出的变量。
export
和import
可以放在模块的任何位置,但必须处于模块顶层(若处于块级作用域内会报错)。
预编译阶段无法解析
```javascript // 报错(块级作用域) if (x === 1) { import { foo } from 'module1'; } else { import { foo } from 'module2'; } // 报错(表达式) import { 'f' + 'oo' } from 'my_module'; // 报错(变量) let module = 'my_module'; import { foo } from module; ```块级作用域、表达式、变量
import()
有自己单独作用域,不污染全局作用域,必须export
才能输出给其他模块。在严格模式下运行。
不推荐
window.属性
。
模块的加载逻辑:
预编译阶段确定模块加载顺序(最底层被依赖的模块——最后一个被import
的模块,最先执行),代码运行时按照确定的顺序一次性执行整个模块代码。
感官上:遇到
import
时,不会跳去执行其他模块(模块执行顺序已经在预编译阶段确定),而是直接利用其他模块的引用。
「循环加载」(circular dependency):
「循环加载」时忽略之前已经被依赖过的模块,最后加载最先出现的「循环加载」的模块。
循环依赖关系为
e.g. ```javascript // 按①②③④⑤⑥的顺序执行 // 入口 ... // ⑤ import 'a模块'; // ①②③④执行后,③④导出的内容 ... // ⑥ // a模块 ... // ③ import 'b模块'; // ①②执行后,①②导出的内容 ... // ④ // b模块 ... // ① import 'a模块'; // a模块未执行,导出为空 ... // ② ```入口 -> a -> b -> a
,模块执行顺序为b -> a -> 入口
,完整执行完一个模块才会进入下一个模块执行
「循环加载」的最先被执行模块无法获取其他模块的import
值(除了function
的提升),仅尝试声明。
import
module实例,则module实例被声明。import
内容为var
,则变量被声明,但未赋值。import
内容为let/const
,则变量未声明。若import
内容为function
,则方法被声明,可以使用(后加载的模块内方法声明会提升至先加载模块中使用)。
- 非「循环加载」的模块和「循环加载」第二个之后的模块,都能先获得
import
值(类似提升,还获得了引用值)。- JS不关心是否发生了「循环加载」,只生成一个指向被加载模块的引用,引用那个被导出的变量。
import
内容(类似变量提升,且可获得引用值)。import
内容与原模块导出的变量是动态绑定,import
出的内容不能赋值,但可以修改属性。
导出/导入的接口名与原模块内部变量间,建立了一一对应的关系。使用接口就是引用原模块的变量。
import { a } from '模块'
可以理解为:'模块'
是一个固定对象,a
是这个对象的属性名,且属性名不能赋值(但可以修改a
的属性)。
import
输入的变量都是只读的,类似于const
变量。
ES6 Module是一个多对象输出、多对象加载的模型:
输出任何模块内部的引用
export { A, B }
、export { A as a, B }
、export default A
、export const A = { }
加载模块中输出的任意引用
import A from ''
、import * as A from ''
、import { A, B } from ''
、import { A as a, B } from ''
(CORS)跨域的模块资源无法
import
引入,也无法通过<script>
以模块方式加载。
export
模块可以导出多个内容,导出变量名不能重复(因此default
只能导出一次)。
default
可以当作导出的默认变量。
export 声明语句
export {变量[, 变量]}
export {变量 as 外号变量[, 变量 as 外号变量]}
避免重命名;可以同一个变量使用多个外号变量。
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?。
export default 表达式
=== export {变量 as default}
e.g.
```javascript /* 表达式 */ number + 1 function () {} ok ? 'YES' : 'NO' Array.from(words).reverse().join('') /* 是语句,不是表达式 var a = 1 流控制不会生效,请使用三元表达式 if ... */ ```
不允许:
。必须输出export 值或变量名或方法名或类名
接口名
(声明
或{变量名或方法名或类名}
)。
import
import {导出的变量[, 导出的变量]} from '模块'
不允许
,因为import {default} from '模块'
default
是关键字,不能作为变量名;允许import {default as 外号变量} from '模块'
。
import {导出的变量 as 外号变量[, 导出的变量 as 外号变量]} from '模块'
避免重命名。
语法不支持直接在导入时解构
e.g. 、import { 变量: { 解构变量 } } from '模块'
、等。import { 变量 as 外号变量 : { 解构变量 } } from '模块'
import 外号变量 from '模块'
=== import {default as 外号变量} from '模块'
仅接受模块导出的
default
内容。
不能直接解构
需要2行代码进行: ```javascript import x, { c } from "./x"; const { a, b } = x; // ./x.js export default { a: 'a', b: 'b' } export const c = 'c' ```default
import * as Module实例 from '模块'
导出的变量(包括
default
)都成为Module
实例的属性(相当于导出命名空间),以Module实例.导出的变量
使用。Module实例
和Module实例.导出的变量
都是只读的,不可以赋值改变。
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
特性
未捕获的失败Promise实例会向全局抛出。
浏览器用window
的unhandledrejection
或Node.js用unhandledRejection
,处理全局未捕获的失败Promise实例。并不触发异常错误事件error
或uncaughtException
。
new Promise((resolve, reject) => { setTimeout(() => { 错误 }, 0) })
不会捕获异步操作中的错误(同理,在try-catch
或async-await
等语法中的异步错误也无法被捕获,但可以捕获await
的reject
)。可以在异步回调内部再包一层try-catch
、或用window
的error
事件捕获。
then
、catch
、finally
(解决回调地狱)。Promise实例拥有2个隐藏属性:
[[PromiseStatus]]
:状态(pending
、resolved
、rejected
)[[PromiseValue]]
:返回值Promise构造函数:
new Promise((resolve, reject) => {/* resolve(参数) 或 reject(参数) */}) // 第一参数必填且必须是方法
创建一个Promise实例。调用方法内部的resolve
则类似Promise.resolve(参数)
,调用方法内部的reject
则类似Promise.reject(参数)
。
resolve
或reject
虽然已经确定了状态,但还会继续向下执行剩余函数体,之后抛出的错误不计算在Promise内,会向上抛出错误。Promise.all(可迭代对象)
可迭代对象都完成则完成,有任一失败则失败。
向下链式传递的Promise实例
[[PromiseValue]]
为:所有成功项Promise实例[[PromiseValue]]
组成的数组、或第一个失败项Promise实例[[PromiseValue]]
。
Promise.all
与Promise.any
是相反的。
Promise.any(可迭代对象)
(ECMAScript 2021)
若只要其中的一个成功,则返回那个已经成功的promise;若可迭代对象中没有一个成功(即所有的promises都失败),则返回一个失败的promise和AggregateError类型(用于把单一的错误集合在一起)的实例。
Promise.race(可迭代对象)
可迭代对象首个完成则完成,首个失败则失败。
Promise.allSettled(可迭代对象)
(ECMAScript 2020)
类似Promise.all
,区别在于会等待参数全部处理完毕后再统一返回,不会短路。
手动创建完成/失败的Promise实例
Promise.resolve(参数) // 等价于:new Promise(resolve => resolve(参数))
不同参数类型对应的返回内容:
then
属性方法的对象:将这个对象转为Promise实例,然后立即执行这个对象的then
方法。[[PromiseValue]]
。Promise.reject(参数) // 等价于:new Promise((resolve, reject) => reject(参数))
失败状态的Promise实例,参数作为Promise实例[[PromiseValue]]
。
new Promise(回调)
的回调、Promise.all/race/any/allSettled([回调])
的回调、Promise.resolve/reject()
,都是同步任务。Promise.prototype.then/catch/finally(回调)
的回调,都是异步任务(microtask)。
Promise原型链(继承给所有实例)
Promise.prototype.then(resolve回调函数, reject回调函数)
Promise实例完成/失败则执行对应回调。接受前一个链式return
的值的[[PromiseValue]]
作为参数;回调函数return
的值作为Promise实例继续向下链式传递。
Promise.prototype.catch(reject回调函数)
Promise实例失败则执行回调(Promise实例成功则跳过不执行)。接受前一个链式return
的值的[[PromiseValue]]
作为参数;回调函数return
的值作为Promise实例继续向下链式传递。
因为链式的需要,建议
then
不要添加第二个参数,而都用catch
处理失败情况。
(
then/catch
)链式调用:后面链式内容根据前面回调函数返回值判断是否执行,参数和状态为前面链式返回的Promise实例[[PromiseValue]]
和[[PromiseStatus]]
。每次链式调用then
或catch
都会产生一个新的Promise实例,新生成的Promise实例就是then
或catch
的返回(若返回非Promise类型则返回值类似包裹着Promise.resolve(参数)
,若回调函数内抛出错误则返回rejected
)
Promise.prototype.finally(函数)
(ECMAScript 2018)
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得出结果之后进行 }); ```
可迭代对象(iterable):数据结构拥有
[Symbol.iterator]
属性方法(迭代器接口),调用返回迭代器。
可迭代对象的作用语法:
for-of
...可迭代对象
yield * 可迭代对象
- 可迭代对象的解构赋值
返回的值:调用可迭代对象的
[Symbol.iterator]
方法,获得迭代器,再遍历调用迭代器的next
方法获得对象的value值,返回,直到对象的done属性为true。迭代器(iterator,遍历器):对象实现
next
方法(return
、throw
方法可选),该方法返回包含done
、value
属性的对象。- 异步可迭代对象(asynchronous iterable):数据结构拥有
[Symbol.asyncIterator]
属性方法(异步迭代器接口),调用返回异步迭代器。- 异步迭代器(asynchronous iterator,异步遍历器):类似迭代器,区别是
next
方法返回一个Promise实例(其完成之后返回包含done
、value
属性的对象)。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 } ```
Array
、「TypedArray」
、Map
、Set
、arguments
、NodeList
、String
、生成器
异步生成器
async function * gen() {
yield 'hello';
}
const genObj = gen();
genObj.next().then(x => console.log(x));
// { value: 'hello', done: false }
yield *
跟一个异步迭代器for-of
for-in
建议仅遍历对象。
break
、continue
、return
若要额外获得每一项的key
1. 额外变量自增记录。 2. 改用`Array/Map/Set.prototype.forEach`。 3. `for (let [key, value] of Object.entries(可迭代对象)) {}`。
for-await-of
(ECMAScript 2018)遍历可迭代对象或异步可迭代对象自身的项。调用自定义迭代钩子,并为每个不同属性的值执行语句。
调用的生成器,是可迭代对象、也是迭代器。生成器内建
[Symbol.iterator]
、next
实现。
function *
声明、yield
语句。执行步骤:
每次调用生成器对象的next
,函数解冻并运行至下一个yield
(或return
),再次冻结。
返回值的value
为yield
或return
后的表达式,且是惰性求值,只有执行到时才会执行表达式。
return
),则done
为ture
;否则done
为false
。next
,则返回固定的{ value: undefined, done: true }
。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
。
执行步骤:
内置执行器,调用即可执行直到遇到await
(await
后若是方法则同步执行该方法),等待await
完成后(Promise
)继续执行剩余函数体;
await
后的剩余函数体:对这个async
而言是同步的执行的代码,因此可以被try-catch
捕获错误;对JS事件循环而言是异步任务microtask。
await
后的表达式类似包裹着Promise.resolve(表达式)
;
await
返回的是后面的[[PromiseValue]]
。如:若a = await Promise.resolve(值)
,则a === 值
(a
不是async
固定返回Promise实例(若返回非Promise实例,则返回值类似包裹着Promise.resolve(返回值)
),在函数体返回前,是未完成状态;
若因为函数体内没有
await
而去除async
标志,要注意此时的函数返回由原来返回Promise实例可能变成非Promise实例,影响调用函数之后是否可以链式调用Promise原型链方法(then/catch/finally
)。
返回:
await
返回失败的Promise或async
内部的错误(均表现为向上抛出错误异常,异常均可用try-catch
捕获化解),不再继续向下执行函数体,导致async
返回值为失败的Promise,Promise实例[[PromiseValue]]
为错误/失败信息;
async
方法内部未捕获的失败Promise实例,不会被async
内部处理(try-catch
包裹也不会处理)。未捕获的失败Promise实例会向全局抛出。
否则直到函数体执行完毕,根据async
返回值决定Promise状态。
async function func () { setTimeout(() => { 错误 }, 0) }
不会捕获异步操作中的错误(同理,在try-catch
或Promise
等语法中的异步错误也无法被捕获,但可以捕获await
的reject
)。可以在异步回调内部再包一层try-catch
、或用window
的error
事件捕获。
class
、class-extends
构造函数(原型链)的语法糖。
class
的数据类型是function
。
类声明时:
static
属性/方法直接是类的属性
;类.prototype
;实例的属性
。类声明时,类内部定义的属性/方法都不可枚举(类内部定义的静态属性是可枚举)、且方法都在严格模式下运行。
类内部的方法(尤其是constructor
)内能新增实例的属性/方法
或类.prototype.属性/方法
。
实例化时(
constructor
)、或实例化之后(实例调用方法)触发:
this.新增属性 = 新值
:新增实例的属性/方法
。this.__proto__.新增属性 = 新值
:新增类.prototype.属性/方法
。类声明完毕之后:
可以在类.prototype
上再添加的属性/方法:
类.prototype.新增属性 = 新值
Object.assign(类.prototype, { 新增属性: 新值 })
Object.defineProperty(类.prototype, '新增属性', 数据属性或访问器属性)
(或Object.defineProperties
)可以在类
上再添加静态方法:
类.新增属性 = 新值
新增的内容为:可枚举(若属性描述为不可枚举则不可枚举)、在严格模式下运行。
new
调用类,否则报错TypeError: Class constructor 类名 cannot be invoked without 'new'
。this
指向:
this
指向实例或类名(static)外部定义
this
指向实例或类名(static)this
指向window或global(严格模式为undefined)类不存在变量提升(要先声明类才能使用)。
原因:类可以继承、且类可以表达式写法,必须保证子类在父类之后定义。
```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
class-extends
继承
prototype
属性的函数(除了Function.prototype
函数)和null
,因此也可继承内置构造函数。 class Father {}
class Son extends Father {
constructor(...args) { // 省略则默认仅调用`super(...args)`
super(...args) // 子类的构造函数必须执行一次`super`
// this. // 调用了`super`之后才可以使用this
}
}
Son.__proto__ === Father // true
Son.prototype.__proto__ === Father.prototype // true
Father.__proto__ === Function.prototype // true
Father.prototype.__proto__ === Object.prototype // true
new Son().__proto__.__proto__ === new Father().__proto__ // true
super
原型对象
(只允许在对象的简写方法中使用,且必须带有属性/方法super.属性/方法
)。class-extends
- 子类的构造函数中指向父类构造函数的调用(只允许在子类的构造函数中使用
super()
);- 子类的任意函数中指向父类方法的访问(只允许在子类中使用,且必须带有属性/方法:
super.属性/方法
)。super
调用的父级方法中的this
,均指向子类实例或子类。
通过super()
调用父类构造函数(父类方法中的this
指向子类实例)。
给子类的实例添加父类的
实例的属性
。
引用
super.属性/方法
访问父类.prototype.属性/方法
(父类方法中的this
指向子类实例)。super.属性/方法
访问为父类.静态属性/静态方法
(父类静态方法中的this
指向子类)赋值(等价于this.属性 = 新值
)
super.属性 = 新值
为子类实例赋值。super.属性 = 新值
为子类赋值(静态属性/静态方法)。new.target
返回new
命令作用于的那个构造函数。
若子类继承父类,则
super
调用父级时,new.target
指向子类。
new
undefined
。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
类型的值与其他任何值不相等)。
作为属性键
不被大部分遍历方法返回:
for-in
、Object.entries/values/keys/getOwnPropertyNames
、JSON.stringify
能够返回:
Object.getOwnPropertySymbols
、对象的展开元素、Map类型的遍历、Reflect.ownKeys
+
、`${Symbol类型的值}`
)。Symbol
不是new
Set
、Map
、WeakSet
、WeakMap
Set
不重复值的集合(通过类似===
判断是否相同,额外能判断NaN === NaN
成立)。
可以直接用for-of
遍历、直接用...Set类型的值
拆分。
每项输出值
。
Map
类似对象的hash结构,键-值的键
可以是任何值(对象的键只能是String
或Symbol
类型,若不是,则会使用键.toString()
转换后的字符串作为键)。
可以直接用for-of
遍历、直接用...Map类型的值
拆分。
每项输出[键, 值]
。
WeakSet
与Set
类似(不重复的值的集合)。
WeakSet
的成员值引用的对象不计算被WeakSet
引用次数。若其成员值引用的对象被垃圾回收机制释放,则这个成员被移除。WeakMap
与Map
类似(键可以是任何值)。
WeakMap
的成员键所指向的对象不计算被WeakMap
引用次数。若其成员键引用的对象被垃圾回收机制释放,则这个成员被移除。新增2进制、8进制写法
2进制:
0b二进制数
、0B二进制数
8进制:
0o八进制数
、0O八进制数
0八进制数
(ES5,不推荐)
Number
、Math
对象的扩展
Proxy
new Proxy(target, handler)
拦截原始语言功能。
handler
可用的拦截属性方法Reflect
操作对象的默认行为。
Proxy
的handler方法一一对应的静态函数BigInt
(ECMAScript 2019)BigInt
不是new
Array.prototype.includes
新增:**
幂运算符
类似于
Math.pow
。e.g.2 ** 3 === 8 /* 2的3次方 */
async-await
语法Object.entries
、Object.values
、Object.getOwnPropertyDescriptors
String.prototype.padStart
、String.prototype.padEnd
function func(a, b, c,) {}; func(1, 2,)
)SharedArrayBuffer
、Atomics
(共享内存位置读取和写入)Promise.prototype.finally
for-await-of
移除带标签的模版字符串中转义序列的语法限制
遇到不合法的字符串转义返回undefined
,并且从raw
上可获取原字符串。
U+2028
)和段分隔符(U+2029
)符号现在允许在字符串文字中,与JSON匹配更改:JSON.stringify
可返回不符合UTF-8标准的字符串。
String.prototype.trimStart
、String.prototype.trimEnd
Object.fromEntries
更改:Array.prototype.sort
稳定性
排序关键字相同的项目其排序前后的顺序不变,默认为稳定。
新增:Array.prototype.flat
、Array.prototype.flatMap
扁平化数组,返回新数组;映射且扁平化数组,返回新数组(只能展开一层数组)。
Function.prototype.toString
现在返回精确字符,包括空格和注释,函数原始代码(与编码一致)。try-catch
可以使用catch(e){}
或catch{}
;修改 catch 绑定Symbol.prototype.description
新增:BigInt
可以超过Number.MIN_SAFE_INTEGER
至Number.MAX_SAFE_INTEGER
。
Promise.allSettled
新增:可选链?.
(若操作符前是undefined/null
则返回undefined
,否则返回右边的属性值)
e.g.
null?.a
、null?.['a'+'b']
、null?.[0]
、null?.()
可选链不能用于赋值
e.g.
object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment
当在表达式中使用可选链时,若左操作数是null
或undefined
,表达式将不会被计算
e.g.
object?.[x++]; // 若object为null或undefined,则x++不会进行执行
??
(若操作符左边的值是undefined/null
则使用操作符后面的值)import()
(返回Promise实例)新增: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
String.prototype.matchAll
更改:for-in
标准化遍历顺序
不同的引擎已就如何迭代属性达成一致,从而使行为标准化。
String.prototype.replaceAll
Promise.any
新增:||=
、&&=
、??=
a ||= b
等价于a || (a = b)
a &&= b
等价于a && (a = b)
a ??= b
等价于a ?? (a = b)
WeakRef
新增:_
分隔数字
e.g.
1_00 === 100
、1_00 === 10_0
document
来自:MDN:document。
获取DOM
方法
document.querySelector(CSS选择器)
- 或
dom.querySelector(CSS选择器)
。- 从自己开始(包括自己)查找最近的一个祖先元素
dom.closest(CSS选择器)
。
document.querySelectorAll(CSS选择器)
或
dom.querySelectorAll(CSS选择器)
。
document.getElementById(Id名)
document.getElementsByTagName(标签名)
document.getElementsByTagNameNS(命名空间, 标签名)
document.getElementsByClassName(类名)
document.getElementsByName(name属性)
属性(只读)
document.documentElement
返回文档的根元素(如:HTML的<html>
)。
document.getElementsByTagName('html')[0] === document.documentElement
document.body
(可写)返回文档的<body>
或<frameset>
。
document.getElementsByTagName('body')[0] === document.body
document.scrollingElement
返回document.documentElement
或document.body
。
document.scrollingElement === document.documentElement || document.body
document.head
返回文档中<head>
。
document.getElementsByTagName('head')[0] === document.head
document.styleSheets
返回文档中<style>
、<link rel="stylesheet">
组成的数组。
document.scripts
返回文档中<script>
组成的数组。
document.images
返回文档中<img>
组成的数组。
document.links
返回文档中具有href
属性的<area>
、<a>
组成的数组。
document.embeds
返回文档中<embed>
组成的数组。
document.forms
返回文档中<form>
组成的数组。
document.execCommand(命令的名称, false, 额外参数)
操作contenteditable="true"
的DOM文本选区覆盖的内容。
操作的内容会读取原本已经应用的CSS内容。
document.queryCommandState(命令的名称)
检查当前光标所在地方是否有某种样式,返回true/false
。
来自: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); } }); ```
window
location
location
中改变路由或刷新页面都会改变document.referrer
。
navigator
screen
history
来自:MDN:history。
属性
history.length
返回(只读)浏览历史记录的数量。
history.state
返回(只读)当前页面的state对象。
history.scrollRestoration
返回/设置重新加载页面时是否滚动到之前位置。auto
(默认)滚动至之前位置;manual
滚动至页面顶部。
方法
history.go(数字)
跳转跨度几个浏览历史记录,正数向前、负数向后、0
或不传参则刷新当前页面。
history.back()
等价于:history.go(-1)
。
history.forward()
等价于:history.go(1)
。
history.pushState(state对象, 标题字符串, URL字符串)
不触发页面刷新、不触发
hashchange
事件,若设置跨域网址则报错。不会改变document.referrer
。
添加并切换到一个最新的浏览历史记录,地址栏变成URL字符串。
history.replaceState(state对象, 标题字符串, URL字符串)
不触发页面刷新、不触发
hashchange
事件,若设置跨域网址则报错。不会改变document.referrer
。
覆盖现在所在的浏览历史记录,地址栏变成URL字符串。
state对象
:
- 可以是任何类型的值。可填
null
。
history.state
返回的值。- window的
popstate
事件触发时,回调函数的参数的state
属性。history.pushState
、history.replaceState
的第一个参数。标题字符串
:页面标题。但所有浏览器目前都忽略这个值,可填null
。URL字符串
:修改浏览器的地址栏,必须同域。
history.go/back/forward
对于document.referrer
:
- 若导致重新载入页面(之前是重新载入而记录进
history
),则改变document.referrer
。- 若没有导致重新载入页面(之前是
history.pushState/replaceState
而记录进history
),则不会改变document.referrer
。
window的popstate
事件
文档的history
变化时触发:
history.back/forward/go
时。使用location
修改URL但不重新载入页面时。
location.hash/search
赋值导致改变URL时触发,其他情况不触发。
调用 或 pushState
时不触发;页面第一次加载时不触发;内部replaceState
<iframe>
不触发。
Blob
Blob
(binary large object,二进制大型对象):用2进制的方式处理文件(展示、下载、传输)。
Blob
创建Blob URL(伪协议):URL.createObjectURL(Blob实例)
因为
File
基于Blob
,所以也可以:URL.createObjectURL(File实例)
。
返回URL对象的DOMString(blob:http://地址
或blob:https://地址
)。
可用于Blob实例内容的访问、下载,如:文件下载,图片展示。
获取Base64值
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:一个字符串以表示所读取的文件内容
本地文件的Base64值
input节点.files
是FileList
,FileList
的每一项是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 URL
或Base64
写入节点的src
中(如:<img>
、<video>
、<audio>
)。
IntersectionObserver
// 提供异步观察目标元素与其祖先元素或顶级文档视窗(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() // 关闭观察者
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
// 监测性能度量事件,包含:
// 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
统计页面从打开到加载完成的时间数据,基本覆盖所有性能优化参数指标。但无法统计内存占用相关情况。
window.performance.timing
window.performance.getEntriesByType('navigation')[0]
优化参照
白屏时间(首元素可见):
performance.timing.domLoading - performance.timing.fetchStart
.html下载完成并开始解析HTM。
首屏可见:
白屏时间 + 首屏渲染时间
解析到首屏底部的某个DOM(如:
MutationObserver
或用<script>
标记)。首屏可交互:
performance.timing.domContentLoadedEventEnd - performance.timing.fetchStart
非异步JS都执行完毕。
加载完成:
performance.timing.loadEventEnd - performance.timing.fetchStart
触发window的load事件(所有资源加载完毕)。
结果判断:
(在控制变量的情况下)埋点上报统计出优化前后的点击/展示的变化。
console
字符串替换:
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.table
适合针对数组、对象打印成表格方式展示。
console.dir
适合针对DOM、函数打印其属性。
FormData
参考:MDN:FormData。
new FormData(<from>元素或空)
FormData.prototype.append/delete/entries/forEach/get/getAll/has/keys/set/values
e.g.
```javascript const formData = new FormData() formData.append(名, 值[, 文件名]) // ...等 ```
fetch
fetch(地址或Request实例[, 配置])
:发起请求,返回Promise实例(Promise实例完成的参数是Response
实例)。
e.g.
fetch("地址", { headers: { 'Content-Type': 'application/json' }, method: "POST", body: JSON.stringify({a: 1, b: 2}) })
。
fetch
是一项新技术,不是实现(XMLHttpRequest
axios
在浏览器是XMLHttpRequest
封装实现)。fetch
和XMLHttpRequest
的请求传递的信息和处理逻辑略有不同。
Headers
参考:MDN:Headers。
new Headers(对象或Headers实例或空)
Headers.prototype.append/delete/entries/forEach/get/has/keys/set/values
Request
参考:MDN:Request。
new Request(地址或Request实例[, 配置])
new Request()
参数与于fetch()
参数完全一致。
Response
参考:MDN:Response。
new Response(body, 配置)
传参:
body
:null
、Blob
、BufferSource
、FormData
、ReadableStream
、URLSearchParams
或USVString
对象。配置
:
status
:response的状态码,如:200
。statusText
:与状态码关联的状态消息,如:OK
。headers
:response的任何headers,Headers
实例或对象。实例的属性:
.headers
、.ok
、.status
、.statusText
、.url
、.type
、.redirected
等
实例的方法:
.json
、.text
、.formData
、.blob
、.arrayBuffer
、.clone
、等
实例实现了Body
接口
WebSocket
参考:MDN:WebSocket。
new WebSocket(ws服务器URL[, 子协议的字符串或数组])
原型链属性
.CONNECTING === 0
、.OPEN === 1
、.CLOSING === 2
、.CLOSED === 3
.onclose
、onerror
、onmessage
、onopen
.binaryType
(websocket连接所传输二进制数据的类型:'blob'
、'arraybuffer'
)bufferedAmount
(未发送至服务器的字节数)extensions
(服务器已选择的扩展值)protocol
(服务器端选中的子协议的字符串或数组,实例化时的第二个参数)readyState
(链接状态:.CONNECTING
、.OPEN
、.CLOSING
、.CLOSED
)url
(链接的绝对路径)原型链方法
.send(文本(String)或 二进制数据(Blob实例或Arraybuffer实例))
.close([状态码[, 关闭原因]])
状态码:MDN: WebSocket关闭码。
实例事件
close
(或.onclose
)、error
(或.onerror
)、message
(或.onmessage
)、open
(或.onopen
)
Node.js实现WebSocket的服务端和客户端(不支持
浏览器):ws。
Deferred
参考:阮一峰:jQuery的deferred对象详解、阮一峰:jQuery.Deferred对象、jQuery:延迟对象。
Deferred对象
创建Deferred对象:
$.Deferred()
Deferred对象的状态:
触发状态:
改变状态:
.resolve()
、.resolveWith()
、.reject()
、.rejectWith()
状态不改变,仅发起一个通知:
.notify()
、notifyWith()
以上所有方法仅在pending状态有效
.resolve/resolveWith()
触发函数:.done
、.always()
、.then(第一个参数)
.reject/rejectWith()
触发函数:.fail
、.always()
、.then(第二个参数)
、.catch()
.notify/notifyWith()
触发函数:.progress()
、.then(第三个参数)
获得状态:.state()
返回三者之一:'pending'
、'resolved'
、'rejected'
。
当Deferred对象状态改变后(或发起notify
通知),根据相应的状态触发回调
向下传递调用方法的对象本身:.done()
、.fail()
、.progress()
、.always()
。
Deferred对象调用则返回Deferred对象;Promise对象调用则返回Promise对象。
向下传递回调函数的return
内容:.then(解决, 拒绝, 通知)
、.catch(拒绝)
。
返回为Promise对象。
且判断:jQuery.when(Deferred对象或其他值)
。
若传入的不是Deferred对象,则当做立即解决的值:$.Deferred().resolve(参数)
。
返回为Promise对象。
改变为Promise对象:.promise()
。
Promise对象
Deferred对象
的子集。
相对于Deferred对象,Promise对象无法改变执行状态:
屏蔽与改变执行状态有关的方法:
resolve
、resolveWith
、reject
、rejectWith
、notify
、notifyWith
开放与改变执行状态无关的方法:
done
、fail
、progress
、always
、then
、catch
、promise
、state
$.ajax
返回Promise对象
。.promise().done(方法)
,使节点所有动画都结束后调用方法)。浏览器事件
resize
仅针对$(window)
。
$(window).resize(func)
、$(window).on('resize', func)
$(window).resize()
、$(window).trigger('resize')
scroll
不冒泡。仅监听自己DOM的滚动,子节点滚动不触发。
.scroll(func)
、.on('scroll', func)
.scroll()
、.trigger('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`切换。scroll
冒泡效果
error
(建议用原生事件)
不冒泡。
jQuery不推荐
on
等方式绑定window
的error
事件,只通过原生的window
的error
定义。
.on('error', func)
.trigger('error')
load
(不可靠、建议用原生事件)
不冒泡。适用于任何可使用URL
关联的元素:<img>
、<link>
、<script>
、<iframe>
、window
。
资源完全加载完毕后触发。
.on('load', func)
.trigger('load')
ready
仅针对$(document)
。
DOM加载解析完毕后触发。若不在ready后才操作DOM,会导致DOM的
properties
可能尚未设置完毕,从而获取到DOM默认的properties
。
$(document).ready(func)
、$(func)
、$().ready(func)
表单事件
blur
不冒泡,直接绑定后无法监听子节点blur
的冒泡。但可以用事件代理(自动转换为focusout
),
.blur(func)
、.on('blur', func)
.blur()
、.trigger('blur')
focus
不冒泡,直接绑定后无法监听子节点focus
的冒泡。但可以用事件代理(自动转换为focusin
),
.focus(func)
、.on('focus', func)
.focus()
、.trigger('focus')
focusout
.focusout(func)
、.on('focusout', func)
.focusout()
、.trigger('focusout')
focusin
.focusin(func)
、.on('focusin', func)
.focusin()
、.trigger('focusin')
change
按钮选择改变、文本内容修改并且失去焦点、文件选择变化。原始的
input
事件是有输入内容就触发。
.change(func)
、.on('change', func)
.change()
、.trigger('change')
select
鼠标选中输入框的文字。
.select(func)
、.on('select', func)
.select()
、.trigger('select')
submit
.submit(func)
、.on('submit', func)
.submit()
、.trigger('submit')
键盘事件
keydown
哪一个键被按下。按住不断触发。
.keydown(func)
、.on('keydown', func)
.keydown()
、.trigger('keydown')
keyup
哪一个键被按下。按住抬起仅触发一次。
.keyup(func)
、.on('keyup', func)
.keyup()
、.trigger('keyup')
keypress
实际输入的文本。按住不断触发。
.keypress(func)
、.on('keypress', func)
.keypress()
、.trigger('keypress')
鼠标事件
mousedown
、mouseup
、click
、dblclick
、contextmenu
、mousemove
、hover
、mouseenter
、mouseleave
、mouseover
、mouseout
只有在事件处理程序执行期间,事件对象才会存在;一旦事件处理程序执行完毕,事件对象就会销毁。
约定:
/* jQuery(或Zepto)对象包装的DOM元素 */$dom.on(..., function (e) {});
、this
为默认值。
e.originalEvent === window.event
e.currentTarget
在事件冒泡过程中的当前DOM元素(事件绑定的DOM),e.currentTarget === this
。
e.target
最深层被触发的目标元素(捕获的终点、冒泡的起点)。
ie是
事件对象.srcElement
。
e.delegateTarget
绑定的宿主。
e.relatedTarget
在事件中涉及的其它任何DOM元素。
e.pageX/Y
鼠标相对于文档的左/上边缘的位置。
e.data
传入处理函数的额外参数。
e.namespace
事件被触发时包含的命名空间。
e.type
事件类型名。
e.which
返回键盘或鼠标(左键:1;中键:2;右键:3)的数字。
e.result
获取前一个事件的返回值。
e.timeStamp
触发时的时间戳。
e.eventPhase
当前事件处理程序所在阶段:0
,没有事件正在被处理;1
,捕获;2
,处于目标;3
,冒泡。
e.trusted
是否为用户触发:true
,用户或浏览器触发;false
,JS触发。
e.preventDefault()
默认事件行为将不再触发。
ie是
事件对象.returnValue = false
。
e.isDefaultPrevented()
事件对象是否调用过e.preventDefault()
。
e.stopPropagation()
阻止事件捕获和冒泡。
ie是
事件对象.cancelBubble = true
。
e.isPropagationStopped()
事件对象是否调用过e.stopPropagation()
。
e.stopImmediatePropagation()
阻止剩余的事件处理程序执行并且阻止事件捕获和冒泡。
e.isImmediatePropagationStopped()
事件对象是否调用过e.stopImmediatePropagation()
。
在webpack打包时,可以在JS文件中混用
require
和export
,但是不能混用。最好统一为某一种规范去使用,不要混用。import
和module.exports
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规范的代码。
转义字符:\
。
转义字符不会计算在:字符串的
length
,字符串的replace
等。
字符串字面量:
来自: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'
。
模板字符串:
除了字符串字面量的转义内容('
和"
不需要转义),还需转义:
字符 | 表示的意义(需要转义的特殊字符) |
---|---|
\` |
` |
\${ |
${ (单独出现${ 表示模板占位符的开始) |
正则表达式字面量:
需要转义的特殊字符:(
)
[
]
{
}
\
/
^
$
|
?
*
+
.
某些方法允许传入的参数来设置this的指向:
Function.prototype.call/apply/bind
Array.prototype.forEach/map/filter/every/some/find/findIndex
Array.from
Set.prototype.forEach
Map.prototype.forEach
「TypedArray」.prototype.forEach/map/filter/every/some/find/findIndex
NodeList.prototype.forEach
「DOMTokenList」.prototype.forEach
CSS选择器
来自:阮一峰:CSS选择器笔记。参考:W3C:selectors。
基本选择器
*
通配符选择器,匹配所有元素。
E
元素选择器,匹配使用E标签的元素。
.className
类选择器,匹配class属性中包含「className」的元素。
#idName
ID选择器,匹配id属性等于「idName」的元素。
关系选择器
E1,E2
多元素选择器,同时匹配E1元素或E2元素。
派生选择器:通过依据元素在其位置的上下文关系来定义样式。因此下面4个是派生选择器。
E1 E2
后代元素选择器,匹配属于E1元素后代的E2元素。
E1>E2
子元素选择器,匹配E1元素的子元素E2。
E1+E2
相邻兄弟选择器,匹配紧随E1元素之后的同级元素E2。
E1~E2
通用兄弟选择器,匹配在E1元素之后的同级E2元素。
属性选择器
- 属性值的引号可加可不加;若属性值含有空格或特殊字符,必须用引号包围。
- 建议始终用(双)引号包围属性值。
[attrName]
匹配具有「attrName」属性的元素,不考虑它的值。
[attrName=val]
匹配「attrName」属性等于「val」的元素。
[attrName~=val]
匹配「attrName」属性具有多个空格分隔的值、其中一个值等于「val」的元素。
[attrName|=val]
匹配「attrName」属性等于「val」或以「val-」开头的元素。
主要用于lang属性,如:”en”、”en-us”、”en-gb”等。
[attrName^=val]
属性「attrName」的值以「val」开头的元素。
[attrName$=val]
属性「attrName」的值以「val」结尾的元素。
[attrName*=val]
属性「attrName」的值包含「val」字符串的元素。
伪元素选择器
:before
在元素之前插入生成的内容。
:after
在元素之后插入生成的内容。
:first-line
匹配元素的第一行。
:first-letter
匹配元素的第一个字母。
伪类选择器
普通伪类
:link
匹配未被点击的链接。
:visited
匹配已被点击的链接。
:active
匹配鼠标已经对其按下、还没有释放的元素。
:hover
匹配鼠标悬停其上的元素。
:focus
匹配获得当前焦点的元素。
:lang(val)
匹配lang属性等于「val」的元素。
与用户界面有关的伪类
:enabled
匹配表单中激活的元素。
:disabled
匹配表单中禁用的元素。
:checked
匹配表单中被选中的radio
(单选框)或checkbox
(复选框)。
::selection
匹配用户当前选中的元素(如:鼠标或其他选择设备选中的部分)。
jQuery选择器无法选中内容;仅能作为CSS选择器添加样式属性。
结构性伪类
:root
匹配文档的根元素,对于HTML文档,就是HTML元素。
:nth-child(num)
匹配其父元素的第num个子元素,第一个编号为1。
:nth-last-child(num)
匹配其父元素的倒数第num个子元素,倒数第一个编号为1。
:nth-of-type(num)
与:nth-child(num)
作用类似,但是仅匹配使用同种标签的元素。
:nth-last-of-type(num)
与:nth-last-child(num)
作用类似,但是仅匹配使用同种标签的元素。
:first-child
匹配父元素的第一个子元素,等同于:nth-child(1)
。
:last-child
匹配父元素的最后一个子元素,等同于:nth-last-child(1)
。
:first-of-type
匹配父元素下使用同种标签的第一个子元素,等同于:nth-of-type(1)
。
:last-of-type
匹配父元素下使用同种标签的最后一个子元素,等同于:nth-last-of-type(1)
。
:only-child
匹配父元素下仅有的一个子元素,等同于:first-child:last-child
或:nth-child(1):nth-last-child(1)
。
:only-of-type
匹配父元素下使用同种标签的唯一一个子元素,等同于:first-of-type:last-of-type
或:nth-of-type(1):nth-last-of-type(1)
。
:empty
匹配一个不包含任意子元素的元素。注意:文本节点也被看作子元素。
:not(selector)
匹配不符合「selector」选择器的元素。注意:「selector」不能再包含:not
。
:target
匹配文档URI的片段标识符,对应相同id属性的元素。
jQuery专有选择器
来自:jQuery:Selectors。
jQuery兼容CSS所有选择器,并进行了扩展。
因为不是CSS规范的一部分,专有选择器无法利用本机DOM的
document.querySelectorAll
提升性能。为了提高代码性能,建议使用filter
、not
、has
、eq
等jQuery方法以及转化为CSS规范的选择器,来合理使用。
[attrName!=val]
匹配「attrName」属性不等于「val」的元素。
:first
匹配文档顺序的第一个元素。
:last
匹配文档顺序的最后一个元素。
:eq(num)
匹配文档顺序的第num个元素,0位第一个,-1为倒数第一个。
:even
匹配文档顺序的偶数元素,索引为0、2、4…。
:odd
匹配文档顺序的奇数元素,索引为1、3、5…。
:gt(num)
匹配索引大于(不包括等于)num的元素,0位第一个,-1为倒数第一个。
:lt(num)
匹配索引小于(不包括等于)num的元素,0位第一个,-1为倒数第一个。
:button
匹配button, [type=button]
的元素。
:file
匹配['type=file']
的元素。
:image
匹配[type=image]
的元素。
:input
匹配input, textarea, select, button
的元素。
:password
匹配[type=password]
的元素。
:radio
匹配[type=radio]
的元素。
:reset
匹配[type=reset]
的元素。
:submit
匹配[type=submit]
的元素。
:text
匹配[type=text]
的元素。
:selected
匹配选中的元素(适用于<option>
)。
:parent
匹配一个包含任意子元素的元素。注意:文本节点也被看作子元素。
:contains(val)
匹配含有「val」字符串(区分大小写)的元素,可以是后代包含。
:animated
匹配此时处于动画进度中的元素。
:has(selector)
匹配符合「selector」选择器的元素。
:header
匹配h1, h2, h3, h4, h5, h6
的元素。
:hidden
匹配隐藏的元素。
:visible
匹配显示的元素。
变量名:
以--
开头,大小写敏感,不能包含 、$
、[
、^
、(
等字符。%
定义、使用:
: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; */
}
用法
只能用作CSS属性值,不可以用作CSS属性名
.foo {
--side: margin-top;
/* 无效 */
var(--side): 20px;
}
变量值类型
数值:
不可以与单位连用,要用calc
.foo {
--size: 20;
/* 无效,解析为:font-size: 20 px; */
font-size: var(--size)px;
/* 有效 */
margin-top: calc(var(--size) * 1px);
}
若变量值带有单位,则不能写成字符串。
/* 无效 */
.foo {
--foo: '20px';
font-size: var(--foo);
}
/* 有效 */
.foo {
--foo: 20px;
font-size: var(--foo);
}
嵌套作用域