Javascript数组研究07_手写实现_[Symbol.iterator]_toLocaleString_toReversed_toSorted_toSpliced

31 Array@@iterator

31.1 基本介绍

@@iterator 方法(通过 array[Symbol.iterator] 访问)返回一个新的数组迭代器对象,该对象包含数组中每个索引的值。

array[Symbol.iterator]()

输入参数:无。

输出:一个新的迭代器对象,可用于遍历数组的元素。

注意事项

  • 该迭代器遵循迭代器协议,具有 next() 方法。
  • 每次调用 next() 方法会返回一个包含 valuedone 属性的对象。
    • value:当前迭代的数组元素的值。
    • done:布尔值,表示迭代是否完成。
  • 该方法是通用的,可用于类数组对象。
  • 方法返回值和Array.prototype.values一致
31.2 手写实现
MyArray.prototype[Symbol.iterator] = function() {
    let index = 0;
    let array = this;
    return {
    	// 返回对象包含next方法
        next: function() {
            if (index < array.length) {
                let value = array[index];
                index++;
                // next()返回值有value和done属性
                return { value: value, done: false };
            } else {
                return { value: undefined, done: true };
            }
        },
        // 实现迭代器协议,返回自身(也是迭代器)
        [Symbol.iterator]: function() { return this; }
    };
};

// 测试用例
let arr = new MyArray(1, 2, 3);
for (let item of arr) {
    console.log(item); // 输出 1, 2, 3
}

let iterator = arr[Symbol.iterator]();
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

难点总结

  • 实现迭代器协议:需要提供 next() 方法和 [Symbol.iterator]() 方法,使迭代器本身可迭代。
  • 正确处理索引:需要跟踪当前索引,确保遍历完整个数组。
  • 处理稀疏数组:迭代器会遍历所有索引,包括空槽,空槽的值为 undefined

32 Array.toLocaleString()

32.1 基本介绍

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

array.toLocaleString()

输入参数:无。

输出:一个字符串,表示数组的元素。

注意事项

  • 该方法不会修改原数组,是一个复制方法
  • 对于每个元素,调用其 toLocaleString 方法。如果元素为 nullundefined,则转换为空字符串。
  • 使用的分隔符是特定于语言环境的。
  • 争对稀疏数组,空槽的行为和undefined一致
32.2 手写实现
MyArray.prototype.toLocaleString = function() {
    let result = '';
    let separator = ','; // 分隔符,实际应根据本地化设置,这里简化处理

    for (let i = 0; i < this.length; i++) {
        if (i > 0) result += separator;

        let element = this[i];
        if (element == null) { // null 或 undefined
            result += '';
        } else if (typeof element.toLocaleString === 'function') {
            result += element.toLocaleString();
        } else {
            result += element.toString();
        }
    }
    return result;
};

// 测试用例
let date = new Date('2020-01-01');
let arr = new MyArray(1234.567, date, 'Hello', null, undefined);
console.log(arr.toLocaleString());
// 输出示例:"1,234.567,1/1/2020, 12:00:00 AM,Hello,,"

难点总结

  • 处理不同类型的元素:需要调用元素的 toLocaleString 方法,处理数字、日期、字符串等类型。
  • 处理 nullundefined:应转换为空字符串。
  • 分隔符:分隔符应根据语言环境确定,简化情况下使用逗号。

33 Array.toReversed()

33.1 基本介绍

toReversed()方法是 reverse() 方法对应的复制版本。它返回一个元素顺序相反的新数组。

array.toReversed()

输入参数:无。

输出:一个新的数组,元素顺序与原数组相反。

注意事项

  • 该方法不会修改原数组,是一个复制方法
  • 返回的新数组是原数组的浅拷贝。
  • 对于稀疏数组,空槽的处理和reverse方法不一致,在该函数空槽将被视为undefined
33.2 手写实现
MyArray.prototype.toReversed = function() {
    let length = this.length >>> 0;
    let result = new MyArray();
    result.length = length;

    for (let i = 0; i < length; i++) {
    	// 直接赋值,空槽将被处理为undefined
        result[i] = this[length - 1 - i];
    }

    return result;
};

// 测试用例
let arr = new MyArray(1, 2, 3);
let reversedArr = arr.toReversed();
console.log(reversedArr); // [3, 2, 1]
console.log(arr); // [1, 2, 3]

let sparseArr = new MyArray();
sparseArr[1] = 'a';
sparseArr[3] = 'b';
let reversedSparseArr = sparseArr.toReversed();
console.log(reversedSparseArr); // ['b', undefined, 'a', empty]

难点总结

  • 创建新数组:需要正确设置新数组的长度。
  • 处理稀疏数组:和reverse不同,空槽将会被看作undefined
  • 不修改原数组:必须确保原数组未被修改。

34 Array.toSorted()

34.1 基本介绍

toSorted() 方法是 sort() 方法的复制方法版本。它返回一个新数组,其元素按升序排列。

array.toSorted(compareFunction)

输入参数

  • compareFunction(a, b)(可选):用于定义排序顺序的函数。

输出:一个新的已排序数组。

注意事项

  • 该方法不会修改原数组,是一个复制方法
  • 排序行为与 sort() 方法相同。
  • 对于稀疏数组,空槽处理行为和sort不一致,将会被视为undefined
34.2 手写实现
MyArray.prototype.toSorted = function(compareFunction) {
    let length = this.length >>> 0;
    let elements = [];
    let holesCount = 0;

    // 将所有元素(包括空槽视为 undefined)收集到 elements 数组中
    for (let i = 0; i < length; i++) {
        if (i in this) {
            let value = this[i];
            elements.push(value);
        } else {
            // 空槽视为 undefined
            elements.push(undefined);
        }
    }

    if (typeof compareFunction !== 'function') {
        compareFunction = function(a, b) {
            // 将 undefined 元素排序到末尾
            if (a === undefined && b === undefined) return 0;
            if (a === undefined) return 1;
            if (b === undefined) return -1;

            let strA = String(a);
            let strB = String(b);
            if (strA < strB) return -1;
            if (strA > strB) return 1;
            return 0;
        };
    } else {
        // 包装用户提供的 compareFunction,确保 undefined 被排序到末尾
        const originalCompareFunction = compareFunction;
        compareFunction = function(a, b) {
            if (a === undefined && b === undefined) return 0;
            if (a === undefined) return 1;
            if (b === undefined) return -1;
            return originalCompareFunction(a, b);
        };
    }

    // 使用排序算法(这里使用快速排序)
    function quickSort(arr, left, right) {
        if (left >= right) return;
        let pivotIndex = partition(arr, left, right);
        quickSort(arr, left, pivotIndex - 1);
        quickSort(arr, pivotIndex + 1, right);
    }

    function partition(arr, left, right) {
        let pivot = arr[right];
        let i = left - 1;
        for (let j = left; j < right; j++) {
            if (compareFunction(arr[j], pivot) <= 0) {
                i++;
                [arr[i], arr[j]] = [arr[j], arr[i]];
            }
        }
        [arr[i + 1], arr[right]] = [arr[right], arr[i + 1]];
        return i + 1;
    }

    quickSort(elements, 0, elements.length - 1);

    // 构建结果数组
    let result = new MyArray();
    for (let i = 0; i < elements.length; i++) {
        result[i] = elements[i];
    }
    result.length = elements.length;

    return result;
};


// 测试用例 1
let arr = new MyArray(3, 1, 4, 1, 5, 9);
let sortedArr = arr.toSorted();
console.log(sortedArr); // [1, 1, 3, 4, 5, 9]
console.log(arr);       // [3, 1, 4, 1, 5, 9]

// 测试用例 2:含有空槽和 undefined
let sparseArr = new MyArray();
sparseArr[2] = 'c';
sparseArr[5] = 'a';
sparseArr[7] = undefined;
sparseArr[9] = 'b';
let sortedSparseArr = sparseArr.toSorted();
console.log(sortedSparseArr); // ['a', 'b', 'c', undefined, undefined, undefined, undefined, undefined, undefined, undefined]
console.log(sparseArr);       // [empty × 2, 'c', empty × 2, 'a', empty, undefined, empty, 'b']

// 测试用例 3:自定义比较函数
let arr2 = new MyArray('banana', undefined, 'apple', , 'cherry');
let sortedArr2 = arr2.toSorted((a, b) => a.localeCompare(b));
console.log(sortedArr2); // ['apple', 'banana', 'cherry', undefined, undefined]
console.log(arr2);       // ['banana', undefined, 'apple', empty, 'cherry']

// 测试用例 4:全是空槽的数组
let arr3 = new MyArray(5);
let sortedArr3 = arr3.toSorted();
console.log(sortedArr3); // [undefined, undefined, undefined, undefined, undefined]

难点总结

  • 将空槽视为 undefined:在遍历数组时,如果索引不存在(空槽),将其视为 undefined 并添加到 elements 数组中。。
  • 排序时将 undefined 排到末尾:在比较函数中,明确规定 undefined 应排在末尾。
  • 处理用户自定义的 compareFunction:当用户提供比较函数时,需要包装一下,确保 undefined 被正确处理。
  • 创建新数组:构建结果数组时,按照排序后的 elements 数组逐个赋值,确保长度和索引正确。

35 Array.toSpliced()

35.1 基本介绍

toSpliced() 方法返回一个数组的浅拷贝,其中从指定的开始索引删除或替换了指定数量的元素,并插入了新元素。该方法不会修改原数组。

array.toSpliced(start)
array.toSpliced(start, deleteCount)
array.toSpliced(start, deleteCount, item1, item2, ...)

输入参数

  • start:开始修改的索引位置。
  • deleteCount(可选):要删除的元素数量。
  • item1, item2, ...(可选):要插入的新元素。

输出:一个新的数组,包含修改后的元素。

注意事项

  • 该方法不会修改原数组,是一个复制方法
  • 行为类似于 splice() 方法,但返回的是新数组。
  • 对于稀疏数组,将会将空槽处理为undefined
35.2 手写实现
MyArray.prototype.toSpliced = function(start, deleteCount, ...items) {
    let length = this.length >>> 0;
    let result = new MyArray();
    let actualStart = start < 0
        ? Math.max(length + start, 0)
        : Math.min(start, length);
    let actualDeleteCount = deleteCount === undefined
        ? length - actualStart
        : Math.min(Math.max(Number(deleteCount), 0), length - actualStart);

    let k = 0;

    // Copy elements before actualStart, treating holes as undefined
    for (let i = 0; i < actualStart; i++, k++) {
        result[k] = this[i]; // Holes will be assigned undefined
    }

    // Insert new items
    for (let i = 0; i < items.length; i++, k++) {
        result[k] = items[i];
    }

    // Copy elements after the deleted section, treating holes as undefined
    for (let i = actualStart + actualDeleteCount; i < length; i++, k++) {
        result[k] = this[i]; // Holes will be assigned undefined
    }

    // Set the length of the new array
    result.length = k;

    return result;
};


// Test Case 1: Basic usage with holes treated as undefined
let arr = new MyArray(1, 2, 3, 4, 5);
let splicedArr = arr.toSpliced(2, 2, 'a', 'b');
console.log(splicedArr); // [1, 2, 'a', 'b', 5]
console.log(arr);        // [1, 2, 3, 4, 5]

// Test Case 2: Deleting elements without adding new ones
let arr2 = new MyArray(1, 2, 3);
let splicedArr2 = arr2.toSpliced(1);
console.log(splicedArr2); // [1]
console.log(arr2);        // [1, 2, 3]

// Test Case 3: Inserting into a sparse array (holes treated as undefined)
let sparseArr = new MyArray(1, , 3); // [1, <empty>, 3]
let splicedSparseArr = sparseArr.toSpliced(1, 0, 'a');
console.log(splicedSparseArr); // [1, 'a', undefined, 3]
console.log(sparseArr);        // [1, <empty>, 3]

// Test Case 4: Deleting from a sparse array (holes treated as undefined)
let splicedSparseArr2 = sparseArr.toSpliced(1, 2);
console.log(splicedSparseArr2); // [1]
console.log(sparseArr);         // [1, <empty>, 3]

// Test Case 5: Negative start index
let arr3 = new MyArray('x', 'y', 'z');
let splicedArr3 = arr3.toSpliced(-2, 1, 'a', 'b');
console.log(splicedArr3); // ['x', 'a', 'b', 'z']
console.log(arr3);        // ['x', 'y', 'z']

// Test Case 6: Deleting more elements than remain
let arr4 = new MyArray(1, 2, 3, 4);
let splicedArr4 = arr4.toSpliced(2, 10);
console.log(splicedArr4); // [1, 2]
console.log(arr4);        // [1, 2, 3, 4]

// Test Case 7: Deleting zero elements
let arr5 = new MyArray(1, 2, 3);
let splicedArr5 = arr5.toSpliced(1, 0, 'a', 'b');
console.log(splicedArr5); // [1, 'a', 'b', 2, 3]
console.log(arr5);        // [1, 2, 3]

难点总结

  • 处理稀疏数组:空槽将会被视为undefined。
  • 处理新数组赋值:不需要修改原始数组,直接拼接原始数组以及添加元素内容即可完成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值