Почему эта переменная сохраняется без переменной внутри функции не глобальной? - PullRequest
1 голос
/ 27 октября 2011

Этот вопрос касается аналогичной проблемы области видимости javascript, которую я задал вчера . Я надеюсь, что вы можете помочь мне решить эту проблему.

Я работаю с расширением Chrome. options.html сохраняет в localStorage новое электронное письмо пользователя как «user» и вызывает refreshUser() функцию в background.html:

//save entered gmail address
document.getElementById("save").addEventListener(
    "click", function ()
    {
        var user = document.getElementById("getEmail").value;
        localStorage.setItem("user", user);
        chrome.extension.getBackgroundPage().refreshUser();
    } , false)

Затем я сохраняю письмо как «newUser» в background.html. Проблема в том, что newUser обновляется внутри refreshUser(), но null снаружи refreshUser():

newUser = localStorage.getItem("user");
console.log("first newUser " + newUser);
//newUser=null

function refreshUser () 
{
    newUser = localStorage.getItem("user");
    console.log("newUser inside of refreshUser function " + newUser);
    //newUser is updated with saved email in localStorage
}

console.log("newUser after refreshUser() " + newUser);
//newUser=null

Почему newUser локально по отношению к refreshUser(), хотя оно определено без ключевого слова var? Спасибо за вашу помощь!

Обновление

В ответ на ответ pimvdb Я копирую код для моего background.html. Если я хочу использовать newUser в formData, как указано, какую функцию мне нужно вызывать внутри refreshUser()? Спасибо.

<html>
<script>

newUser = localStorage.getItem("user");
console.log("first newUser " + newUser);

function refreshUser () 
{
    newUser = localStorage.getItem("user");
    console.log("newUser inside of refreshUser function " + newUser);
}

console.log("newUser after refreshUser() " + newUser);

//I want to user newUser below in formData  
chrome.browserAction.onClicked.addListener(function(tab) 
{
    chrome.tabs.getSelected(null, 
    function(tab) 
    {
        // Send a request to the content script.
        chrome.tabs.sendRequest(tab.id, {action: "getDOM"}, 
        function(response) 
        {
            var firstParagraph = response.dom;

            var formData = new FormData();
            formData.append("url", tab.url);
            formData.append("title", tab.title);
            formData.append("pitch", firstParagraph);
            formData.append("extension_user", "abc@gmail.com");
            //I want to user newUser here:
            //formData.append("extension_user", newUser);
            console.log("newUser inside formData: " + newUser)

            var xhr = new XMLHttpRequest();
            xhr.open("POST", "http://ting-1.appspot.com/submithandlertest", true);
            xhr.onreadystatechange = 
            function (aEvt) 
            {
                if (xhr.readyState == 4) 
                {
                    if (xhr.status == 200)
                    { 
                        console.log("request 200-OK");
                        chrome.browserAction.setBadgeText ( { text: "done" } );
                        setTimeout(function () 
                        {
                            chrome.browserAction.setBadgeText( { text: "" } );
                        }, 2000);
                    }
                    else
                    {
                        console.log("connection error");
                        chrome.browserAction.setBadgeText ( { text: "ERR" } );
                    }        
                }        
            };
            xhr.send(formData);
        }); //chrome.tabs.sendRequest
    });
});


</script>
</html>

Обновление до ответа Комментарий pimvdb :

Проблема, с которой я столкнулся, заключается в том, что background.html загружается при открытии браузера, но электронная почта сохраняется в options.html впоследствии. Так что refreshUser() говорит background.html получить newUser от localStorage. Затем мне нужно использовать "newUser" в formData, как это:

formData.append("extension_user", newUser);

Но то, как у меня сейчас "newUser" снаружи refreshUser(), равно нулю. Чего мне не хватает?

Обновление, чтобы уточнить, почему некоторые журналы не отображаются в консоли

Вот что я делаю:

1. I reload the extension and start with localStorage empty
2. I use the extension to save a bookmark
3. all 3 logs are null as expected

 first newUser null
 newUser after refreshUser() null
 newUser inside formData: null
 request 200-ok

4. now I save user email in options as abc@gmail.com
5. now I use the extension again to save a bookmark
6. now refreshUser is executed and the log inside the function says abc@gmail.com and formData log says abc@gmail.com

newUser inside of refreshUser function abc@gmail.com
newUser inside formData: abc@gmail.com
request 200-OK

7. but what confuses me is that now the first 2 logs do not show in the console. Why?

Ответы [ 4 ]

2 голосов
/ 27 октября 2011

Вы не вызвали refreshUser () в опубликованном вами фрагменте, поэтому он не будет установлен.

Попробуйте позвонить, , затем проверка глобального newUser.

2 голосов
/ 27 октября 2011

Это глобально, но вы обращаетесь к нему не в то время.

function refreshUser () { ... } - это просто объявление функции; ничто действительно не выполнено. Оба журнала за пределами этого объявления запускаются немедленно, и в этот момент элемент localStorage не был установлен (то есть null).

Ваша формулировка "newUser after refreshUser ()" довольно неоднозначна. Он действительно выполняется после объявления, но newUser не изменился вообще, поэтому оба журнала выходят за пределы журнала функций null. Вы не можете получить к нему доступ в то время, когда он еще не установлен, как вы, вероятно, ожидаете.

Следующее должно хорошо регистрироваться, так как глобальная переменная была обновлена. Просто назовите его после , установив его внутри refreshUser.

function otherFunction() {
    // logs the global variable 'newUser', which is thus indeed global
    console.log("newUser inside otherFunction: " + newUser);
}

function refreshUser () 
{
    newUser = localStorage.getItem("user");
    otherFunction();
}
1 голос
/ 27 октября 2011

Я просто хочу прокомментировать практику определения переменных, но это слишком долго для комментария.

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

var globalObject = this,
    globalVariable = 1; //or globalObject.globalVariable = 1;

function example(){
var globalVariable;

globalVariable = 2 //This will not set the global variable and you can see it's not intended either since we used var
console.log( globalObject.globalVariable ); 
globalObject.globalVariable = 2 // This will set the global variable, the intent to do so is very explicitly shown
console.log( globalObject.globalVariable ); 
}

example();
//1
//2
console.log( globalObject.globalVariable, globalVariable );
//2 2
1 голос
/ 27 октября 2011

Я думаю, что предыдущий ответ уместен: Какова область видимости переменных в JavaScript?

Попробуйте объявить переменную с var в глобальном контексте.

...