Конструктор терпит неудачу во второй раз, но не первый - PullRequest
1 голос
/ 10 июня 2019

У меня есть следующий код:

var foo = function () {
    foo = this;
    foo.boo = function () {
        console.log("boo");
    }
}

var bar = new foo().boo();
var baz = new foo().boo();

Этот код выполняет первое создание экземпляра foo, но завершается с ошибкой при следующем выводе:

boo
/Users/BaranSkistad/Code/example.js:9
var baz = new foo().boo();
          ^

TypeError: foo is not a constructor
    at Object.<anonymous> (/Users/BaranSkistad/Code/example.js:9:11)
    at Module._compile (module.js:573:30)
    at Object.Module._extensions..js (module.js:584:10)

    at Module.load (module.js:507:32)
    at tryModuleLoad (module.js:470:12)
    at Function.Module._load (module.js:462:3)
    at Function.Module.runMain (module.js:609:10)
    at startup (bootstrap_node.js:158:16)
    at bootstrap_node.js:578:3

Почему этот скрипт не работает?Я знаю, что это как-то связано с установкой foo в this в строке 2 вместо простого использования this, но почему это проблематично?

var foo = function () {
    self = this;
    self.boo = function () {
        console.log("boo");
    }
}

var bar = new foo().boo();
var baz = new foo().boo();

Если я установлю self равным this проходит, почему это так?

Ответы [ 2 ]

3 голосов
/ 10 июня 2019

Проблема в следующей строке

foo = this;

В строке выше пропущено объявление переменной. Так что foo будет ссылаться на глобальную переменную foo, которая является конструктором. Когда вы вызываете функцию в первый раз, когда строка выполняется, и foo изменяется на this (экземпляр foo)

Во втором случае код также создает глобальную переменную self, которая будет равна this. Но в этом случае он не изменит конструктор, потому что имена разные.

Решение этой проблемы - сделать foo локальной переменной с помощью let (или const/var).

var foo = function () {
    let foo = this;
    foo.boo = function () {
        console.log("boo");
    }
}

var bar = new foo().boo();
var baz = new foo().boo();
0 голосов
/ 10 июня 2019

Хотя вы уже получили ответ, но вы не можете явно установить this. Если вы console.log внутри foo работаете, он зарегистрирует object Вместо этого вы можете просто return и object, который будет иметь все внутренние функции

var foo = function() {
  return {
    testVal: 5,
    boo: function() {
      console.log("boo ", this.testVal);
    }
  }
}

var bar = new foo().boo();
var baz = new foo().boo();
...