Функции в объектных литералах


У меня 2 вопроса о функциях внутри объекта литералы. Я включил обходные пути я использую, но они, кажется, программистские. Есть ли лучший способ сделать это?

ns = {
  a: function (x, y) { return x+y; },

  // Problem 1

  // This does not work: Error: ns.b is not a function
  b: this.a,

  // Is this the correct workaround for this?
  c: function (x, y) { return this.a(x, y); },

  // Problem 2

  // I understand why this won't work, because a is not defined in d's scope
  d: function (x, y) {
    function add(n, o) {
      return this.a(n, o);
    }
    return add(3, 4);
  },

  // Is this the correct workaround for this?  It works in Firefox and Chrome.
  e: function (x, y) {
    function add(n, o) {
      return ns.a(n, o);
    }
    return add(3, 4);
  }
};

ns.a(3, 4); //===> 7

ns.b(3, 4); //===> Error: ns.a is not a function
ns.c(3, 4); //===> 7

ns.d(3, 4); //===> Error: no method named a
ns.e(3, 4); //===> 7

Редактировать: Спасибо за все ваши ответы. Как missingno указал я использую НС для определения модуля, хотя я избегал шаблона модуля, потому что у меня нет каких-либо частных переменных. Следующие вроде бы элегантное решение моей проблемы.

var ns = {};
ns.a = function (x, y) { return x+y; };
ns.b = ns.a;
ns.c = function (x, y) {
  function add(n, o) {
    return ns.a(3, 4);
  }
  return add(x, y);
}

ns.a(3, 4); //===> 7
ns.b(3, 4); //===> 7
ns.c(3, 4); //===> 7

После этого была перенесена в код комментарий, Я приветствую любую критику моей реализации схемы SRFI-1.



8462
2
задан 12 декабря 2011 в 01:12 Источник Поделиться
Комментарии
4 ответа

Проблема 1

Просто назначить их по одному за раз, после того, как объект уже существует:

ns = {};
ns.a = function (x, y) { return x+y; };
ns.b = ns.a;

Чтобы ответить конкретно, есть ли любой другой способ, если вы решительно настроены на объявлении этих внутри литерала объекта синтаксис: нет.

Проблема 2

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

Рассмотрите возможность использования вместо прототипирования.

4
ответ дан 12 декабря 2011 в 01:12 Источник Поделиться

1) нормальное решение для дублирования функций просто использует переменную

var f = function(){};
var ns = {
a: f,
b: f
},

2) и нормальное решение для вложенных этого с помощью промежуточной переменной

var that = this;
var f = function(){
that.a();
}

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

//this is just an example. There are many variations on this theme...
var ns = (function(){

var M = {};

var a_private_f = function(){ /*...*/ };

M.a = function(){
a_private_f();
}

M.b = function(){
M.a();
}

return M;

}());

Отказ от использования этого ссылаться на другие функции в пространстве имен также позволяет ваши функции будет передаваться через обратные вызовы, в ситуациях, когда это не точка в пространстве имен объекта.

2
ответ дан 12 декабря 2011 в 01:12 Источник Поделиться

Проблема 1
При создании объектного литерала, такого уровня, что функция построения объекта. Это позволяет сделать:

this.foo = 'bar';
var obj = { foo: this.foo };
console.log(obj.foo); // 'bar'

На самом деле объект не существует до конца объектного литерала, поэтому нет объекта для ссылки.

Корректной работы для вас вопрос как бы так. Потому что нельзя использовать одно и то же значение для нескольких ключей в литерал объекта.

ns = { a: function() {} };
ns.c = ns.a; // the same function now is on .a and .c

Проблема 2

Это не имеет ничего общего с областью, но вместо контекста (значение этого). В вызовах функции, точечный синтаксис-это то, что обеспечивает это. Например:

obj.someFn() // inside someFn: this === obj

Это синтаксис, который обеспечивает это. Поэтому, когда нет точки доступа, это по умолчанию глобальный объект (окно в браузере).

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

d: function(x, y) {
var self = this;
var add = function(x, y) {
self.a(x, y);
};
add(3, 4);
}

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

d: function(x, y) {
var add = function(x, y) {
this.a(x, y);
};
add.call(this, 3, 4);
}

2
ответ дан 12 декабря 2011 в 01:12 Источник Поделиться

// I understand why this won't work, because a is not defined in d's scope

Ошибочные. Как вы написали это, объем не имеет значения В добавить функцию, потому что вы назвали его без рамки объекта, т. е. добавить(3, 4). Если вы хотите, чтобы область, в Добавить же объем в D, вы должны использовать добавить.вызов(этот, 3, 4).

0
ответ дан 12 декабря 2011 в 01:12 Источник Поделиться