引用类型

基本引用类型

Date

要创建日期对象,就使用 new 操作符来调用 Date 构造函数:

let now = new Date()

Date 类型将日期保存为自协调世界时(UTC,Universal Time Coordinated)时间 1970 年 1 月 1 日午夜(零时)至今所

表示其他时间

Date.parse()

Date.parse()方法接收一个表示日期的字符串参数,尝试将这个字符串转换为表示该日期的毫秒数。

let someDate = new Date(Date.parse("May 23, 2019"))
let someDate = new Date("May 23, 2019")

Date.UTC()

传给 Date.UTC()的参数是年、零起点月数(1 月是 0,2 月是 1,以此类推)、日(131)、时(023)、分、秒和毫秒。这些参数中,只有前两个(年和月)是必需的。

如果不提供日,那么默认为 1 日

let y2k = new Date(Date.UTC(2000, 0))
// GMT 时间2005 年5 月5 日下午5 点55 分55 秒
let allFives = new Date(Date.UTC(2005, 4, 5, 17, 55, 55))

获取执行的时间毫秒数

Date.now()

// 起始时间
let start = Date.now()
// 调用函数
doSomething()
// 结束时间
let stop = Date.now(),
  result = stop - start

日期格式化

let now = new Date()
//toDateString()显示日期中的周几、月、日、年(格式特定于实现);
//Tue Mar 30 2021
console.log(now.toDateString())
// toLocaleDateString()显示日期中的周几、月、日、年(格式特定于实现和地区)
// 2021/3/30
console.log(now.toLocaleDateString())
// toTimeString()显示日期中的时、分、秒和时区(格式特定于实现
// 11:30:01 GMT+0800 (中国标准时间)
console.log(now.toTimeString())
// toLocaleTimeString()显示日期中的时、分、秒(格式特定于实现和地区);
// 上午11:30:01
console.log(now.toLocaleTimeString())
// toUTCString()显示完整的UTC 日期(格式特定于实现
//Tue, 30 Mar 2021 03:30:01 GMT
console.log(now.toUTCString())

常用方法

方法描述
getDate()从 Date 对象返回一个月中的某一天 (1 ~ 31)。
getDay()从 Date 对象返回一周中的某一天 (0 ~ 6)。
getMonth()从 Date 对象返回月份 (0 ~ 11)。
getFullYear()从 Date 对象以四位数字返回年份。
getHours()返回 Date 对象的小时 (0 ~ 23)。
getMinutes()返回 Date 对象的分钟 (0 ~ 59)。
getSeconds()返回 Date 对象的秒数 (0 ~ 59)。
getMilliseconds()返回 Date 对象的毫秒(0 ~ 999)。
getTime()返回 1970 年 1 月 1 日至今的毫秒数。
setDate()设置 Date 对象中月的某一天 (1 ~ 31)。
setMonth()设置 Date 对象中月份 (0 ~ 11)。
setFullYear()设置 Date 对象中的年份(四位数字)。
setHours()设置 Date 对象中的小时 (0 ~ 23)。
setMinutes()设置 Date 对象中的分钟 (0 ~ 59)。
setSeconds()设置 Date 对象中的秒钟 (0 ~ 59)。
setMilliseconds()设置 Date 对象中的毫秒 (0 ~ 999)

RegExp

ECMAScript 通过 RegExp 类型支持正则表达式。正则表达式使用类似 Perl 的简洁语法来创建:

let expression = /pattern/afgls

flags

每个正则表达式可以带零个或多个 flags(标记),用于控制正则表达式的行为

 g:全局模式,表示查找字符串的全部内容,而不是找到第一个匹配的内容就结束。
 i:不区分大小写,表示在查找匹配时忽略 pattern 和字符串的大小写。
 m:多行模式,表示查找到一行文本末尾时会继续查找。
 y:粘附模式,表示只查找从 lastIndex 开始及之后的字符串。
 u:Unicode 模式,启用 Unicode 匹配。
 s:dotAll 模式,表示元字符.匹配任何字符(包括\n 或\r)。

// 匹配字符串中的所有"at"
let pattern1 = /at/g
// 匹配第一个"bat"或"cat",忽略大小写
let pattern2 = /[bc]at/i
// 匹配所有以"at"结尾的三字符组合,忽略大小写
let pattern3 = /.at/gi

pattern

元字符

元字符(Metacharacter)是拥有特殊含义的字符:

元字符描述
.查找单个字符,除了换行和行结束符。
\w查找单词字符。word
\W查找非单词字符。
\d查找数字。digit
\D查找非数字字符。
\s查找空白字符。space
\S查找非空白字符。
\b匹配单词边界。border
\B匹配非单词边界。
\0查找 NUL 字符。
\n查找换行符。
\f查找换页符。
\r查找回车符。
\t查找制表符。
\v查找垂直制表符。
\xxx查找以八进制数 xxx 规定的字符。
\xdd查找以十六进制数 dd 规定的字符。
\uxxxx查找以十六进制数 xxxx 规定的 Unicode 字符。
匹配abc开头的字符串
\babc
量词
量词描述
n+匹配任何包含至少一个 n 的字符串。
n*匹配任何包含零个或多个 n 的字符串。
n?匹配任何包含零个或一个 n 的字符串。
n{X}匹配包含 X 个 n 的序列的字符串。
n{X,Y}匹配包含 X 至 Y 个 n 的序列的字符串。
n{X,}匹配包含至少 X 个 n 的序列的字符串。
n$匹配任何结尾为 n 的字符串。
^n匹配任何开头为 n 的字符串。
?=n匹配任何其后紧接指定字符串 n 的字符串。
?!n匹配任何其后没有紧接指定字符串 n 的字符串。
匹配8位数字
^\d{8}
匹配14~18的数字
^\d{14,18}
分组

正则表达式中用小括号()来做分组,也就是括号中的内容作为一个整体。

匹配字符串包含0到多个 ab开头
^(ab)*
转义
匹配(ab)开头
^(\(ab\))*
条件或

正则用符号 | 来表示或,也叫做分支条件,当满足正则里的分支条件的任何一种条件时,都会当成是匹配成功。

区间

正则提供一个元字符中括号 [] 来表示区间条件

[0-9]查找任何从 0 至 9 的数字。
[a-z]查找任何从小写 a 到小写 z 的字符。
[A-Z]查找任何从大写 A 到大写 Z 的字符。
[A-z]查找任何从大写 A 到小写 z 的字符。
[adgk]查找给定集合内的任何字符。
[^adgk]查找给定集合外的任何字符

实列属性

属性描述FFIE
globalRegExp 对象是否具有标志 g。14
ignoreCaseRegExp 对象是否具有标志 i。14
lastIndex一个整数,标示开始下一次匹配的字符位置。14
multilineRegExp 对象是否具有标志 m。14
source正则表达式的源文本。14

实例方法

exec()
//string	必需。要检索的字符串。
//返回的数组是Array实例,但还包含额外两个属性:index和input
//属性index和input:
//index表示匹配项在字符串中的起始位置。
//input表示应用正则表达式的字符串。
//返回包含第一个匹配项信息的数组,或者在没有匹配项时返回null
RegExpObject.exec(string)

有 global 匹配,非 global 匹配

global 模式执行 exec()匹配成功一次以后,再次执行 exec()时,会从前一次匹配的最后一位开始继续向后匹配

var exp = /.at/g
var matches = exp.exec('cat, bat, sat, fat'); //第一次匹配
matches.index => 0
matches.input => 'cat, bat, sat, fat'
matches => ['cat']
exp.lastIndex => 3

matches = exp.exec('cat, bat, sat, fat'); //第二次匹配
matches.index => 5
matches.input => 'cat, bat, sat, fat'
matches => ['bat']
exp.lastIndex => 8

非 global 模式执行 exec()匹配成功一次以后,再次执行 exec()时,会从头开始重新匹配。

var exp = /.at/
var matches = exp.exec('cat, bat, sat, fat'); //第一次匹配
matches.index => 0
matches.input => 'cat, bat, sat, fat'
matches => ['cat']
exp.lastIndex => 0


matches = exp.exec('cat, bat, sat, fat'); //第二次匹配
matches.index => 0
matches.input => 'cat, bat, sat, fat'
matches => ['cat']
exp.lastIndex => 0

当使用(…)分组匹配时,一次 exec()会匹配到多个结果

var exp = /(there)\s+(you)\s+(are)/
var matches = exp.exec("hey, there you are my dear")
matches = ["there you are", "there", "you", "are"]

matches[0]匹配整个表达式字符串。
matches[1]匹配第一个(…)内的字符串,之后以此类推。

test()
//如果字符串 string 中含有与 RegExpObject 匹配的文本,则返回 true,否则返回 false。
RegExpObject.test(string)

string方法

search()
//search不支持全局搜索,它会忽略global标识。
//返回值
//stringObject 中第一个与 regexp 相匹配的子串的起始位置。
//如果没有找到任何匹配的子串,则返回 -1。
stringObject.search(regexp)
replace()
//第一个参数是一个正则表达式,第二个参数是要替换成的字符串。如果exp带有global标识,那么源字符str中所有与exp表达式匹配的子串都会被替换。如果不带g,str中仅第一个与exp匹配的子串会被替换。
//返回一个新的字符串,是用 replacement 替换了 regexp 的第一次匹配或所有匹配之后得到的。
stringObject.replace(regexp / substr, replacement)
match()
//返回一个由匹配结果组成的数组
//当有global标识时,match返回全局匹配到的所有字符串组成的数组;当没有global标识时,match就返回第一个匹配到的字符串组成的单元素数组。
stringObject.match(regexp)

'11+2=13'.match(/\d/g) => ['1','1','2','1','3']
'11+2=13'.match(/\d/) => ['1']
split()
//separator	必需。字符串或正则表达式,从该参数指定的地方分割 stringObject。//howmany	可选。该参数可指定返回的数组的最大长度。如果设置了该参数,返回的子串不会多于这个参数指定的数组。如果没有设置该参数,整个字符串都会被分割,不考虑它的长度。stringObject.split(separator,howmany)'1   ,  ,2 , 3  ,   4  ,  5'.split(/\s*,\s*/) => ['1','2','3','4','5']

进阶

零宽断言

正向先行断言(正前瞻)

  • 语法:(?=pattern)
  • 作用:匹配 pattern 表达式的前面内容,不返回本身。
var str = "abZW863"
var reg = /ab(?=[A-Z])/
console.log(str.match(reg))
//匹配后面跟随任意一个大写字母的字符串"ab"。最终匹配结果是"ab"
//因为零宽断言"(?=[A-Z])"并不匹配任何字符,只是用来规定当前位置的后面必须是一个大写字母。

负向先行断言(负前瞻)

  • 语法:(?!pattern)
  • 作用:匹配非 pattern 表达式的前面内容,不返回本身。
var str = "abZW863"
var reg = /ab(?![A-Z])/
console.log(str.match(reg))
//匹配后面不跟随任意一个大写字母的字符串"ab"

正向后行断言(正后顾):

  • 语法:(?<=pattern)
  • 作用:匹配 pattern 表达式的后面的内容,不返回本身。

负向后行断言(负后顾)

  • 语法:(?<!pattern)
  • 作用:匹配非 pattern 表达式的后面内容,不返回本身。
捕获

在正则表达式中,使用“()”进行分组,一对圆括号括起来的表达式就是一个分组。

捕获性分组工作模式()会把每个分组里匹配的值保存起来,方便接下来的操作

var rel = /([a-z]+)\s([a-z]+)/
var text = "alen turing"
var matches = text.match(rel)
console.log(matches)
//["alen turing", "alen", "turing"]

js 中每一个括号匹配的内容可以被 RegExp 对象捕获到(最多匹配九个,可以通过返回一个数组索引来取得所有的括号匹配项.)

var reg = /([a-z]+)(\d+)/ //匹配一个或多个字母,和一个或多个数字
reg.test("hello123") //ture
console.log(RegExp.$1) //输出 hello,即匹配的第一个括号里的内容
console.log(RegExp.$2) //输出 123  ,即匹配的第二个括号里的内容

从左向右,分组以的左括号为标志,第一个出现的分组的组号为 1,第二个为 2,以此类推。

反向引用

组捕获可以反向引用(在表达式中直接使用某个分组的内容)

var rel = /([0-9])\1\1/ //要一个aaa式的数字
var text = "333"
var matches = text.match(rel)
console.log(matches)
//["333", "3"]

使用’\ num’(num 是编号)这个方法就可以实现在表达式中引用捕获组的内容

var rel = /([a-z]+)\s([a-z]+)/
var text = "alen turing"
var arr_2 = text.replace(rel, "$2 $1")
console.log(arr_2) //"turing alen"
贪婪和非贪婪

贪婪匹配:当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符,这匹配方式叫做贪婪匹配

懒惰

懒惰匹配:当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能少的字符,这匹配方式叫做懒惰匹配

懒惰量词是在贪婪量词后面加个“?”

原始值包装类型

Boolean

Boolean 是对应布尔值的引用类型

let booleanObject = new Boolean(true)

Boolean 的实例会重写 valueOf()方法,返回一个原始值 true 或 false。toString()方法被调用时也会被覆盖,返回字符串"true"或"false"

原始值和引用值(Boolean 对象)区别

typeof 操作符对原始值返回"boolean",但对引用值返回"object"。

Boolean 对象是 Boolean 类型的实例,在使用 instaceof 操作符时返回 true,但对原始值则返回 false

Number

Number 是对应数值的引用类型。要创建一个 Number 对象,就使用 Number 构造函数并传入一个数值

let numberObject = new Number(10)

Number 类型重写了 valueOf()、toLocaleString()和 toString()方法。valueOf()方法返回 Number 对象表示的原始数值,另外两个方法返回数值字符串。

toFixed()

返回包含指定小数点位数的数值字符串

let num = 10
console.log(num.toFixed(2)) // "10.00"

toExponential()

返回以科学记数法(也称为指数记数法)表示的数值字符串

let num = 10
console.log(num.toExponential(1)) // "1.0e+1"

原始数值在调用 typeof 时始终返回"number",而 Number 对象则返回"object"。类似地,Number 对象是 Number 类型的实例,而原始数值不是。

isInteger()

辨别一个数值是否保存为整数

console.log(Number.isInteger(1)) // true
console.log(Number.isInteger(1.0)) // true
console.log(Number.isInteger(1.01)) // false

String

String 是对应字符串的引用类型。要创建一个 String 对象,使用 String 构造函数并传入一个数值

let stringObject = new String("hello world")

JavaScript 字符串由 16 位码元(code unit)组成

charCodeAt()

返回指定索引位置的码元值,索引以整数指定

let message = "abcde"
// Unicode "Latin small letter C"的编码是U+0063
console.log(message.charCodeAt(2)) // 99

formCharCode()

根据给定的 UTF-16 码元创建字符串中的字符

console.log(String.fromCharCode(0x61, 0x62, 0x63, 0x64, 0x65)) // "abcde"
字符串操作方法

concat()

将一个或多个字符串拼接成一个新字

let stringValue = "hello "
let result = stringValue.concat("world")
console.log(result) // "hello world"
console.log(stringValue) // "hello"

可以接收任意多个参数

let stringValue = "hello "
let result = stringValue.concat("world", "!")
console.log(result) // "hello world!"
console.log(stringValue) // "hello"

slice()

方法提取某个字符串的一部分,并返回一个新的字符串,且不会改动原字符串。

str.slice(beginIndex[, endIndex])
//beginIndex
//从该索引(以 0 为基数)处开始提取原字符串中的字符。如果值为负数,会被当做 `strLength + beginIndex` 看待,这里的`strLength` 是字符串的长度(例如, 如果 `beginIndex` 是 -3 则看作是:`strLength - 3`)
//endIndex
//可选。在该索引(以 0 为基数)处结束提取字符串。如果省略该参数,slice() 会一直提取到字符串末尾。如果该参数为负数,则被看作是 strLength + endIndex,这里的 strLength 就是字符串的长度(例如,如果 endIndex 是 -3,则是, strLength - 3)。
const str = "The quick brown fox jumps over the lazy dog."
console.log(str.slice(31))
// expected output: "the lazy dog."

split()

**split()**方法使用指定的分隔符字符串将一个String对象分割成子字符串数组,以一个指定的分割字串来决定每个拆分的位置

str.split([separator[, limit]])
//separator
//指定表示每个拆分应发生的点的字符串。separator 可以是一个字符串或正则表达式。 如果纯文本分隔符包含多个字符,则必须找到整个字符串来表示分割点。如果在str中省略或不出现分隔符,则返回的数组包含一个由整个字符串组成的元素。如果分隔符为空字符串,则将str原字符串中每个字符的数组形式返回
//limit
//一个整数,限定返回的分割片段数量。当提供此参数时,split 方法会在指定分隔符的每次出现时分割该字符串,但在限制条目已放入数组时停止。如果在达到指定限制之前达到字符串的末尾,它可能仍然包含少于限制的条目。新数组中不返回剩下的文本


const str = "The quick brown fox jumps over the lazy dog."
const words = str.split(" ")
console.log(words[3])
// expected output: "fox"

substr()

substr() 方法返回一个字符串中从指定位置开始到指定字符数的字符。

str.substr(start[, length])
//start
//开始提取字符的位置。如果为负值,则被看作 strLength + start,其中 strLength 为字符串的长度(例如,如果 start 为 -3,则被看作 strLength + (-3))。
//length
//可选。提取的字符数。
var str = "abcdefghij"
console.log("(1,2): " + str.substr(1, 2)) // (1,2): bc

substring()

**substring()**方法返回一个字符串在开始索引到结束索引之间的一个子集, 或从开始索引直到字符串的末尾的一个子集。

str.substring(indexStart[, indexEnd])
//indexStart
//需要截取的第一个字符的索引,该索引位置的字符作为返回的字符串的首字母。
//indexEnd
//可选。一个 0 到字符串长度之间的整数,以该数字为索引的字符不包含在截取的字符串内。
var anyString = "Mozilla"
// 输出 "Moz"
console.log(anyString.substring(0, 3))
字符串位置方法

indexOf()

indexOf() 方法返回调用它的 String 对象中第一次出现的指定值的索引,从 fromIndex 处进行搜索。如果未找到该值,则返回 -1。

str.indexOf(searchValue [, fromIndex])
//searchValue要被查找的字符串值。
//fromIndex 可选  数字表示开始查找的位置。可以是任意整数,默认值为 0。
"Blue Whale".indexOf("Blue") // 返回 0
"Blue Whale".indexOf("Whale", 0) // 返回 5
"Blue Whale".indexOf("Whale", 5) // 返回 5

lastIndexOf()

lastIndexOf() 方法返回调用String 对象的指定值最后一次出现的索引,在一个字符串中的指定位置 fromIndex处从后向前搜索。如果没找到这个特定值则返回-1

str.lastIndexOf(searchValue[, fromIndex])
//searchValue
//一个字符串,表示被查找的值。如果searchValue是空字符串,则返回fromIndex。
//fromIndex可选
//待匹配字符串searchValue的开头一位字符从 str的第fromIndex位开始向左回向查找。fromIndex默认值是 +Infinity。如果 fromIndex >= str.length ,则会搜索整个字符串。如果 fromIndex < 0 ,则等同于 fromIndex == 0。
"canal".lastIndexOf("a")
// returns 3 (没有指明fromIndex则从末尾l处开始反向检索到的第一个a出现在l的后面,即index为3的位置)
"canal".lastIndexOf("a", 2)
// returns 1(指明fromIndex为2则从n处反向向回检索到其后面就是a,即index为1的位置)
"canal".lastIndexOf("a", 0)
// returns -1(指明fromIndex为0则从c处向左回向检索a发现没有,故返回-1)
字符串包含方法

startsWith()

startsWith() 方法用来判断当前字符串是否以另外一个给定的子字符串开头,并根据判断结果返回 truefalse

str.startsWith(searchString[, position])
//searchString
//要搜索的子字符串。
//position 可选
//在 str 中搜索 searchString 的开始位置,默认值为 0。
const str1 = "Saturday night plans"

console.log(str1.startsWith("Sat"))
// expected output: true

endsWith()

**endsWith()**方法用来判断当前字符串是否是以另外一个给定的子字符串“结尾”的,根据判断结果返回 truefalse

str.endsWith(searchString[, length])
//searchString
//要搜索的子字符串。
//length 可选
//作为 str 的长度。默认值为 str.length。
const str1 = "Cats are the best!"

console.log(str1.endsWith("best", 17))
// expected output: true

includes()

includes() 方法用于判断一个字符串是否包含在另一个字符串中,根据情况返回 true 或 false。

str.includes(searchString[, position])
//searchString
//要在此字符串中搜索的字符串。
//position 可选
//从当前字符串的哪个索引位置开始搜寻子字符串,默认值为 0。
字符串清楚空格方法

trim()

trimLeft()/trimStart()

trimRight()/trimEnd()

字符串赋值方法

repeat()

repeat() 构造并返回一个新字符串,该字符串包含被连接在一起的指定数量的字符串的副本。

str.repeat(count)
//count
//介于 0 和 +Infinity 之间的整数。表示在新构造的字符串中重复了多少遍原字符串。
"abc".repeat(-1) // RangeError: repeat count must be positive and less than inifinity
"abc".repeat(0) // ""
"abc".repeat(1) // "abc"
"abc".repeat(2) // "abcabc"

padStart()

padStart() 方法用另一个字符串填充当前字符串(如果需要的话,会重复多次),以便产生的字符串达到给定的长度。从当前字符串的左侧开始填充。

str.padStart(targetLength [, padString])
//targetLength
//当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身。
//padString 可选
//填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截断。此参数的默认值为 " "(U+0020)
"abc".padStart(10) // "       abc"
"abc".padStart(10, "foo") // "foofoofabc"
"abc".padStart(6, "123465") // "123abc"
"abc".padStart(8, "0") // "00000abc"
"abc".padStart(1) // "abc"

padEnd()

padEnd() 方法会用一个字符串填充当前字符串(如果需要的话则重复填充),返回填充后达到指定长度的字符串。从当前字符串的末尾(右侧)开始填充

str.padEnd(targetLength [, padString])//targetLength//当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身。//padString 可选//填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截断。此参数的缺省值为 " "(U+0020)。
"abc".padEnd(10) // "abc       ""abc".padEnd(10, "foo") // "abcfoofoof""abc".padEnd(6, "123456") // "abc123""abc".padEnd(1) // "abc"
字符串迭代与解构

@@iterator

let message = "abc"
let stringIterator = message[Symbol.iterator]()
console.log(stringIterator.next()) // {value: "a", done: false}
console.log(stringIterator.next()) // {value: "b", done: false}
console.log(stringIterator.next()) // {value: "c", done: false}
console.log(stringIterator.next()) // {value: undefined, done: true}

for-of

for (const c of "abcde") {
  console.log(c)
}
// a
// b
// c
// d
// e
字符串大小写转换

toLowerCase()

toLocaleLowerCase()

toUpperCase()

toLocaleUpperCase()

字符串匹配方法

match()

search()

replace()

字符串比较方法

localeCompare()

最后一个方法是 localeCompare(),这个方法比较两个字符串,返回如下 3 个值中的一个

 如果按照字母表顺序,字符串应该排在字符串参数前头,则返回负值。(通常是-1,具体还要看
与实际值相关的实现。)
 如果字符串与字符串参数相等,则返回 0。
 如果按照字母表顺序,字符串应该排在字符串参数后头,则返回正值。(通常是 1,具体还要看
与实际值相关的实现。)

let stringValue = "yellow"
console.log(stringValue.localeCompare("brick")) // 1
console.log(stringValue.localeCompare("yellow")) // 0
console.log(stringValue.localeCompare("zoo")) // -1

单例内置对象

Global

不存在全局变量或全局函数这种东西。在全局作用域中定义的变量和函数都会变成 Global 对象的属性 。

URL编码

encodeURI()

encodeURI 会替换所有的字符,但不包括以下字符,即使它们具有适当的 UTF-8 转义序列:

类型包含
保留字符; , / ? : @ & = + $
非转义的字符字母 数字 - _ . ! ~ * ' ( )
数字符号#
let uri = "http://www.wrox.com/illegal value.js#start"

console.log(encodeURI(uri))
// "http://www.wrox.com/illegal%20value.js#start"

encodeURIComponent()

encodeURIComponent 转义除了如下所示外的所有字符:

不转义的字符:
    A-Z a-z 0-9 - _ . ! ~ * ' ( )
let uri = "http://www.wrox.com/illegal value.js#start"

console.log(encodeURIComponent(uri))
// "http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.js%23start"

eval()方法

当解释器发现 eval()调用时,会将参数解释为实际的 ECMAScript 语句,然后将其插入到该位置。
通过 eval()执行的代码属于该调用所在上下文,被执行的代码与该上下文拥有相同的作用域链。这意
味着定义在包含上下文中的变量可以在 eval()调用内部被引用

Math

Math 对象属性
属性描述
E返回算术常量 e,即自然对数的底数(约等于 2.718)。
LN2返回 2 的自然对数(约等于 0.693)。
LN10返回 10 的自然对数(约等于 2.302)。
LOG2E返回以 2 为底的 e 的对数(约等于 1.414)。
LOG10E返回以 10 为底的 e 的对数(约等于 0.434)。
PI返回圆周率(约等于 3.14159)。
SQRT1_2返回返回 2 的平方根的倒数(约等于 0.707)。
SQRT2返回 2 的平方根(约等于 1.414)。
min()和max()

min()和 max()方法用于确定一组数值中的最小值和最大值。这两个方法都接收任意多个参数

let max = Math.max(3, 54, 32, 16)
console.log(max) // 54
let min = Math.min(3, 54, 32, 16)
console.log(min) // 3
舍入方法

ceil()

始终向上舍入为最接近的整数

console.log(Math.ceil(25.9)) // 26
console.log(Math.ceil(25.5)) // 26
console.log(Math.ceil(25.1)) // 26

floor()

始终向下舍入为最接近的整数

console.log(Math.floor(25.9)) // 25
console.log(Math.floor(25.5)) // 25
console.log(Math.floor(25.1)) // 25

round()

方法执行四舍五入

console.log(Math.round(25.9)) // 26
console.log(Math.round(25.5)) // 26
console.log(Math.round(25.1)) // 25

fround()

返回数值最接近的单精度(32 位)浮点值表示

console.log(Math.fround(0.4)) // 0.4000000059604645
console.log(Math.fround(0.5)) // 0.5
console.log(Math.fround(25.9)) // 25.899999618530273
random()方法

方法返回一个 0~1 范围内的随机数,其中包含 0 但不包含 1

let num = Math.floor(Math.random() * 10 + 1)
//0~10
其他方法
方法描述
abs(x)返回数的绝对值。
acos(x)返回数的反余弦值。
asin(x)返回数的反正弦值。
atan(x)以介于 -PI/2 与 PI/2 弧度之间的数值来返回 x 的反正切值。
atan2(y,x)返回从 x 轴到点 (x,y) 的角度(介于 -PI/2 与 PI/2 弧度之间)。
ceil(x)对数进行上舍入。
cos(x)返回数的余弦。
exp(x)返回 e 的指数。
floor(x)对数进行下舍入。
log(x)返回数的自然对数(底为 e)。
max(x,y)返回 x 和 y 中的最高值。
min(x,y)返回 x 和 y 中的最低值。
pow(x,y)返回 x 的 y 次幂。
random()返回 0 ~ 1 之间的随机数。
round(x)把数四舍五入为最接近的整数。
sin(x)返回数的正弦。
sqrt(x)返回数的平方根。
tan(x)返回角的正切。
toSource()返回该对象的源代码。
valueOf()返回 Math 对象的原始值。

集合引用类型

Object 类型

//创建方法
1
var person = new Object()
person.name = "Nicholas"
person.age = 29
2
var person = {
  name: "Nicholas",
  age: 29,
}
person["name"] = "Nicholas"
3
var person = {} //与 new Object()相同
person.name = "Nicholas"
person.age = 29

Array 类型

ECMAScript 数组的每一项可以保存任何类型的数据

数据大小是可以动态调整的,即可以随着数据的添加自动增长以容 纳新增数据

创建数组

使用 Array 构造函数

var colors = new Array()
//将创建 length 值为 20的数组
var colors = new Array(20)
var colors = new Array("red", "blue", "green")
//使用 Array 构造函数时也可以省略 new 操作符
var colors = Array(3) // 创建一个包含 3 项的数组
var names = Array("Greg") // 创建一个包含 1 项,即字符串"Greg"的数组

使用数组字面量(array literal)表示法

let colors = ["red", "blue", "green"] // 创建一个包含3 个元素的数组
let names = [] // 创建一个空数组
let values = [1, 2] // 创建一个包含2 个元素的数组

from()

Array.from() 方法从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。

Array.from(arrayLike[, mapFn[, thisArg]])
//arrayLike
//想要转换成数组的伪数组对象或可迭代对象。
//mapFn 可选
//如果指定了该参数,新数组中的每个元素会执行该回调函数。
//thisArg 可选
//可选参数,执行回调函数 mapFn 时 this 对象。
console.log(Array.from("foo"))
// expected output: Array ["f", "o", "o"]

console.log(Array.from([1, 2, 3], (x) => x + x))
// expected output: Array [2, 4, 6]

of()

**Array.of()** 方法创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。

Array.of(element0[, element1[, ...[, elementN]]])
//elementN
//任意个参数,将按顺序成为返回数组中的元素。
Array.of(7) // [7]
Array.of(1, 2, 3) // [1, 2, 3]

Array(7) // [ , , , , , , ]
Array(1, 2, 3) // [1, 2, 3]

数组空位

使用数组字面量初始化数组时,可以使用一串逗号来创建空位(hole)。ECMAScript 会将逗号之间
相应索引位置的值当成空位,ES6 新增方法普遍将这些空位当成存在的元素,只不过值为 undefined

const options = [, , , , ,] // 创建包含5 个元素的数组
console.log(options.length) // 5
console.log(options) // [,,,,,]

for (const option of options) {
  console.log(option === undefined) //true --5
}

ES6 之前的方法会忽略这个空位,但具体的行为也会因方法而异

const options = [1, , , , 5]
// map()会跳过空位置
console.log(options.map(() => 6)) // [6, undefined, undefined, undefined, 6]
// join()视空位置为空字符串
console.log(options.join("-")) // "1----5"

数组索引

要取得或设置数组的值,需要使用中括号并提供相应值的数字索引

let colors = ["red", "blue", "green"] // 定义一个字符串数组
alert(colors[0]) // 显示第一项
colors[2] = "black" // 修改第三项
colors[3] = "brown" // 添加第四项

数组 length 属性的独特之处在于,它不是只读的。通过修改 length 属性,可以从数组末尾删除或添加元素

let colors = ["red", "blue", "green"] // 创建一个包含3 个字符串的数组
colors.length = 2
alert(colors[2]) // undefined

检测数组

一个经典的 ECMAScript 问题是判断一个对象是不是数组。在只有一个网页(因而只有一个全局作
用域)的情况下,使用 instanceof

if (value instanceof Array) {
  // 操作数组
}

如果要把数组从一个框架传给另一个框架,则这个数组的构造函数将有别于在第二个框架内本地创建的数组。

if (Array.isArray(value)) {
  // 操作数组
}

迭代器方法

keys()

**keys()方法返回一个包含数组中每个索引键的Array Iterator**对象。

const a = ["foo", "bar", "baz", "qux"]
const aKeys = Array.from(a.keys())
console.log(aKeys) // [0, 1, 2, 3]

values()

values() 方法返回一个新的 Array Iterator 对象,该对象包含数组每个索引的值

const a = ["foo", "bar", "baz", "qux"]
const aValues = Array.from(a.values())
console.log(aValues) // ["foo", "bar", "baz", "qux"]

entries()

entries() 方法返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对。

const a = ["foo", "bar", "baz", "qux"]
const aEntries = Array.from(a.entries())
console.log(aEntries) // [[0, "foo"], [1, "bar"], [2, "baz"], [3, "qux"]]

复制和填充方法

copyWithin()

**copyWithin()** 方法浅复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度。

arr.copyWithin(target[, start[, end]])
// target
// 0 为基底的索引,复制序列到该位置。如果是负数,target 将从末尾开始计算。
// 如果 target 大于等于 arr.length,将会不发生拷贝。如果 target 在 start 之后,复制的序列将被修改以符合 arr.length。
// start
// 0 为基底的索引,开始复制元素的起始位置。如果是负数,start 将从末尾开始计算。
// 如果 start 被忽略,copyWithin 将会从0开始复制。
// end
// 0 为基底的索引,开始复制元素的结束位置。copyWithin 将会拷贝到该位置,但不包括 end 这个位置的元素。如果是负数, end 将从末尾开始计算。
// 如果 end 被忽略,copyWithin 方法将会一直复制至数组结尾(默认为 arr.length)。
[1, 2, 3, 4, 5].copyWithin(-2)
// [1, 2, 3, 1, 2]

[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]

[1, 2, 3, 4, 5].copyWithin(0, 3, 4)
// [4, 2, 3, 4, 5]

[1, 2, 3, 4, 5].copyWithin(-2, -3, -1)
// [1, 2, 3, 3, 4]

fill()

fill() 方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。

arr.fill(value[, start[, end]])
// value
// 用来填充数组元素的值。
// start 可选
// 起始索引,默认值为0。
// end 可选
// 终止索引,默认值为 this.length。
;[1, 2, 3].fill(4) // [4, 4, 4]
;[1, 2, 3].fill(4, 1) // [1, 4, 4]
;[1, 2, 3].fill(4, 1, 2) // [1, 4, 3]
;[1, 2, 3].fill(4, 1, 1) // [1, 2, 3]
;[1, 2, 3].fill(4, 3, 3) // [1, 2, 3]
;[1, 2, 3].fill(4, -3, -2) // [4, 2, 3]
;[1, 2, 3].fill(4, NaN, NaN) // [1, 2, 3]
;[1, 2, 3].fill(4, 3, 5) // [1, 2, 3]

转换方法

toLocaleString()

返回一个字符串表示数组中的元素。数组中的元素将使用各自的 toLocaleString 方法转成字符串,这些字符串将使用一个特定语言环境的字符串(例如一个逗号 “,”)隔开。

arr.toLocaleString([locales[,options]]);
//locales 可选
//带有BCP 47语言标记的字符串或字符串数组,关于locales参数的形式与解释,请看Intl页面。
//options 可选
//一个可配置属性的对象,对于数字 Number.prototype.toLocaleString(),对于日期Date.prototype.toLocaleString().
var prices = ['¥7', 500, 8123, 12];
prices.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY' });

// "¥7,¥500,¥8,123,¥12"

toString()

返回一个字符串,表示指定的数组及其元素。

arr.toString()
const array1 = [1, 2, 'a', '1a'];

console.log(array1.toString());
// expected output: "1,2,a,1a"

valueOf()

valueOf()返回的还是数组本身。

栈方法

栈是一种后进先出(LIFO,Last-In-First-Out)的结构

push()

push()方法接收任意数量的参数,并将它们添加到数组末尾,返回数组的最新长度

pop()

pop()方法则用于删除数组的最后一项,同时减少数组的length 值,返回被删除的项

队列方法

队列以先进先出(FIFO,First-In-First-Out)形式限制访问。队列在列表末尾添加数据,但从列表开头获取数据

shift()

shift()删除数组的第一项并返回它,然后数组长度减1。

push()

push()方法接收任意数量的参数,并将它们添加到数组末尾,返回数组的最新长度

排序方法

reverse()

reverse()方法就是将数组元素反向排列。

sort()

sort() 方法用原地算法对数组的元素进行排序,并返回数组

arr.sort([compareFunction])
//compareFunction 可选
//用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的各个字符的Unicode位点进行排序。
//firstEl
//第一个用于比较的元素。
//secondEl
//第二个用于比较的元素。
var numbers = [4, 2, 5, 1, 3];
numbers.sort((a, b) => a - b);
console.log(numbers);

// [1, 2, 3, 4, 5]

操作方法

concat()

方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。

var new_array = old_array.concat(value1[, value2[, ...[, valueN]]])
//valueN可选
//数组和/或值,将被合并到一个新的数组中。如果省略了所有 valueN 参数,则 concat 会返回调用此方法的现存数组的一个浅拷贝
var alpha = ['a', 'b', 'c'];
var numeric = [1, 2, 3];

alpha.concat(numeric);
// result in ['a', 'b', 'c', 1, 2, 3]

slice()

方法返回一个新的数组对象,这一对象是一个由 beginend 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。

arr.slice([begin[, end]])
var fruits = ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango'];
var citrus = fruits.slice(1, 3);

// fruits contains ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango']
// citrus contains ['Orange','Lemon']

splice()

方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。

array.splice(start[, deleteCount[, item1[, item2[, ...]]]])

//start​
//指定修改的开始位置(从0计数)。如果超出了数组的长度,则从数组末尾开始添加内容;如果是负值,则表示从数组末位开始的第几位(从-1计数,这意味着-n是倒数第n个元素并且等价于array.length-n);如果负数的绝对值大于数组的长度,则表示开始位置为第0位。

//deleteCount 可选
//整数,表示要移除的数组元素的个数。
//如果 deleteCount 大于 start 之后的元素的总数,则从 start 后面的元素都将被删除(含第 start 位)。
//如果 deleteCount 被省略了,或者它的值大于等于array.length - start(也就是说,如果它大于或者等于start之后的所有元素的数量),那么start之后数组的所有元素都会被删除。
//如果 deleteCount 是 0 或者负数,则不移除元素。这种情况下,至少应添加一个新元素。

//item1, item2, ... 可选
//要添加进数组的元素,从start 位置开始。如果不指定,则 splice() 将只删除数组元素
var myFish = ["angel", "clown", "mandarin", "sturgeon"];
var removed = myFish.splice(2, 0, "drum");

// 运算后的 myFish: ["angel", "clown", "drum", "mandarin", "sturgeon"]
// 被删除的元素: [], 没有元素被删除
var myFish = ['angel', 'clown', 'drum', 'sturgeon'];
var removed = myFish.splice(2, 1, "trumpet");

// 运算后的 myFish: ["angel", "clown", "trumpet", "sturgeon"]
// 被删除的元素: ["drum"]

搜索和位置方法

严格相等

indexOf()

方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。

arr.indexOf(searchElement[, fromIndex])
//searchElement
//要查找的元素

//fromIndex 可选
//开始查找的位置。如果该索引值大于或等于数组长度,意味着不会在数组里查找,返回-1。如果参数中提供的索引值是一个负值,则将其作为数组末尾的一个抵消,即-1表示从最后一个元素开始查找,-2表示从倒数第二个元素开始查找 ,以此类推。 注意:如果参数中提供的索引值是一个负值,并不改变其查找顺序,查找顺序仍然是从前向后查询数组。如果抵消后的索引值仍小于0,则整个数组都将会被查询。其默认值为0.
var array = [2, 5, 9];
array.indexOf(2);     // 0
array.indexOf(7);     // -1
array.indexOf(9, 2);  // 2
array.indexOf(2, -1); // -1
array.indexOf(2, -3); // 0

lastIndexOf()

方法返回指定元素(也即有效的 JavaScript 值或变量)在数组中的最后一个的索引,如果不存在则返回 -1。从数组的后面向前查找,从 fromIndex 处开始。

arr.lastIndexOf(searchElement[, fromIndex])
//searchElement
//被查找的元素。

//fromIndex 可选
//从此位置开始逆向查找。默认为数组的长度减 1(arr.length - 1),即整个数组都被查找。如果该值大于或等于数组的长度,则整个数组会被查找。如果为负值,将其视为从数组末尾向前的偏移。即使该值为负,数组仍然会被从后向前查找。如果该值为负时,其绝对值大于数组长度,则方法返回 -1,即数组不会被查找
var array = [2, 5, 9, 2];
var index = array.lastIndexOf(2);
// index is 3
index = array.lastIndexOf(7);
// index is -1
index = array.lastIndexOf(2, 3);
// index is 3
index = array.lastIndexOf(2, 2);
// index is 0
index = array.lastIndexOf(2, -2);
// index is 0
index = array.lastIndexOf(2, -1);
// index is 3

includes()

ECMAScript 7新增

方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false。

arr.includes(valueToFind[, fromIndex])
//valueToFind
//需要查找的元素值。

//Note:  使用 includes()比较字符串和字符时是区分大小写。

//fromIndex 可选
//从fromIndex 索引处开始查找 valueToFind。如果为负值,则按升序从 array.length + fromIndex 的索引开始搜 (即使从末尾开始往前跳 fromIndex 的绝对值个索引,然后往后搜寻)。默认为 0。
[1, 2, 3].includes(2);     // true
[1, 2, 3].includes(4);     // false
[1, 2, 3].includes(3, 3);  // false
[1, 2, 3].includes(3, -1); // true
[1, 2, NaN].includes(NaN); // true

断言函数

find()

方法返回数组中满足提供的测试函数的第一个元素的值

arr.find(callback[, thisArg])
//callback
//在数组每一项上执行的函数,接收 3 个参数:
//element
//当前遍历到的元素。
//index可选
//当前遍历到的索引。
//array可选
//数组本身。

//thisArg可选
//执行回调时用作this 的对象。
var inventory = [
    {name: 'apples', quantity: 2},
    {name: 'bananas', quantity: 0},
    {name: 'cherries', quantity: 5}
];

function findCherries(fruit) {
    return fruit.name === 'cherries';
}

console.log(inventory.find(findCherries)); // { name: 'cherries', quantity: 5 }

findIndex

方法返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回-1。

arr.findIndex(callback[, thisArg])
//callback
针对数组中的每个元素, 都会执行该回调函数, 执行时会自动传入下面三个参数:
element
当前元素。
index
当前元素的索引。
array
调用findIndex的数组。

//thisArg
可选。执行callback时作为this对象的值.

迭代方法

every()

对数组中的每一项运行给定函数,如果该函数对每一项都返回 true,则返回 true。

var numbers = [1,2,3,4,5,4,3,2,1];
var everyResult = numbers.every(function(item, index, array){     return (item > 2);  });
alert(everyResult);    //false

filter()

对数组中的每一项运行给定函数,返回该函数会返回 true 的项组成的数组。

var numbers = [1,2,3,4,5,4,3,2,1];
var filterResult = numbers.filter(function(item, index, array){     return (item > 2); });
alert(filterResult);  //[3,4,5,4,3]

forEach()

对数组中的每一项运行给定函数。这个方法没有返回值。

var numbers = [1,2,3,4,5,4,3,2,1];
numbers.forEach(function(item, index, array){     //执行某些操作  });

map()

对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。

var numbers = [1,2,3,4,5,4,3,2,1];
var mapResult = numbers.map(function(item, index, array){     return item * 2; });
alert(mapResult);  //[2,4,6,8,10,8,6,4,2]

some()

对数组中的每一项运行给定函数,如果该函数对任一项返回 true,则返回 true

var someResult = numbers.some(function(item, index, array){     return (item > 2); });
alert(someResult);     //true

归并方法

reduce()

方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。

arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
//callback
执行数组中每个值 (如果没有提供 initialValue则第一个值除外)的函数,包含四个参数:
accumulator
累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或initialValue(见于下方)。
currentValue
数组中正在处理的元素。
index 可选
数组中正在处理的当前元素的索引。 如果提供了initialValue,则起始索引号为0,否则从索引1起始。
array可选
调用reduce()的数组

//initialValue可选
作为第一次调用 callback函数时的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错

执行过程

[0, 1, 2, 3, 4].reduce(function(accumulator, currentValue, currentIndex, array){
  return accumulator + currentValue;
});
callbackaccumulatorcurrentValuecurrentIndexarrayreturn value
first call011[0, 1, 2, 3, 4]1
second call122[0, 1, 2, 3, 4]3
third call333[0, 1, 2, 3, 4]6
fourth call644[0, 1, 2, 3, 4]10

reduceRight()

方法接受一个函数作为累加器(accumulator)和数组的每个值(从右到左)将其减少为单个值。

定型数组

定型数组(typed array)是ECMAScript 新增的结构,目的是提升向原生库传输数据的效率。是一种特殊的包含数值类型的数组

历史

在2006 年,Mozilla、Opera 等浏览器提供商就实验性地在浏览器中增加了用于渲染复杂图形应用程序的编程平台,无须安装任何插件。其目标是开发一套JavaScript API,从而充分利用3D 图形API 和GPU 加速,以便
在元素上渲染复杂的图形。

WebGL

最后的JavaScript API 是基于OpenGL ES(OpenGL for Embedded Systems)2.0 规范的。OpenGL ES
是OpenGL 专注于2D 和3D 计算机图形的子集。这个新API 被命名为WebGL(Web Graphics Library),
于2011 年发布1.0 版。有了它,开发者就能够编写涉及复杂图形的应用程序,它会被兼容WebGL 的浏
览器原生解释执行。
在WebGL 的早期版本中,因为JavaScript 数组与原生数组之间不匹配,所以出现了性能问题。图形
驱动程序API 通常不需要以JavaScript 默认双精度浮点格式传递给它们的数值,而这恰恰是JavaScript
数组在内存中的格式。因此,每次WebGL 与JavaScript 运行时之间传递数组时,WebGL 绑定都需要在
目标环境分配新数组,以其当前格式迭代数组,然后将数值转型为新数组中的适当格式,而这些要花费
很多时间。

定型数组

Mozilla 为解决这个问题而实现了CanvasFloatArray。这是一个提供JavaScript 接口的、C 语言风格的浮点值数组。JavaScript 运行时使用这个类型可以分配、读取和写入数组。这个数组可以直接传给底层图形驱动程序API

最终,CanvasFloatArray变成了Float32Array,也就是定型数组中可用的第一个“类型”

ArrayBuffer

Float32Array 实际上是一种“视图”,可以允许JavaScript 运行时访问一块名为ArrayBuffer 的预分配内存。ArrayBuffer 是所有定型数组及视图引用的基本单位

ArrayBuffer()是一个普通的JavaScript 构造函数,可用于在内存中分配特定数量的字节空间,ArrayBuffer 一经创建就不能再调整大小

const buf = new ArrayBuffer(16); // 在内存中分配16 字节
alert(buf.byteLength);

DataView

第一种允许你读写ArrayBuffer 的视图是DataView。这个视图专为文件I/O 和网络I/O 设计,其API 支持对缓冲数据的高度控制,但相比于其他类型的视图性能也差一些。DataView 对缓冲内容没有
任何预设,也不能迭代。

const buf = new ArrayBuffer(16);
// DataView 默认使用整个ArrayBuffer
const fullDataView = new DataView(buf);
alert(fullDataView.byteOffset); // 0
alert(fullDataView.byteLength); // 16
alert(fullDataView.buffer === buf); // true

定型数组

定型数组是另一种形式的ArrayBuffer 视图,设计定型数组的目的就是提高与WebGL 等原生库交换二进制数据的效率

Map

ECMAScript 6 的新增特性,键/值存储机制

使用new 关键字和Map 构造函数可以创建一个空映射:

const m1 = new Map([
["key1", "val1"],
["key2", "val2"],
["key3", "val3"]
]);

// 映射期待的键/值对,无论是否提供
const m3 = new Map([[]]);
alert(m3.has(undefined)); // true
alert(m3.get(undefined)); // undefined

基本API

set()

set方法设置键名key对应的键值为value,然后返回整个 Map 结构。如果key已经有值,则键值会被更新,否则就新生成该键。

const m = new Map();

m.set('edition', 6)        // 键是字符串
m.set(262, 'standard')     // 键是数值
m.set(undefined, 'nah')    // 键是 undefined

set方法返回的是当前的Map对象,因此可以采用链式写法

let map = new Map()
  .set(1, 'a')
  .set(2, 'b')
  .set(3, 'c');

get()

get方法读取key对应的键值,如果找不到key,返回undefined

const m = new Map();

const hello = function() {console.log('hello');};
m.set(hello, 'Hello ES6!') // 键是函数

m.get(hello)  // Hello ES6!

has()

has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。

const m = new Map();

m.set('edition', 6);
m.set(262, 'standard');
m.set(undefined, 'nah');

m.has('edition')     // true
m.has('years')       // false
m.has(262)           // true
m.has(undefined)     // true

delete()

delete方法删除某个键,返回true。如果删除失败,返回false

const m = new Map();
m.set(undefined, 'nah');
m.has(undefined)     // true

m.delete(undefined)
m.has(undefined)       // false

clear()

clear方法清除所有成员,没有返回值。

let map = new Map();
map.set('foo', true);
map.set('bar', false);

map.size // 2
map.clear()
map.size // 0

size

size属性返回 Map 结构的成员总数。

const map = new Map();
map.set('foo', true);
map.set('bar', false);

map.size // 2

顺序与迭代

keys()

返回键名的遍历器

const map = new Map([
  ['F', 'no'],
  ['T',  'yes'],
]);

for (let key of map.keys()) {
  console.log(key);
}
// "F"
// "T"

values()

返回键值的遍历器。

const map = new Map([
  ['F', 'no'],
  ['T',  'yes'],
]);
for (let value of map.values()) {
  console.log(value);
}
// "no"
// "yes"

entries()

返回所有成员的遍历器

const map = new Map([
  ['F', 'no'],
  ['T',  'yes'],
]);
for (let item of map.entries()) {
  console.log(item[0], item[1]);
}
// "F" "no"
// "T" "yes"

for (let [key, value] of map.entries()) {
  console.log(key, value);
}
// "F" "no"
// "T" "yes"

// 等同于使用map.entries()
for (let [key, value] of map) {
  console.log(key, value);
}
// "F" "no"
// "T" "yes"

forEach()

遍历 Map 的所有成员

相互转换

Map转为数组

const map = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
]);

[...map.keys()]
// [1, 2, 3]

[...map.values()]
// ['one', 'two', 'three']

[...map.entries()]
// [[1,'one'], [2, 'two'], [3, 'three']]

[...map]
// [[1,'one'], [2, 'two'], [3, 'three']]

数组转为Map

new Map([
  [true, 7],
  [{foo: 3}, ['abc']]
])
// Map {
//   true => 7,
//   Object {foo: 3} => ['abc']
// }

Map转为对象

function strMapToObj(strMap) {
  let obj = Object.create(null);
  for (let [k,v] of strMap) {
    obj[k] = v;
  }
  return obj;
}

对象转换为Map

let obj = {"a":1, "b":2};
let map = new Map(Object.entries(obj)

Object还是Map

  1. 内存占用
    Object 和Map 的工程级实现在不同浏览器间存在明显差异,但存储单个键/值对所占用的内存数量
    都会随键的数量线性增加。批量添加或删除键/值对则取决于各浏览器对该类型内存分配的工程实现。
    不同浏览器的情况不同,但给定固定大小的内存,Map 大约可以比Object 多存储50%的键/值对。
  2. 插入性能
    向Object 和Map 中插入新键/值对的消耗大致相当,不过插入Map 在所有浏览器中一般会稍微快
    一点儿。对这两个类型来说,插入速度并不会随着键/值对数量而线性增加。如果代码涉及大量插入操
    作,那么显然Map 的性能更佳。
  3. 查找速度
    与插入不同,从大型Object 和Map 中查找键/值对的性能差异极小,但如果只包含少量键/值对,
    则Object 有时候速度更快。在把Object 当成数组使用的情况下(比如使用连续整数作为属性),浏
    览器引擎可以进行优化,在内存中使用更高效的布局。这对Map 来说是不可能的。对这两个类型而言,
    查找速度不会随着键/值对数量增加而线性增加。如果代码涉及大量查找操作,那么某些情况下可能选
    择Object 更好一些。
  4. 删除性能
    使用delete 删除Object 属性的性能一直以来饱受诟病,目前在很多浏览器中仍然如此。为此,
    出现了一些伪删除对象属性的操作,包括把属性值设置为undefined 或null。但很多时候,这都是一
    种讨厌的或不适宜的折中。而对大多数浏览器引擎来说,Map 的delete()操作都比插入和查找更快。
    如果代码涉及大量删除操作,那么毫无疑问应该选择Map。

WeakMap

ECMAScript 6 新增的“弱映射”(WeakMap)是一种新的集合类型,为这门语言带来了增强的键/值对存储机制。WeakMap 是Map 的“兄弟”类型,其API 也是Map 的子集。WeakMap 中的“weak”(弱),描述的是JavaScript 垃圾回收程序对待“弱映射”中键的方式。

WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名

const map = new WeakMap();
map.set(1, 2)
// TypeError: 1 is not an object!
map.set(Symbol(), 2)
// TypeError: Invalid value used as weak map key
map.set(null, 2)
// TypeError: Invalid value used as weak map key

弱键

WeakMap 中“weak”表示弱映射的键是“弱弱地拿着”的。意思就是,这些键不属于正式的引用,不会阻止垃圾回收

只要键存在,键/值对就会存在于映射中,并被当作对值的引用,因此就不会被当作垃圾回收。

const wm = new WeakMap();
wm.set({}, "val");

set()方法初始化了一个新对象并将它用作一个字符串的键。因为没有指向这个对象的其他引用,
所以当这行代码执行完成后,这个对象键就会被当作垃圾回收。然后,这个键/值对就从弱映射中消失
了,使其成为一个空映射。在这个例子中,因为值也没有被引用,所以这对键/值被破坏以后,值本身
也会成为垃圾回收的目标。

不可迭代键

因为WeakMap 中的键/值对任何时候都可能被销毁,所以没必要提供迭代其键/值对的能力

使用弱映射

因为WeakMap 实例不会妨碍垃圾回收,所以非常适合保存关联元数据

const e1 = document.getElementById('foo');
const e2 = document.getElementById('bar');
const arr = [
  [e1, 'foo 元素'],
  [e2, 'bar 元素'],
];
// 不需要 e1 和 e2 的时候
// 必须手动删除引用
arr [0] = null;
arr [1] = null;

一旦忘了写,就会造成内存泄露

const m = new Map();
const loginButton = document.querySelector('#login');
// 给这个节点关联一些元数据
m.set(loginButton, {disabled: true});

在上面的代码执行后,页面被JavaScript 改变了,原来的登录按钮从DOM 树中被删掉了。但由于映射中还保存着按钮的引用,所以对应的DOM 节点仍然会逗留在内存中,除非明确将其从映射中删除或者等到映射本身被销毁。一旦消除对该节点的引用,它占用的内存就会被垃圾回收机制释放。Weakmap 保存的这个键值对,也会自动消失。

Set

类似于数组,但是成员的值都是唯一的,没有重复的值。

const s = new Set();

[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));

for (let i of s) {
  console.log(i);
}
// 2 3 5 4

基本API

size

  • 返回Set实例的成员总数。

add()

添加某个值,返回 Set 结构本身

delete()

删除某个值,返回一个布尔值,表示删除是否成功

has()

返回一个布尔值,表示该值是否为Set的成员。

clear()

清除所有成员,没有返回值。

顺序与迭代

keys()

返回键名的遍历器

let set = new Set(['red', 'green', 'blue']);

for (let item of set.keys()) {
  console.log(item);
}
// red
// green
// blue

values()

返回键值的遍历器

let set = new Set(['red', 'green', 'blue']);
for (let item of set.values()) {
  console.log(item);
}
// red
// green
// blue

entries()

返回键值对的遍历器

let set = new Set(['red', 'green', 'blue']);
for (let item of set.entries()) {
  console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]

forEach()

WeakSet

WeakSet 结构与 Set 类似,也是不重复的值的集合.WeakSet 的成员只能是对象,而不能是其他类型的值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值