【问题标题】:Calling splice on an extended Array causes an Error and I have no idea why在扩展数组上调用 splice 会导致错误,我不知道为什么
【发布时间】:2020-11-04 20:39:03
【问题描述】:

当我在课堂上调用Remove 时,它会在涉及this.splice 时引发错误。请注意,this.index 工作正常。你知道为什么吗?您有解决方法吗?

export class DefaultReorderableList<T> extends Array<T> implements ReorderableList<T> {

    constructor(items: Array<T>=[]) {
        super(...items);
        Object.setPrototypeOf(this, new.target.prototype);
    }
    
    Remove(item: T | ((element:T)=>boolean) ): void {
        let index: number = -1;
        if(item instanceof ((element: T)=> Boolean)){
            for(let i:number = 0, l:number = this.length; i<l; i++){
                let foo:(element:T)=>boolean =item as (element:T)=>boolean;
                if(foo(this[i])){
                    index=i;
                }
            }
        }
        index = this.indexOf(item as T);
        if (index >= 0) {
            this.splice(index,1);
        }
    }

    SwapToPrevious(index: number): void {
        if(index == 0){
            return;
        }
        if(index < 0 || index >= this.length){
            throw new Error("Out of Range");
        }
        let indexedValue = this[index];
        this[index] = this[index -1];
        this[index-1]= indexedValue;
    }


    SwapToNext(index: number): void {
        if(index == 0){
            return;
        }
        if(index < 0 || index >= this.length){
            throw new Error("Out of Range");
        }
        let indexedValue = this[index];
        this[index] = this[index + 1];
        this[index + 1]= indexedValue;
    }

}

现在你可以在 JavaScript 中运行它:https://jsfiddle.net/La3pqj1v/

class DefaultReorderableList extends Array{

    constructor(items =[]) {
        super(...items);
        Object.setPrototypeOf(this, new.target.prototype);
    }
    
    Remove(item) {
        let index = -1;
        index = this.indexOf(item); // works
        if (index >= 0) {
            this.splice(index,1); // does not work
        }
    }

    SwapToPrevious(index) {
        if(index == 0){
            return;
        }
        if(index < 0 || index >= this.length){
            throw new Error("Out of Range");
        }
        let indexedValue = this[index];
        this[index] = this[index -1];
        this[index-1]= indexedValue;
    }


    SwapToNext(index) {
        if(index == 0){
            return;
        }
        if(index < 0 || index >= this.length){
            throw new Error("Out of Range");
        }
        let indexedValue = this[index];
        this[index] = this[index + 1];
        this[index + 1]= indexedValue;
    }

}

let testClass = new DefaultReorderableList();
testClass.push("a");
testClass.push("b");

console.log(testClass[0])
testClass.SwapToPrevious(1); // works
console.log(testClass[0])
testClass.Remove("b"); // does not work

【问题讨论】:

  • 错误说明了什么?
  • @imvain2 取决于运行时
  • @Bergi 现在我有时间添加一个可运行的示例
  • 顺便说一句,Object.setPrototypeOf(this, new.target.prototype); 在任何 ES6 兼容的环境中都应该是不必要的

标签: javascript typescript


【解决方案1】:

问题在于splice 返回一个包含已删除项目的数组。该数组与方法接收器(this 值)属于同一物种(读取:子类),即在您的情况下为 DefaultReorderableList。并且splice 用长度实例化一个new DefaultReorderableList(1),因为任何Array 构造函数都应该支持它。您的构造函数违反了实现该接口的约定,并在尝试迭代 super(...items) 中的数字时导致异常。

另见When Extending Array map is undefined

通过完全删除您的构造函数(或重新实现默认的constructor(...items) { super(...items); })来修复它。如果你想创建一个实例并传递一个数组来初始化它,请使用DefaultReorderableList.from([…])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-27
    • 1970-01-01
    • 1970-01-01
    • 2016-08-16
    • 1970-01-01
    • 2014-10-07
    • 2010-09-18
    相关资源
    最近更新 更多