Ошибка использования функции генератора в качестве значения WeakMap - PullRequest
1 голос
/ 27 апреля 2020

Я строю связанный список самостоятельно. Я попытался назначить генератор в качестве значения ключа / значения WeakMap в конструкторе. _iterator - это WeakMap, потому что это закрытый член, который я хочу использовать для упрощения итерации по моей структуре данных, но я не хочу делать генератор видимым снаружи, потому что в противном случае я нарушу абстракцию. Но у меня ошибка SyntaxError: missing ( before formal parameters. В чем проблема?

  class Node{
     constructor(value){
        this.value = value;
        this.next = null;
     }
  }

  //IIFE function that return the class. 
  const SingleLinkedList = (() => { //Here use IIFE to create a new block scope for private variables
     let _counts = new WeakMap();
     let _head = new WeakMap();
     let _tail = new WeakMap();
     let _iterator = new WeakMap();

     class SingleLinkedList {
        constructor() {
           _counts.set(this, 0);
           _head.set(this, null);
           _tail.set(this, null);
           let instance = this;//closure
           _iterator.set(this,(function* [Symbol.iterator](){
              let n=_head.get(instance);
              while(n){
                 yield n;
                 n = n.next;
              }
           }));
        }


        get counts() { //read only get accessor property
           return _counts.get(this);
        }

        isEmpty() {
           return !this.counts;  //or return !_head.get(this)
        }

        //insert a new Node (in tail) with the desired value
        push(value) {
           let n = new Node(value);
           if (this.isEmpty()) 
              _head.set(this, n);
           else {
              let tail = _tail.get(this); //tail is a pointer to the node-tail
              tail.next = n; //old tail-node will point to new node
           }

           //the following instructions are common to both the cases.
           _tail.set(this, n); //set new tail
           _counts.set(this, this.counts+1); //increment item counter

           return this; //to allow multiple push call
        }

        //Generator to return the values
        *[Symbol.iterator](){

           let n = _head.get(this); 
           while(n){
              yield n.value;
              n=n.next;
           }
        }
        //the the values of each node
        print() {
           let output = "";
           for(let el of this)
              output += `${el} `;
           console.log(output);
        }
     }
     return SingleLinkedList;
  })();

  let myLinkedList = new SingleLinkedList();
  myLinkedList.push(3);
  myLinkedList.push(5);
  myLinkedList.print();

  /*for(let x of myLinkedList)
     console.log(x);*/

1 Ответ

4 голосов
/ 27 апреля 2020

Функциональные выражения не могут иметь вычисляемых имен, этот синтаксис разрешен только для литералов объекта или членов класса, поэтому вместо этого определите конструктор вашего SingleLinkedList следующим образом:

constructor() {
  _counts.set(this, 0);
  _head.set(this, null);
  _tail.set(this, null);
  let instance = this;//closure
  _iterator.set(this, function* (){
// remove the computed name ---^
    let n=_head.get(instance);
    while(n){
      yield n;
      n = n.next;
    }
  });
}

Возможно, даже больше полезно знать, как отлаживать синтаксические ошибки в будущем, поэтому вам не нужно снова задавать такие вопросы. Если вы откроете консоль разработчика, нажав F12, вы увидите журнал, который выглядит примерно так:

SyntaxError in developer console

Нажмите эту ссылку, и она займет Вы прямо к месту нахождения ошибки:

SyntaxError in debugger


Просто для удовольствия, я предлагаю переписать, используя некоторые более современные функции ECMAScript, такие как приватные поля :

class Node {
  next = null;

  constructor (value) {
    this.value = value;
  }
}

class SingleLinkedList {
  #size = 0;
  #head = null;
  #tail = null;

  // read only get accessor property
  get size () {
    return this.#size;
  }

  isEmpty () {
    return this.#size === 0;
  }

  // insert a new Node (in tail) with the desired value
  push (value) {
    const node = new Node(value);

    if (this.isEmpty()) {
      this.#head = node;
    } else {
      this.#tail.next = node;
    }

    // the following instructions are common to both the cases.
    this.#tail = node;
    this.#size++;

    // to allow multiple push call
    return this;
  }

  // generator to return the values
  *[Symbol.iterator] () {
    for (let current = this.#head; current; current = current.next) {
      yield current.value;
    }
  }

  // the the values of each node
  toString () {
    return [...this].join(' ');
  }
}

const myLinkedList = new SingleLinkedList();
myLinkedList.push(3).push(5);
console.log(myLinkedList.toString());
...