现代JavaScript 教程( 数据类型)总结
原始类型方法
在JavaScript中:
- 原始类型仍然是原始的。与预期相同,提供单个值
- JavaScript 允许访问字符串,数字,布尔值和 symbol 的方法和属性。
- 为了使它们起作用,创建了提供额外功能的特殊“对象包装器”,使用后即被销毁。
“对象包装器”对于每种原始类型都是不同的,它们被称为 String、Number、Boolean 和 Symbol。它们提供了不同的方法。
例如,字符串方法 str.toUpperCase() 返回一个大写化处理的字符串。
使用时:
- 字符串
str是一个原始值。因此,在访问其属性时,会创建一个包含字符串字面值的特殊对象,并且具有有用的方法,例如toUpperCase()。 - 该方法运行并返回一个新的字符串(由
alert显示)。 - 特殊对象被销毁,只留下原始值
str。
数字类型
要写有很多零的数字:
- 将
"e"和 0 的数量附加到数字后。就像:123e6与123后面接 6 个 0 相同。 "e"后面的负数将使数字除以 1 后面接着给定数量的零的数字。例如123e-6表示0.000123(123的百万分之一)。
对于不同的数字系统:
- 可以直接在十六进制(
0x),八进制(0o)和二进制(0b)系统中写入数字。 parseInt(str,base)将字符串str解析为在给定的base数字系统中的整数,2 ≤ base ≤ 36。num.toString(base)将数字转换为在给定的base数字系统中的字符串。
要将 12pt 和 100px 之类的值转换为数字:
- 使用
parseInt/parseFloat进行“软”转换,它从字符串中读取数字,然后返回在发生 error 前可以读取到的值。
小数:
- 使用
Math.floor,Math.ceil,Math.trunc,Math.round或num.toFixed(precision)进行舍入。 - 请确保记住使用小数时会损失精度。
测试:isFinite 和 isNaN:
-
isNaN(value)将其参数转换为数字,然后测试它是否为NaN -
isFinite(value)将其参数转换为数字,如果是常规数字,则返回true,而不是NaN/Infinity/-Infinity- 注意,在所有数字函数中,包括
isFinite,空字符串或仅有空格的字符串均被视为0。
- 注意,在所有数字函数中,包括
更多数学函数:
- 需要时请查看 Math 对象。这个库很小,但是可以满足基本的需求。
字符串
- 有 3 种类型的引号。反引号允许字符串跨越多行并可以使用
${…}在字符串中嵌入表达式。 - JavaScript 中的字符串使用的是 UTF-16 编码。
- 我们可以使用像
\n这样的特殊字符或通过使用\u...来操作它们的 unicode 进行字符插入。 - 获取字符时,使用
[]。 - 获取子字符串,使用
slice或substring或substr。 - 字符串的大/小写转换,使用:
toLowerCase/toUpperCase。 - 查找子字符串时,使用
indexOf或includes/startsWith/endsWith进行简单检查。 - 根据语言比较字符串时使用
localeCompare,否则将按字符代码进行比较。
还有其他几种有用的字符串方法:
str.trim()—— 删除字符串前后的空格 (“trims”)。str.repeat(n)—— 重复字符串n次。- ……更多内容细节请参见 手册。
数组
数组是一种特殊的对象,适用于存储和管理有序的数据项。
-
声明:
// 方括号 (常见用法) let arr = [item1, item2...]; // new Array (极其少见) let arr = new Array(item1, item2...);调用
new Array(number)会创建一个给定长度的数组,但不含有任何项。 -
length属性是数组的长度,准确地说,它是数组最后一个数字索引值加一。它由数组方法自动调整。 -
如果我们手动缩短
length,那么数组就会被截断。
我们可以通过下列操作以双端队列的方式使用数组:
push(...items)在末端添加items项。pop()从末端移除并返回该元素。shift()从首端移除并返回该元素。unshift(...items)从首端添加items项。
遍历数组的元素:
for (let i=0; i<arr.length; i++)— 运行得最快,可兼容旧版本浏览器。for (let item of arr)— 现代语法,只能访问 items。for (let i in arr)— 永远不要用这个(for..in会遍历所有属性,不仅仅是数字属性,且速度慢)。
比较数组时,不要使用 == 运算符(当然也不要使用 > 和 < 等运算符),因为它们不会对数组进行特殊处理。它们通常会像处理任意对象那样处理数组,这通常不是我们想要的。
但是,我们可以使用 for..of 循环来逐项比较数组。
数组方法
数组方法备忘单:
- 添加/删除元素:
push(...items)—— 向尾端添加元素,pop()—— 从尾端提取一个元素,shift()—— 从首端提取一个元素,unshift(...items)—— 向首端添加元素,splice(pos, deleteCount, ...items)—— 从pos开始删除deleteCount个元素,并插入items。slice(start, end)—— 创建一个新数组,将从索引start到索引end(但不包括end)的元素复制进去。concat(...items)—— 返回一个新数组:复制当前数组的所有元素,并向其中添加items。如果items中的任意一项是一个数组,那么就取其元素。
- 搜索元素:
indexOf/lastIndexOf(item, pos)—— 从索引pos开始搜索item,搜索到则返回该项的索引,否则返回-1。includes(value)—— 如果数组有value,则返回true,否则返回false。find/filter(func)—— 通过func过滤元素,返回使func返回true的第一个值/所有值。findIndex和find类似,但返回索引而不是值。
- 遍历元素:
forEach(func)—— 对每个元素都调用func,不返回任何内容。
- 转换数组:
map(func)—— 根据对每个元素调用func的结果创建一个新数组。sort(func)—— 对数组进行原位(in-place)排序,然后返回它。reverse()—— 原位(in-place)反转数组,然后返回它。split/join—— 将字符串转换为数组并返回。reduce/reduceRight(func, initial)—— 通过对每个元素调用func计算数组上的单个值,并在调用之间传递中间结果。
- 其他:
Array.isArray(arr)检查arr是否是一个数组。
请注意,sort,reverse 和 splice 方法修改的是数组本身。
这些是最常用的方法,它们覆盖 99% 的用例。但是还有其他几个:
-
arr.some(fn)/arr.every(fn) 检查数组。
与
map类似,对数组的每个元素调用函数fn。如果任何/所有结果为true,则返回true,否则返回false。这两个方法的行为类似于
||和&&运算符:如果fn返回一个真值,arr.some()立即返回true并停止迭代其余数组项;如果fn返回一个假值,arr.every()立即返回false并停止对其余数组项的迭代。我们可以使用
every来比较数组:function arraysEqual(arr1, arr2) { return arr1.length === arr2.length && arr1.every((value, index) => value === arr2[index]); } alert( arraysEqual([1, 2], [1, 2])); // true -
arr.fill(value, start, end) —— 从索引
start到end,用重复的value填充数组。 -
arr.copyWithin(target, start, end) —— 将从位置
start到end的所有元素复制到 自身 的target位置(覆盖现有元素)。 -
arr.flat(depth)/arr.flatMap(fn) 从多维数组创建一个新的扁平数组。
-
[Array.of(element0, element1[, …[, elementN]]]) 基于可变数量的参数创建一个新的
Array实例,而不需要考虑参数的数量或类型。
有关完整列表,请参阅 手册。
Iterable object(可迭代对象)
可以应用 for..of 的对象被称为 可迭代的。
- 技术上来说,可迭代对象必须实现
Symbol.iterator方法。obj[Symbol.iterator]()的结果被称为 迭代器(iterator)。由它处理进一步的迭代过程。- 一个迭代器必须有
next()方法,它返回一个{done: Boolean, value: any}对象,这里done:true表明迭代结束,否则value就是下一个值。
Symbol.iterator方法会被for..of自动调用,但我们也可以直接调用它。- 内置的可迭代对象例如字符串和数组,都实现了
Symbol.iterator。 - 字符串迭代器能够识别代理对(surrogate pair)。(译注:代理对也就是 UTF-16 扩展字符。)
有索引属性和 length 属性的对象被称为 类数组对象。这种对象可能还具有其他属性和方法,但是没有数组的内建方法。
如果我们仔细研究一下规范 —— 就会发现大多数内建方法都假设它们需要处理的是可迭代对象或者类数组对象,而不是“真正的”数组,因为这样抽象度更高。
Array.from(obj[, mapFn, thisArg]) 将可迭代对象或类数组对象 obj 转化为真正的数组 Array,然后我们就可以对它应用数组的方法。可选参数 mapFn (可以是一个函数,该函数会在对象中的元素被添加到数组前,被应用于每个元素)和 thisArg 允许我们将函数应用到每个元素。
Map and Set(映射和集合)
Map 是一个带键的数据项的集合,就像一个 Object 一样。 但是它们最大的差别是 Map 允许任何类型的键(key)。
方法和属性如下:
new Map([iterable])—— 创建 map,可选择带有[key,value]对的iterable(例如数组)来进行初始化。map.set(key, value)—— 根据键存储值。每一次map.set调用都会返回 map 本身,所以我们可以进行“链式”调用。map.get(key)—— 根据键来返回值,如果map中不存在对应的key,则返回undefined。map.has(key)—— 如果key存在则返回true,否则返回false。map.delete(key)—— 删除指定键的值。map.clear()—— 清空 map 。map.size—— 返回当前元素个数。- 如果要在
map里使用循环,可以使用以下三个方法:map.keys()—— 遍历并返回所有的键(returns an iterable for keys),map.values()—— 遍历并返回所有的值(returns an iterable for values),map.entries()—— 遍历并返回所有的实体(returns an iterable for entries)[key, value],for..of在默认情况下使用的就是这个。- map迭代顺序和插入值的顺序相同
map.forEach((value, key, map)=>{})——类似Array- 从一个已有的普通对象(plain object)来创建一个
Map,那么我们可以使用内建方法 Object.entries(obj),该方法返回对象的键/值对数组,该数组格式完全按照Map所需的格式。 Object.fromEntries方法的作用是相反的:给定一个具有[key, value]键值对的可迭代对象,它会根据给定参数创建一个对象
与普通对象 Object 的不同点:
- 任何键、对象都可以作为键。
- 有其他的便捷方法,如
size属性。
Set —— 是一组唯一值的集合。
方法和属性:
new Set([iterable])—— 创建 set,可选择带有iterable(例如数组)来进行初始化。set.add(value)—— 添加一个值(如果value存在则不做任何修改),返回 set 本身。set.delete(value)—— 删除值,如果value在这个方法调用的时候存在则返回true,否则返回false。set.has(value)—— 如果value在 set 中,返回true,否则返回false。set.clear()—— 清空 set。set.size—— 元素的个数。- set迭代的函数和map相同,参数不变,参数
key都换成value
在 Map 和 Set 中迭代总是按照值插入的顺序进行的,所以我们不能说这些集合是无序的,但是我们不能对元素进行重新排序,也不能直接按其编号来获取元素。
WeakMap and WeakSet(弱映射和弱集合)
WeakMap 是类似于 Map 的集合,它仅允许对象作为键,并且一旦通过其他方式无法访问它们,便会将它们与其关联值一同删除。
WeakSet 是类似于 Set 的集合,它仅存储对象,并且一旦通过其他方式无法访问它们,便会将其删除。
它们都不支持引用所有键或其计数的方法和属性。仅允许单个操作。
WeakMap 和 WeakSet 被用作“主要”对象存储之外的“辅助”数据结构。一旦将对象从主存储器中删除,如果该对象仅被用作 WeakMap 或 WeakSet 的键,那么它将被自动清除。
Object.keys,values,entries
对于普通对象,下列这些方法是可用的:
- Object.keys(obj) —— 返回一个包含该对象所有的键的数组。
- Object.values(obj) —— 返回一个包含该对象所有的值的数组。
- Object.entries(obj) —— 返回一个包含该对象所有 [key, value] 键值对的数组。
……但是请注意区别(比如说跟 map 的区别):
| Map | Object | |
|---|---|---|
| 调用语法 | map.keys() |
Object.keys(obj),而不是 obj.keys() |
| 返回值 | 可迭代项 | “真正的”数组 |
⚠Object.keys/values/entries 会忽略 symbol 属性
就像
for..in循环一样,这些方法会忽略使用Symbol(...)作为键的属性。通常这很方便。但是,如果我们也想要 Symbol 类型的键,那么这儿有一个单独的方法 Object.getOwnPropertySymbols,它会返回一个只包含 Symbol 类型的键的数组。另外,还有一种方法 Reflect.ownKeys(obj),它会返回 所有 键。
转换对象
对象缺少数组存在的许多方法,例如 map 和 filter 等。
如果我们想应用它们,那么我们可以使用 Object.entries,然后使用 Object.fromEntries:
- 使用
Object.entries(obj)从obj获取由键/值对组成的数组。 - 对该数组使用数组方法,例如
map。 - 对结果数组使用
Object.fromEntries(array)方法,将结果转回成对象。
解构赋值
-
解构赋值可以立即将一个对象或数组映射到多个变量上。
-
解构对象的完整语法:
let {prop : varName = default, ...rest} = object这表示属性
prop会被赋值给变量varName,如果没有这个属性的话,就会使用默认值default。没有对应映射的对象属性会被复制到
rest对象。 -
解构数组的完整语法:
let [item1 = default, item2, ...rest] = array数组的第一个元素被赋值给
item1,第二个元素被赋值给item2,剩下的所有元素被复制到另一个数组rest。 -
从嵌套数组/对象中提取数据也是可以的,此时等号左侧必须和等号右侧有相同的结构。
日期和时间
- 在 JavaScript 中,日期和时间使用 Date 对象来表示。我们不能只创建日期,或者只创建时间,
Date对象总是同时创建两者。 - 月份从 0 开始计数(对,一月是 0)。
- 一周中的某一天
getDay()同样从 0 开始计算(0 代表星期日)。 - 当设置了超出范围的组件时,
Date会进行自我校准。这一点对于日/月/小时的加减很有用。 - 日期可以相减,得到的是以毫秒表示的两者的差值。因为当
Date被转换为数字时,Date对象会被转换为时间戳。 - 使用
Date.now()可以更快地获取当前时间的时间戳。
JSON方法,toJSON
- JSON 是一种数据格式,具有自己的独立标准和大多数编程语言的库。
- JSON 支持 object,array,string,number,boolean 和
null。 - JavaScript 提供序列化(serialize)成 JSON 的方法 JSON.stringify 和解析 JSON 的方法 JSON.parse。
- 这两种方法都支持用于智能读/写的转换函数。
- 如果一个对象具有
toJSON,那么它会被JSON.stringify调用。
原文地址:数据类型

浙公网安备 33010602011771号