Как реализовать шаблон посетителя в javascript?

Насколько я понимаю, шаблон посетителя часто используется для добавления методов к некоторой структуре иерархии. Но я все равно не понимаю: см. Пример, где я пытаюсь выделить левое поддерево:

subtree highlighting

Реализация дерева JavaScript:

  function node(val) {
    this.value = val;
    this.left = this.right = null;
  }

  var tree = new node("A");
  tree.left = new node("B1");
  tree.right = new node("B2");
  tree.left.left = new node("C1");
  tree.left.right = new node("C2");

Я думаю, что я использую подсветку посетителя:

node.prototype.accept = function(visitorObj) {
  visitorObj.visit(this);
}

function visitor() {
  var that = this;
  this.visit = function(tgt) {
    tgt.value = "*"+tgt.value;
  }
  this.highlight = function(tgt) {
    tgt.accept(that);
    if(tgt.left) that.highlight(tgt.left);
    if(tgt.right) that.highlight(tgt.right);
  }
}

(new visitor()).highlight(tree.left);

Но зачем использовать методы accept-visit, когда это может быть более простым?

function visitor() {
  var that = this;
  this.highlight = function(tgt) {
    tgt.value = "*"+tgt.value;
    if(tgt.left) that.highlight(tgt.left);
    if(tgt.right) that.highlight(tgt.right);
  }
}

(new visitor()).highlight(tree.left);

Он похож на этот пример. Означает ли это, что если языковые типы смешивания (например, javascript), нет причин для пары accept-visit вообще?

Ответ 1

Вы пропустили что-то в реализации. Представьте, что левое и правое свойства элемента Node были частными. Тогда как бы вы выделили их в своей реализации?

Посетитель не должен знать древовидную структуру и пусть элемент Node запускает посетителя на любом подэлементе, который является прямым потомком. Поэтому ваш код должен выглядеть так:

node.prototype.accept = function(visitorObj) {
    visitorObj.visit(this);
    if (this.left) this.left.accept(visitorObj);
    if (this.right) this.right.accept(visitorObj);
}

function visitor() {
    var that = this;
    this.visit = function(tgt) {
        tgt.value = "*"+tgt.value;
    }
    this.highlight = function(tgt) {
        tgt.accept(that);
    }
}

(new visitor()).highlight(tree.left);

Таким образом, посетитель не знает структуру дерева, он является общим и будет работать на любом Node, который имеет свойство "value".