Как сделать выражение Immediately-Invoked-Func-Expression, чтобы иметь доступ к ранее определенному свойству в javascript, как только объект будет построен

1
 var Counter = function(name) {
    this.name = name;
    this.data = (function() {
        console.log(this.name);
    })();
};

var counter = new Counter("some name");

Ожидаемое поведение: напечатать "какое-то имя".

Текущее поведение: ничего не печатается.

Я пытаюсь получить доступ к "данным" внутреннего свойства, как только объект будет создан. Эти "данные" извлекаются с использованием функции, которая зависит от внутреннего имени "имя". Однако, когда вызывается вызванное сразу выражение функции, похоже, что он не может получить доступ к свойству this.name, поэтому я не могу получить данные сразу после построения объекта.

Я могу заставить его работать, сначала определив эквивалент this типа:

var Counter = function(name) {
    var that = {};
    that.name = name;
    that.data = (function() {
        console.log(that.name);
    })();
    return that;
};

var counter = new Counter("some name");

Почему это происходит? Как я могу заставить его работать элегантным способом?

  • 1
    Ваша самоисполняющаяся функция не имеет оператора return .
  • 0
    И почему именно вы не просто использовать name или передать name в качестве параметра функции?
Показать ещё 1 комментарий
Теги:
iife

3 ответа

2
Лучший ответ

this печально известно в JavaScript для изменения в разных контекстах. this во внутренней функции является глобальным объектом (window, если вы запустите его в браузере), а не this объект в конструкторе.

Существует несколько различных решений, в зависимости от того, какую версию JavaScript вы планируете:

ECMAScript 5

Вы можете передать this значение, apply [MDN]:

var Counter = function(name) {
  this.name = name;
  this.data = (function() {
    console.log(this.name);
  }).apply(this);
};

var counter = new Counter("some name");

ECMAScript 6

Если вы используете ES6, вы можете использовать функции стрелок, которые автоматически связывают this значение родительской функции:

var Counter = function(name) {
  this.name = name;
  this.data = (() => {
    console.log(this.name);
  })();
};

var counter = new Counter("some name");

ECMAScript 3

Другой вариант, похожий на то, что у вас есть в вашем вопросе, является присвоение this новым переменным that. Тогда вы можете ссылаться на that в дочерней функции.

var Counter = function(name) {
  var that = this;
  that.name = name;
  that.data = (function() {
    console.log(that.name);
  })();
};

var counter = new Counter("some name");

Это было наиболее распространенное решение до тех пор, пока apply было введено в ECMAScript 5.

  • 0
    Спасибо, оба "применяются" и "тот" методы работают! Однако мне хочется использовать что-то неясное, чего я не понимаю. Также использование некоторой простой переменной вместо «this.name» заставляет его работать. Почему подход "this.name" не работает?
  • 1
    @mclzc Как я уже упоминал в своем ответе, во внутренней функции this имеет другое значение, чем во внешней. Вот почему вам нужно передать значение для этого с apply или сохранить его в другой переменной, подобной that .
2

Проблема в вашем примере была контекстом. При использовании (function(){ } )() вы используете новый контекст, у которого есть this.name отличное от свойства имени функции Counter.

Вы можете использовать функцию стрелки, чтобы контекст мог использоваться внутри вашей функции IIFE.


ПРЕДУПРЕЖДЕНИЕ: Моему растворителю нужна поддержка ECMA2015 aka es6. Другое совпадение без es6 - использовать ответ @Peter Olson.

Здесь вы можете увидеть таблицу совместимости функции стрелки.

const Counter = function(name) {
    this.name = name;
    
    this.data = (() => {
      console.log(this.name);
    })();
};

const counter = new Counter('some name');
  • 1
    Я собирался спросить это, если есть способ не использовать функции es6, потому что я использую сценарии Google Apps, которые не поддерживают его. Благодарю.
0

Некоторая хорошая информация выше. Мне также интересно, можете ли вы просто назначить this.data, а затем сразу же вызвать свою функцию сразу после?

var Counter = function(name) {
  this.name = name;
  this.data = this.name;
  console.log(this.data);
};

var counter = new Counter("some name");

Ещё вопросы

Сообщество Overcoder
Наверх
Меню