整理一些平时容易忽略的 JavaScript 数组方法

2022-09-15 03:35:27

Array.of

不论参数的数量和类型,都会将其作为数组的元素创建一个新数组。这比直接使用 new Array() 更直观,因为 new Array(3) 会创建一个长度为 3 的空数组,而不是包含数字 3 的数组。

const arr = Array.of(3) // [3]
const arr2 = Array.of(1, 2, 3) // [1, 2, 3]
const arr3 = Array.from({ length: 3 }) // [empty × 3] ⚠️ 不是 [3]

Array.copyWithin

将数组中指定位置的一组元素复制到数组的另一位置, 原数组会被修改, 返回修改后的原数组

arr.copyWithin(target, start, end)
// target: 从这里开始覆盖(目标索引)
// start:  从什么位置开始复制元素(源起始索引),默认 0
// end:    复制到哪里结束(源结束索引,不包含),默认数组长度

Example

const arr = [1, 2, 3, 4, 5]
arr.copyWithin(1)

// 从索引 1 的位置开始覆盖
// 从索引 0 开始复制到末尾 -> [1, 2, 3, 4, 5]
// 原数组变为: [1, 1, 2, 3, 4]

arr.copyWithin(2, 0, 2)

// 从索引 2 的位置开始覆盖
// 从索引 0 开始复制,到索引 2 结束(不包含)-> [1, 2]
// 原数组变为: [1, 2, 1, 2, 5]

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

// 从索引 0 的位置开始覆盖
// 从索引 3 开始复制到末尾 -> [4, 5]
// 原数组变为: [4, 5, 3, 4, 5]

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

// 负数索引:-1 是最后一位,-2 是倒数第二位
// 从倒数第二位(索引 3)开始覆盖
// 从倒数第三位(索引 2)开始复制,到倒数第一位(索引 4)结束(不包含)-> [3, 4]
// 原数组变为: [1, 2, 3, 3, 4]

ArrayBuffer

ArrayBuffer 提供了操作内存的能力, 表示通用的原始二进制的数据缓冲

不能直接操作 ArrayBuffer 的内容, 而是要通过类型化数组对象 || DataView 对象操作

Reference: ArrayBuffer - JavaScript | MDN

基础

const buffer = new ArrayBuffer(19) // 创建一个 10 字节的内存空间
buffer.byteLength // 获取字节数
const buffer2 = buffer.slice(2, 4) // 拿到新的 ArrayBuffer

读取

要读取 ArrayBuffer 的数据,需要对应的视图对象实现

  • DataView: 非常灵活的读取方式, 能控制字节序
  • **TypedArray: 提供了不同数据类型的独特视图 ** TypedArray
/**
 * DataView(buffer, byteOffset,byteLength)
 *                     偏移量   操作的长度
 */
const buffer = new ArrayBuffer(10)
const view = new DataView(buffer)
view.setInt8(4, 3)
console.log(view.getInt8())

/**
 *
 */
const arr1 = new Int8Array(buffer)
const arr2 = new Int16Array(buffer)
console.log(arr1 === arr2)
console.log(arr1.buffer === arr2.buffer) // 内存的操作空间是一样的

Example

因为操作的是二进制数据,所以像 file audio 等处理起来拿心应手。那就来处理图片吧

<img id="img" src="./1.png" alt="">


<canvas id="canvas"></canvas>
<script>
    window.addEventListener('load', () => {
        const canvas = document.getElementById('canvas')
        const img = document.getElementById('img')
        const ctx = canvas.getContext('2d')

        ctx.drawImage(img, 0, 0, img.width, img.height)

        const imgData = ctx.getImageData(0, 0, img.width, img.height) // 获取画布上从左上角到图片宽高区域的像素数据

        const data = imgData.data
        /**
         * 画布是由多个像素点组成的, 每个像素点有四个数据: rgba(红,绿, 蓝,透明度)
         * 所以需要将图像的每个像素点设置为 rgb 的平均值
         */

        for (let i = 0; i < data.length; i += 4) {
            const r = data[i]
            const g = data[i + 1]
            const b = data[i + 2]

            // 标准灰度公式:Y = 0.299*R + 0.587*G + 0.114*B
            const gray = 0.299 * r + 0.587 * g + 0.114 * b

            data[i] = gray
            data[i + 1] = gray
            data[i + 2] = gray
        }
        // 重新绘制到画布
        ctx.putImageData(imgData, 0, 0)
    })
</script>