поддельные локальные переменные функции

#javascript #function #scope

#javascript #функция #область видимости

Вопрос:

Есть ли какой-нибудь способ ввести здесь локальную переменную «iWantThisHere», чтобы я мог вызвать obj.n()

 var obj = { 
    test: "sure", 
    n : function(){ console.log(iWantThisHere); }
};
  

я пытался с:

 function fake(methods){
    var F =  new Function('methods', "var iWantThisHere = 'u have it', obj = {}; for( var meth in methods){ obj[meth] = methods[meth] } return obj;");

    return F(methods); }

console.log(fake(obj), fake(obj).n());
  

я не хочу использовать глобальные переменные здесь. Представьте себе модульную систему, где каждый модуль использует, например, класс util, который определен, например, в объекте приложения. Поэтому мне всегда приходится вводить, например, App.utils.map или что-то в этом роде. Было бы неплохо иметь ярлык для этой утилитарной функции, которая является локальной переменной в самом контексте модуля.

РЕДАКТИРОВАТЬ — нет никакого способа сделать это —-

Комментарии:

1. Да? О чем, черт возьми, ты говоришь?

2. Совсем не ясно, какой вы хотите видеть эту переменную, или делать, или что-то еще на самом деле.

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

4. я не хочу использовать глобальные переменные здесь. Представьте себе модульную систему, где каждый модуль использует, например, класс util, который определен, например, в объекте приложения. Поэтому мне всегда приходится вводить, например, App.utils.map или что-то в этом роде. Было бы неплохо иметь ярлык для этой утилитарной функции, которая является локальной переменной в самом контексте модуля.

5. @Sep O Sep — ну, просто нет способа сделать то, что вы хотите, если только вы не хотите заставить весь клиентский код вашей модульной системы определять все свои функции в виде необработанных строк для оценки вашим кодом (пожалуйста, пожалуйста, не делайте этого, ради человечества).

Ответ №1:

Ввести закрытие:

 var obj = (function(){
    var R = {};

    R.iWantThisHere = 5;

    R.log = function() {
        console.log(R.iWantThisHere);
    }

    return R;
})();
  

ДЕМОНСТРАЦИЯ:

 > obj.log()
5
> obj.iWantThisHere = 6
> obj.log()
6
  

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

Ответ №2:

Если ваш вопрос таков: «Как я могу поместить новое именованное значение в уже существующую область?», ответ заключается в том, что вы не можете. Самое близкое, к чему вы можете подойти, это:

 var obj = (function() {
  var iWantThisHere = "whatever";
  return {
    test: "sure",
    n: function() { var x = iWantThisHere   "yaay I have my special variable"; }
  };
})();
  

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

Комментарии:

1. хорошо, спасибо, я попробовал использовать какую-то хакерскую функцию, которая упаковала переданный obj в строку, подобную json, и переместила ее в новую область видимости, но это не было подходящим решением

Ответ №3:

Есть какая-то конкретная причина сделать это сложным способом? Почему бы просто не добавить аргумент к функции в obj.n ?

 var obj = { 
  test: "sure", 
  n : function(iWantThisHere){ console.log(iWantThisHere); }
};

obj.n("yeah");
  

Или даже проще (хотя область видимости становится уродливее):

 var iWantThisHere = "dance time";
var obj = {
  test: "sure", 
  n : function(){ console.log(iWantThisHere); }
};
obj.n();
  

Или с закрытием, плюс некоторые подробности о том, как вы разделяете их общедоступные и приватные части:

 var obj = (function() {
  var privateVariable = "i'm private";

  function privilegedMethod() {
  };

  return {
    iWantThisHere: "",
    test: "sure",
    n: function() {
      console.log(this.iWantThisHere);
    },
    publicVariable: "i'm public",
    publicMethod: function() {}
  };
})();

obj.iWantThisHere = "hi";
obj.n(); // logs "hi"
obj.addedMethod = function() { console.log("I've been added"); }
obj.addedMethod(); // logs "I've been added";
console.log(obj.privateVariable); // logs undefined (unavailable outside closure)
console.log(obj.publicVariable); // logs "i'm public"
  

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

Комментарии:

1. Я не уверен, хочет ли он предоставить ему что-то реальное для регистрации, но это, по крайней мере, сделало бы его вход неопределенным, если бы он вызвал obj.n () без аргументов.. Опять не ясно, чего именно он хочет.