现代JavaScript 教程( 数据类型)总结

原始类型方法

在JavaScript中:

  1. 原始类型仍然是原始的。与预期相同,提供单个值
  2. JavaScript 允许访问字符串,数字,布尔值和 symbol 的方法和属性。
  3. 为了使它们起作用,创建了提供额外功能的特殊“对象包装器”,使用后即被销毁。

“对象包装器”对于每种原始类型都是不同的,它们被称为 StringNumberBooleanSymbol。它们提供了不同的方法。

例如,字符串方法 str.toUpperCase() 返回一个大写化处理的字符串。

使用时:

  1. 字符串 str 是一个原始值。因此,在访问其属性时,会创建一个包含字符串字面值的特殊对象,并且具有有用的方法,例如 toUpperCase()
  2. 该方法运行并返回一个新的字符串(由 alert 显示)。
  3. 特殊对象被销毁,只留下原始值 str

数字类型

要写有很多零的数字:

  • "e" 和 0 的数量附加到数字后。就像:123e6123 后面接 6 个 0 相同。
  • "e" 后面的负数将使数字除以 1 后面接着给定数量的零的数字。例如 123e-6 表示 0.000123123 的百万分之一)。

对于不同的数字系统:

  • 可以直接在十六进制(0x),八进制(0o)和二进制(0b)系统中写入数字。
  • parseInt(str,base) 将字符串 str 解析为在给定的 base 数字系统中的整数,2 ≤ base ≤ 36
  • num.toString(base) 将数字转换为在给定的 base 数字系统中的字符串。

要将 12pt100px 之类的值转换为数字:

  • 使用 parseInt/parseFloat 进行“软”转换,它从字符串中读取数字,然后返回在发生 error 前可以读取到的值。

小数:

  • 使用 Math.floorMath.ceilMath.truncMath.roundnum.toFixed(precision) 进行舍入。
  • 请确保记住使用小数时会损失精度。

测试:isFinite 和 isNaN:

  • isNaN(value) 将其参数转换为数字,然后测试它是否为 NaN

  • isFinite(value) 将其参数转换为数字,如果是常规数字,则返回 true,而不是 NaN/Infinity/-Infinity

    • 注意,在所有数字函数中,包括 isFinite,空字符串或仅有空格的字符串均被视为 0

更多数学函数:

  • 需要时请查看 Math 对象。这个库很小,但是可以满足基本的需求。

字符串

  • 有 3 种类型的引号。反引号允许字符串跨越多行并可以使用 ${…} 在字符串中嵌入表达式。
  • JavaScript 中的字符串使用的是 UTF-16 编码。
  • 我们可以使用像 \n 这样的特殊字符或通过使用 \u... 来操作它们的 unicode 进行字符插入。
  • 获取字符时,使用 []
  • 获取子字符串,使用 slicesubstringsubstr
  • 字符串的大/小写转换,使用:toLowerCase/toUpperCase
  • 查找子字符串时,使用 indexOfincludes/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 的第一个值/所有值。
    • findIndexfind 类似,但返回索引而不是值。
  • 遍历元素:
    • forEach(func) —— 对每个元素都调用 func,不返回任何内容。
  • 转换数组:
    • map(func) —— 根据对每个元素调用 func 的结果创建一个新数组。
    • sort(func) —— 对数组进行原位(in-place)排序,然后返回它。
    • reverse() —— 原位(in-place)反转数组,然后返回它。
    • split/join —— 将字符串转换为数组并返回。
    • reduce/reduceRight(func, initial) —— 通过对每个元素调用 func 计算数组上的单个值,并在调用之间传递中间结果。
  • 其他:
    • Array.isArray(arr) 检查 arr 是否是一个数组。

请注意,sortreversesplice 方法修改的是数组本身。

这些是最常用的方法,它们覆盖 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) —— 从索引 startend,用重复的 value 填充数组。

  • arr.copyWithin(target, start, end) —— 将从位置 startend 的所有元素复制到 自身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

MapSet 中迭代总是按照值插入的顺序进行的,所以我们不能说这些集合是无序的,但是我们不能对元素进行重新排序,也不能直接按其编号来获取元素。

WeakMap and WeakSet(弱映射和弱集合)

WeakMap 是类似于 Map 的集合,它仅允许对象作为键,并且一旦通过其他方式无法访问它们,便会将它们与其关联值一同删除。

WeakSet 是类似于 Set 的集合,它仅存储对象,并且一旦通过其他方式无法访问它们,便会将其删除。

它们都不支持引用所有键或其计数的方法和属性。仅允许单个操作。

WeakMapWeakSet 被用作“主要”对象存储之外的“辅助”数据结构。一旦将对象从主存储器中删除,如果该对象仅被用作 WeakMapWeakSet 的键,那么它将被自动清除。

Object.keys,values,entries

对于普通对象,下列这些方法是可用的:

……但是请注意区别(比如说跟 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),它会返回 所有 键。

转换对象

对象缺少数组存在的许多方法,例如 mapfilter 等。

如果我们想应用它们,那么我们可以使用 Object.entries,然后使用 Object.fromEntries

  1. 使用 Object.entries(obj)obj 获取由键/值对组成的数组。
  2. 对该数组使用数组方法,例如 map
  3. 对结果数组使用 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 调用。

原文地址:数据类型

posted @ 2021-10-31 12:24  xloading  阅读(130)  评论(0)    收藏  举报