自学内容网 自学内容网

Javascript数组研究08_手写实现_toString_unshift_values_with

36 Array.prototype.toString()

36.1 基本介绍

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

toString()

输入参数:无。

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

注意事项

  • Array对象覆盖了ObjecttoString方法,内部调用了join方法,使用,来拼接数组元素。
  • 如果join方法不可用会使用Object.prototype.toString()方法来替代。
  • 当数组需要表示为文本值的时候会自动调用toString()方法。
36.2 手写实现
MyArray.prototype.toString = function(){
    if(typeof this.join !== "function"){
        return Object.prototype.toString.call(this)
    }else{
        return this.join()
    }
}


const arr = new MyArray()
arr.join = 1; // 将 `join` 重新赋值为非函数的值
console.log(arr.toString()); // [object Array]

const arr_1 = new MyArray(1, 2, "a", "1a");
console.log(arr_1.toString()); // "1,2,a,1a"
console.log(MyArray.prototype.toString.call({ join: () => 1 }));
// 1; 一个数字
console.log(MyArray.prototype.toString.call({ join: () => undefined }));
// undefined
console.log(MyArray.prototype.toString.call({ join: "not function" }));
// "[object Object]"

难点总结

  • 方法选择:根据join是否是函数来判断调用其他函数来实现,使用Object原型上的toString或者调用自身的join方法。

37 unshift

37.1 基本介绍

unshift 方法将指定元素添加到数组的开头,并返回数组的新长度。

unshift()
unshift(element1)
unshift(element1, element2)
unshift(element1, element2, /* …, */ elementN)

输入参数elementN是添加到数组开头的元素

输出:返回添加元素后的length属性。

注意事项

  • unshiftpush有类似的行为,但是将其元素插入到末尾。
  • 方法是通用的
37.2 手写实现
MyArray.prototype.unshift = function(...args){
    const newCount = args.length
    const len = this.length ? this.length : 0
    for(let i = this.length; i >= 0; i --){
        if(i in this){
            this[i + newCount] = this[i]
        }else{
            delete this[i + newCount]
        }
    }

    for(let i = 0; i < newCount; i ++){
        this[i] = args[i]
    }

    this.length = len + newCount

    return this.length
}


// 测试示例
let arr_2 = new MyArray(4, 5, 6);
arr_2.unshift(1, 2, 3);
console.log(arr_2);
// [1, 2, 3, 4, 5, 6]
let arr_3 = new MyArray(4, 5, 6);
arr_3.unshift(1);
arr_3.unshift(2);
arr_3.unshift(3);
console.log(arr_3);
// [3, 2, 1, 4, 5, 6]
const arrayLike = {
    length: 3,
    unrelated: "foo",
    2: 4,
};
MyArray.prototype.unshift.call(arrayLike, 1, 2);
console.log(arrayLike);
// { '0': 1, '1': 2, '4': 4, length: 5, unrelated: 'foo' }
const plainObj = {};
// 这里没有长度属性,所以这里的长的为 0
MyArray.prototype.unshift.call(plainObj, 1, 2);
console.log(plainObj);
// { '0': 1, '1': 2, length: 2 }

难点总结

  • 正确处理length:有的类数组对象可能不会携带length属性,此时要判断length的合法性。统计加入元素的个数,从而计算出正确的长度在最后返回。
  • 正确的移动数组:根据插入的元素个数来正确的移动数组,遇到空槽需要正确的delete this[i + newCount]

38

38.1 基本介绍

values() 方法返回一个新的数组迭代器对象,该对象迭代数组中每个元素的值。

values()

输入参数:无。

输出:一个新的可迭代迭代器对象。

注意事项

  • Array.prototype.values() Array.prototype[Symbol.iterator]() 的默认实现。
  • 空槽会被处理为undefined
  • 生成的迭代器对象是一次性的,当状态donetrue的就不该再次使用。
38.2 手写实现
MyArray.prototype.values = function(){
    if(Array.isArray(this)){
        return this[Symbol.iterator]()
    }else {
        const arrLike = this
        let index = 0
        return {
            next(){
                if(index < arrLike.length){
                    const res = {value: arrLike[index ++], done: false}
                    return res
                }else{
                    return {value: undefined, done: true}
                }
            },
            [Symbol.iterator]:function(){
                return this
            }
        }
    }
}



// 测试代码
const arr_4 = new MyArray("a", "b", "c", "d", "e");
const iterator = arr_4.values();

for (const letter of iterator) {
  console.log(letter);
} // "a" "b" "c" "d" "e"
const arrayLike_1 = {
    length: 3,
    0: "a",
    1: "b",
    2: "c",
  };
  for (const entry of MyArray.prototype.values.call(arrayLike_1)) {
    console.log(entry);
  }
  // a
  // b
  // c

难点总结

  • 类数组对象处理:类数组对象一般没有实现迭代器协议和迭代器方法,我们需要返回一个可迭代的像(实现next方法,且自身实现迭代器协议)
  • 数组返回:注意返回的是调用迭代器协议下迭代器方法返回的迭代器,不要返回整个迭代器方法。

39 Array.prototype.with()

39.1 基本介绍

with 方法是使用方括号表示法修改指定索引值的复制方法版本。它会返回一个新数组,其指定索引处的值会被新值替换。

arrayInstance.with(index, value)

输入参数index要修改的数组索引,越界会有RangeErrorvalue要分配给指定索引的值。

输出:一个替换了index索引的值的全新数组。

注意事项

  • index > array.lengthindex < -array.length 时抛出RangeError
  • 对于稀疏数组,将会把空槽视为undefined
39.2 手写实现
MyArray.prototype.with = function(index, value){
    if(index <= -this.length || index > this.length){
        throw RangeError("index out of Range")
    }

    index = index < 0 ? index + this.length : index
    const res = new MyArray()
    for(let i = 0; i < this.length; i ++){
        if(i === index){
            res[i] = value
        }else{
            res[i] = this[i]
        }
    }

    return res
}
  

const arr_5 = new MyArray(1, 2, 3, 4, 5);
console.log(arr_5.with(2, 6)); // [1, 2, 6, 4, 5]
console.log(arr_5); // [1, 2, 3, 4, 5]
const arrayLike_2 = {
    length: 3,
    unrelated: "foo",
    0: 5,
    2: 4,
    3: 3, // 由于 length 属性的值为 3,with() 会忽略该值
  };
  console.log(MyArray.prototype.with.call(arrayLike_2, 0, 1));
  // [ 1, undefined, 4 ]

难点总结

  • 范围错误:当范围不合法时抛出错误,这和之前很多索引处理不同。
  • 返回全新数组:不修改原数组,而是返回一个全新的数组。

原文地址:https://blog.csdn.net/qq_33546823/article/details/142705242

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!