2015-10-06 2 views
0

Может кто-нибудь объяснить мне следующий код:JavaScript Закрытие и Scoping вопросы

var person = (function() { 
    var locX = 0; 
    return { 
     "walk": function() { 
      locX++; 
     }, 
     "getLocX": function() { 
      return locX; 
     }, 
     "locX": locX 
    } 
})(); 


person.locX // output 0 

person.getLocX() // output 0 

person.walk() 

person.getLocX() // output 1 

person.locX // output 0 <-------- why it is still 0 

ответ

5

person.locX // выход 0 < -------- почему она до сих пор 0

Поскольку в объекте инициализаторе, это свойство инициализатор:

"locX" : locX 

принимает значение из locX и присваивает его собственности на объект. Он не создает ссылку между вашей locXпеременной и ее собственностью.

Это точно так:

var a, b; 
a = 1; 
b = a; 
a = 2; 
console.log(b); // 1, of course 

Назначение a «s значение к b не создавали какой-либо связи между a и b. Точно так же и с объектом.

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

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

var person = (function() { 
 
    var locX = 0; 
 
    return { 
 
    walk: function() { 
 
     locX++; 
 
    }, 
 
    get locX() { 
 
     return locX; 
 
    } 
 
    }; 
 
})(); 
 
snippet.log(person.locX); // 0 
 
person.walk(); 
 
snippet.log(person.locX); // 1
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --> 
 
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

важно понимать, что с помощью функции геттера означает, что person.locX является вызовом скрытого функции.

+0

Спасибо большое за ваши объяснения, я заметил, что вы не использовали "" процитировать ' walk', в чем разница между цитируемым ходом и неуправляемым ходом? –

+0

@XuzhengWang Ничего. Когда ключ объекта не содержит специального символа, кроме подчеркивания, вы можете пропустить кавычки – Tushar

+0

@XuzhengWang: Имя свойства в инициализаторе свойств может быть любым из: 1. Литеральным, который соответствует правилам * IdentifierName * ('walk 'is), 2. строковый литерал (одиночные или двойные кавычки), 3. или числовой литерал. (ES2015 также добавляет вычисленные имена.) Итак, для 'walk' нет никакой разницы, но если вы хотите создать прозвище« walk with me »(обратите внимание на пробелы), вам нужно будет использовать кавычки. Аналогично вам понадобятся кавычки для prop под названием '123abc', потому что это не является допустимым * IdentifierName *. Правила для * IdentifierName * те же, что и для переменных, кроме зарезервированных слов. –

2

person.locX // выход 0 < -------- почему она до сих пор 0

Проблема здесь,

"locX" : locX 

В отличие от getLocX, только значение 0 был скопирован в момент заявления о возврате, а не ссылка locX.

1

Поскольку изменение значения переменной locX не обновляет значение свойства, они не связаны друг с другом.

Возможное решение заключается в использовании Object.defineProperty(), как показано ниже, чтобы мы могли возвращать значение локальной переменной всякий раз, когда запрашивается значение свойства locX.

var person = (function() { 
 
    var locX = 0; 
 
    var obj = { 
 
    "walk": function() { 
 
     locX++; 
 
    }, 
 
    "getLocX": function() { 
 
     return locX; 
 
    } 
 
    } 
 

 
    Object.defineProperty(obj, 'locX', { 
 
    enumerable: true, 
 
    get: function() { 
 
     return locX 
 
    } 
 
    }); 
 

 
    return obj; 
 
})(); 
 

 
snippet.log('locX: ' + person.locX); 
 
snippet.log('getLocX: ' + person.getLocX()); 
 
person.walk(); 
 
snippet.log('walk') 
 
snippet.log('locX: ' + person.locX); 
 
snippet.log('getLocX: ' + person.getLocX());
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --> 
 
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>


Или, как TJ сказал, используя getter

var person = (function() { 
 
    var locX = 0; 
 

 
    return { 
 
    "walk": function() { 
 
     locX++; 
 
    }, 
 
    "getLocX": function() { 
 
     return locX; 
 
    }, 
 
    get locX() { 
 
     return locX; 
 
    } 
 

 
    }; 
 
})(); 
 

 
snippet.log('locX: ' + person.locX); 
 
snippet.log('getLocX: ' + person.getLocX()); 
 
person.walk(); 
 
snippet.log('walk') 
 
snippet.log('locX: ' + person.locX); 
 
snippet.log('getLocX: ' + person.getLocX());
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --> 
 
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

+0

http://jsfiddle.net/arunpjohny/jokmch2u/ –

+0

Для этого вам не нужно использовать 'Object.defineProperty' (хотя вы можете), есть литальный синтаксис getter. –