Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Вопрос про scope (https://javascript.ru/forum/misc/10067-vopros-pro-scope.html)

B~Vladi 17.06.2010 21:41

Вопрос про scope
 
function fn(data){
  return {
    get: function(){
      return data;
    }
  }
}

var test1 = fn(1);
var test2 = fn(2);

alert(test1.get());
alert(test2.get());
alert(test1.get());


Собственно, почему третий alert выводит 1?! Функция одна, а локальная область всегда новая при каждом вызове?!

Octane 17.06.2010 21:53

Функция не одна, ты каждый раз при вызове fn создаешь:
function(){
	      return data;
	    }

которая и замыкает разный data.

B~Vladi 17.06.2010 21:56

А разве новая функция не берёт значение из scope fn?

B~Vladi 17.06.2010 22:11

Вот ещё пример:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <title></title>
</head>
<body>
<script type="text/javascript">
  function fn(){
    eval('var ' + this.name + ' = ' + this.value);
    alert(this.name);
  }
  fn.call({
    name: 'test1',
    value: '1'
  });
  fn.call({
    name: 'test2',
    value: '2'
  });  
</script>
</body>
</html>

Поставьте брейкпоинт на alert. При втором вызове почему-то нет переменной test1. При вызове функции, её старый scope затирается?

Octane 17.06.2010 22:30

А понял о чем вопрос. Ну да каждый раз при вызове функции создается новый контекст исполнения (если не ошибаюсь в терминологии).

Gvozd 17.06.2010 22:32

B~Vladi,
у вас сложилось превратное понимание замыканий

при повторном вызове ф-ции, она не имеет понятия о пеерменных внутри нее созданных при более ранних ее вызовах.
поэтому в вашем втором примере ф-ция не помнит переменную test1

Кстати, при кадом новом вызове ф-ции, создается новый [scope], а при завршении ее, убивается, если на него нету ссылок(например их созданных внутри ф-ций)

поэтому в вашем первом примере, каждый вызов fn() создает новый [scope], который запоминается свежесозаднной ф-цией внутри fn()
поэтому каждая из этих ф-ций помнит свой scope, и ничего не знает о чужом

[scope] ф-ции -- это не что-то привязанное к самой ф-ции, а привязанное к ней, и ее одному запуску.
новый запуск-новый [scope]

B~Vladi 17.06.2010 23:09

Гадство. А как бы мне сделать так, чтобы я мог в уже существующий scope добавлять свои переменные?
Например есть функция:
function fn(){
  var test = 1;
}

Я в неё хочу добавить ещё одну переменную - test2 после первого выполнения fn. Другими словами - мне нужен динамический scope...

Есть другой вариант - with. Вот например мы можем обращаться к document без указания window. Какие есть отличия между такими scope? Вроде получается тоже самое:
var obj = {
  a: 1
};
with(obj){
  alert(a); // 1
  a = 3
}
alert(obj.a); // 3

Gvozd 17.06.2010 23:33

Цитата:

Сообщение от B~Vladi
в уже существующий scope добавлять свои переменные?

никак.
можно только менять уже определенные ранее в нем переменные.
Цитата:

Сообщение от B~Vladi
Есть другой вариант - with

опять таки, он позволяет работать только с уже существующими свойствами
var obj = {
  a: 1
};
with(obj){
  alert(a); // 1
  a = 3;
  b=4;
}
alert(obj.a); // 3
alert(obj.b); // undefined вместо 4
alert(b); // 4 вместо undefined

Цитата:

Сообщение от B~Vladi
Какие есть отличия между такими scope

те, что with-это не scope

B~Vladi 17.06.2010 23:39

Цитата:

Сообщение от Gvozd
те, что with-это не scope

Да, я не правильно выразился. Мне не нужно определять несуществующие свойства... Просто хочу создать среду где было бы глобальная область видимости + мои переменные, доступные просто по имени. Пожалуй with подойдет.

Gvozd 17.06.2010 23:41

Цитата:

Сообщение от B~Vladi
Мне не нужно определять несуществующие свойства... Просто хочу создать среду где было бы глобальная область видимости + мои переменные, доступные просто по имени. Пожалуй with подойдет.

замыкание под эти требования все также подходит.
чем оно вам не нравится?

B~Vladi 17.06.2010 23:44

Цитата:

Сообщение от Gvozd
замыкание под эти требования все также подходит.

Где же подходит? Можно демку?
Цитата:

Сообщение от Gvozd
чем оно вам не нравится?

Если не сложно - давай на ты?

Gvozd 18.06.2010 00:51

Цитата:

Сообщение от B~Vladi
Можно демку?

все ваши требования соблюдены
var global=1;
(function(){
var local=2;
window.fn=function(){
alert(global);
alert(local);
}
})()
fn();

Цитата:

Сообщение от B~Vladi
Если не сложно - давай на ты?

мне привычней в инете общаться на вы.
постараюсь запомнить что с тобой на ты, но могу забыть

B~Vladi 18.06.2010 14:37

Ну я всё равно не смогу добавить переменную local2 в scope анонимной функции, после её выполнения...

e1f 18.06.2010 15:35

Цитата:

Сообщение от B~Vladi (Сообщение 60034)
Ну я всё равно не смогу добавить переменную local2 в scope анонимной функции, после её выполнения...

B~Vladi, а Вам действительно нужно именно это? ;) Как вариант -- добавляйте свойства прототипу функции.

B~Vladi 18.06.2010 19:46

Цитата:

Сообщение от e1f
B~Vladi, а Вам действительно нужно именно это?

Хм.
Ну вот представь глобальную область видимости. Хочу такую же, только свою. Но чтобы в глобальной не было моих переменных.
А тобой можно на ты?
Цитата:

Сообщение от e1f
Как вариант -- добавляйте свойства прототипу функции.

Ну это не кошерный вариант.

e1f 18.06.2010 19:54

B~Vladi, а Ваш вириант кошерен? Давайте тогда уточнять, что же вы подразумеваете под "своей областью видимости". Приводите пример из имеющихся языков программирования :)

Gvozd 18.06.2010 20:08

Цитата:

Сообщение от B~Vladi
Ну я всё равно не смогу добавить переменную local2 в scope анонимной функции, после её выполнения...

Цитата:

Сообщение от B~Vladi
Да, я не правильно выразился. Мне не нужно определять несуществующие свойства...

вы уж определитесь что ли?

B~Vladi 18.06.2010 21:23

Ты ты ты ты ты:)
А не вы:)

Я то определился.
Есть некая область видимости, из которой доступна глобальная (ну само собой).
Есть 2 фронта.
Первый фронт - мой. Из этого фронта я должен определять свои переменные, доступные только из этой "некой" области видимости, но не из глобальной. Необходимо, чтобы я в любой момент мог определить любую переменную с нужным мне именем.
Второй фронт - вражеский. Из него можно получить доступ к переменным, определённым в первом фронте, просто обращаясь по имени (как к document, без указания window в глобальной области). Из этого же фронта нельзя определить свои переменные, разве что если они попадут в глобальную область - ничего страшного.
Задачка не тривиальная, поэтому собсно и был создан этот сабж. У меня конечно же есть свои наработки, но пока не 100% того что я хочу.
Сори, если кого ввел в заблуждение. Мне проще на словах рассказать.

Kolyaj 19.06.2010 08:56

B~Vladi,
шаблонный движок чтоле?

B~Vladi 19.06.2010 11:41

Цитата:

Сообщение от Kolyaj
шаблонный движок чтоле?

Это как?:)

B~Vladi 19.06.2010 15:14

Всем спасибо, тему можно закрывать. Демо-код получился такой:
(function(){
  if(this == window){
    document.userScope = arguments.callee;
  } else {
    with(this.stack){ // Область видимости для вражеского фронта
      eval('(function(){' + this.code + '}).call(this.module);');
    }
    this.stack[this.name] = this.module;
  }

})();

(function(){ // Мой фронт
  var userScope = document.userScope;
  delete document.userScope;

  var stack = {};

  var module1 = {};
  var module2 = {};

  userScope.call({ // Добавляем первую переменную
    name: 'module1',
    code: 'this.fn = function(){console.log(module2)};', // Вражеский фронт
    module: module1,
    stack: stack
  });

  userScope.call({
    name: 'module2',
    code: 'console.log(this)',
    module: module2,
    stack: stack
  });

  module1.fn(); // После добавления новых переменных, старые их тоже видят.

})();

Ничего лишнего не попало во вражескую область видимости.


Часовой пояс GMT +3, время: 07:41.