Создание добирается/метод установки динамично в JavaScript

Я пытаюсь создать объект UserDon, и пытающийся генерировать получение и методы установки программно (на основе Pro книги JavaScript страницей 37 John Resig), и тестирую это на Firefox 3.5

Проблема: в функциональном UserDon "это" относится к объекту окна вместо объекта UserDon.

Таким образом, после называния var userdon = новый UserDon (...) я получил setname и getname методы, созданные на объекте окна (также setage и getage).

Как я могу зафиксировать это?

function UserDon( properties ) {
   for( var i in properties ) {
   (function(){
      this[ "get" + i ] = function() {
        return properties[i];
      };

      this[ "set" + i ] = function(val) {
        properties[i] = val;
      };
      })();
   }
 }

var userdon = new UserDon( {
   name: "Bob",
   age: 44
});
6
задан Don Ch 11 April 2010 в 04:32
поделиться

4 ответа

Используемое вами значение this принадлежит автоматически вызывающемуся выражению функции внутри цикла, и когда вы вызываете функцию таким образом, this будет всегда относятся к глобальному объекту.

Редактировать: Я пропустил тот факт, что выражение функции пытается захватить переменную для обработки создания получателя / установщика внутри цикла, но переменная цикла i , необходимо передать в качестве аргумента для этого, и поскольку выражение функции присутствует, контекст (внешний this ) должен быть сохранен:

function UserDon( properties ) {
  var instance = this; // <-- store reference to instance

  for( var i in properties ) { 
    (function (i) { // <-- capture looping variable
      instance[ "get" + i ] = function() {
        return properties[i];
      };

      instance[ "set" + i ] = function(val) {
        properties[i] = val;
      };
    })(i); // <-- pass the variable
  }
}

var userdon = new UserDon( {
   name: "Bob",
   age: 44
});

userdon.getname(); // "Bob"
userdon.getage();  // 44

Вы также можете использовать call для вызова функционального выражения, сохраняя контекст (значение this ) и вводя переменную цикла в новую область видимости за один шаг:

function UserDon( properties ) {
  for( var i in properties ) { 
    (function (i) { // <-- looping variable introduced
      this[ "get" + i ] = function() {
        return properties[i];
      };

      this[ "set" + i ] = function(val) {
        properties[i] = val;
      };
    }).call(this, i); // <-- preserve context and capture variable
  }
}

Я бы также рекомендовал использовать if (properties.hasOwnProperty (i)) {...} внутри цикла for ... in , чтобы избежать повторения расширенных свойств пользователя, унаследованных от Object.prototype .

7
ответ дан 16 December 2019 в 21:37
поделиться

Вот как я бы это закодировал: -

function UserDon( properties ) {
   var self = this;
   for( var i in properties ) {
   (function(prop){
      self[ "get" + prop ] = function() {
        return properties[prop];
      };

      self[ "set" + prop ] = function(val) {
        properties[prop] = val;
      };
      })(i);
   }
 }
0
ответ дан 16 December 2019 в 21:37
поделиться

Возможно, было бы лучше получить общую функцию с 2 параметрами: имя свойства и значение (или только имя для геттера). И эта функция проверяла бы наличие специальной функции для этого свойства, и если таковой нет, то просто изменяла бы значение свойства (или возвращала бы его значение для getter).

0
ответ дан 16 December 2019 в 21:37
поделиться

Вы также можете использовать менее известные
__ defineGetter __ ("varName", function () {});
и __ defineSetter __ ("varName", function (val) {});

Хотя они нестандартны [например, x-html-replace content-type], они поддерживаются большинством браузеров, не относящихся к IE [chrome, firefox]

Синтаксис будет следующим:

benjamin = new object();
benjamin.__defineGetter__("age", function(){
  return 21;
});

Или вы можете подойти к этому с прототипированием

benjamin = {
  get age()
  {
    return 21;
  }
}
1
ответ дан 16 December 2019 в 21:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: