Implement Array-like behavior in JavaScript without using Array

后端 未结 10 1209
暖寄归人
暖寄归人 2020-12-13 07:45

Is there any way to create an array-like object in JavaScript, without using the built-in array? I\'m specifically concerned with behavior like this:

var sup         


        
10条回答
  •  情话喂你
    2020-12-13 07:50

    Interface and implementation

    The case is a simple implementation of the original array packaging, you can replace the data structure and refer to the common interface can be implemented.

    export type IComparer = (a: T, b: T) => number;
    
    export interface IListBase {
      readonly Count: number;
      [index: number]: T;
      [Symbol.iterator](): IterableIterator;
      Add(item: T): void;
      Insert(index: number, item: T): void;
      Remove(item: T): boolean;
      RemoveAt(index: number): void;
      Clear(): void;
      IndexOf(item: T): number;
      Sort(): void;
      Sort(compareFn: IComparer): void;
      Reverse(): void;
    }
    
    
    export class ListBase implements IListBase {
      protected list: T[] = new Array();
      [index: number]: T;
      get Count(): number {
        return this.list.length;
      }
      [Symbol.iterator](): IterableIterator {
        let index = 0;
        const next = (): IteratorResult => {
          if (index < this.Count) {
            return {
              value: this[index++],
              done: false,
            };
          } else {
            return {
              value: undefined,
              done: true,
            };
          }
        };
    
        const iterator: IterableIterator = {
          next,
          [Symbol.iterator]() {
            return iterator;
          },
        };
    
        return iterator;
      }
      constructor() {
        return new Proxy(this, {
          get: (target, propKey, receiver) => {
            if (typeof propKey === "string" && this.isSafeArrayIndex(propKey)) {
              return Reflect.get(this.list, propKey);
            }
            return Reflect.get(target, propKey, receiver);
          },
          set: (target, propKey, value, receiver) => {
            if (typeof propKey === "string" && this.isSafeArrayIndex(propKey)) {
              return Reflect.set(this.list, propKey, value);
            }
            return Reflect.set(target, propKey, value, receiver);
          },
        });
      }
      Reverse(): void {
        throw new Error("Method not implemented.");
      }
      Insert(index: number, item: T): void {
        this.list.splice(index, 0, item);
      }
      Add(item: T): void {
        this.list.push(item);
      }
      Remove(item: T): boolean {
        const index = this.IndexOf(item);
        if (index >= 0) {
          this.RemoveAt(index);
          return true;
        }
        return false;
      }
      RemoveAt(index: number): void {
        if (index >= this.Count) {
          throw new RangeError();
        }
        this.list.splice(index, 1);
      }
      Clear(): void {
        this.list = [];
      }
      IndexOf(item: T): number {
        return this.list.indexOf(item);
      }
      Sort(): void;
      Sort(compareFn: IComparer): void;
      Sort(compareFn?: IComparer) {
        if (typeof compareFn !== "undefined") {
          this.list.sort(compareFn);
        }
      }
      private isSafeArrayIndex(propKey: string): boolean {
        const uint = Number.parseInt(propKey, 10);
        const s = uint + "";
        return propKey === s && uint !== 0xffffffff && uint < this.Count;
      }
    }
    

    Case

    const list = new List(["b", "c", "d"]);
    const item = list[0];
    

    Reference

    • proxy
    • [Symbol.iterator]()

提交回复
热议问题