来自JS中的函数内的全局变量问题

时间:2017-09-11 07:16:36

标签: javascript

我有以下脚本:

    <script>
                var xmlhttp = new XMLHttpRequest();
                var myApp = angular.module("myApp", []);

                xmlhttp.onreadystatechange = function () {
                    if (this.readyState == 4 && this.status == 200) {
                        response = this.responseText;
                        var myObj = JSON.parse(response);
                        console.log(myObj);

                    }
                };

                xmlhttp.open("GET", "functions.php?action=getuserdata&id=" + document.getElementById('userID').innerHTML, true);
                xmlhttp.send();

                console.log(myObj);

                myApp.controller("myCtrl", function ($scope) {
                    $scope.firstName = myObj[0].firstname;
                    $scope.lastName = myObj[0].lastname;
                    $scope.email = myObj[0].email;
                    $scope.cell = myObj[0].cell;
                    $scope.domainname = myObj[0].domainname;
                    $scope.tfamethod = myObj[0].tfamethod;
                    $scope.said = myObj[0].said;
                });
    </script>

现在我的理解是&#39; var&#39;关键字,全局分配一个可从窗口内的任何位置访问的变量。我在onreadystatechange函数中设置了var,并且在执行第一个console.log时我能够看到它,但我得到的是&#39; undefined&#39;当我在功能外再次登录时。我对var的理解不正确吗?如果是这样,我如何修复代码以便能够从函数外部访问myObj?

4 个答案:

答案 0 :(得分:3)

该代码有两个问题:

var

  

现在我的理解是'var'关键字,全局分配一个可从窗口内的任何位置访问的变量。

这种理解是不正确的。 varvar出现的函数中声明一个变量。要声明一个全局变量,请在所有函数之外声明它。

或者更好,不要。浏览器上的全局命名空间非常拥挤。相反,将所有代码包装在作用域函数中并将“全局变量”放在那里。它们可以被所有代码访问,而不是实际上是全局的。

时序

另外:您不能在代码中使用myObj,因为它不会被分配,无论它在何处声明。有关原因,请参阅this question's answers

所以这是带有作用域函数的代码,并在正确的位置使用myObj回调中);此外,由于您只使用返回数组中的第一个条目,因此您可以访问该条目一次而不是重复:

(function() {
    var xmlhttp = new XMLHttpRequest();
    var myApp = angular.module("myApp", []);

    xmlhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            response = this.responseText;
            var myObj = JSON.parse(response)[0];           // Note the [0]
            myApp.controller("myCtrl", function($scope) {
                $scope.firstName = myObj.firstname;
                $scope.lastName = myObj.lastname;
                $scope.email = myObj.email;
                $scope.cell = myObj.cell;
                $scope.domainname = myObj.domainname;
                $scope.tfamethod = myObj.tfamethod;
                $scope.said = myObj.said;
            });
        }
    };

    xmlhttp.open("GET", "functions.php?action=getuserdata&id=" + document.getElementById('userID').innerHTML, true);
    xmlhttp.send();
})();

答案 1 :(得分:0)

  

用var声明的变量的范围是它的当前执行上下文,它是封闭函数,或者对于在任何函数外部声明的变量,是全局的。

来源:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var

因此,如果在函数内部声明变量,则无法在此函数外部访问它。

固定代码:

var myObj;
xmlhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
        response = this.responseText;
        myObj = JSON.parse(response);
        console.log(myObj);

    }
};

xmlhttp.open("GET", "functions.php?action=getuserdata&id=" + document.getElementById('userID').innerHTML, true);
xmlhttp.send();

console.log(myObj);

答案 2 :(得分:0)

用var定义的变量具有功能上下文。它们首先在功能上提升,仅可从功能体上获得。如果要从外部访问变量,首先在外部定义并访问函数内部。只有未定义的变量才具有全局范围。

答案 3 :(得分:0)

我认为您需要了解变量范围的工作原理。 MDN做得很好解释

但长话短说。如果你想创建一个糟糕的“全局”变量,它将与你的第二个console.log()

在同一个块中

所以这段代码会被重构为。

//Global variable
var myObj;
xmlhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
   response = this.responseText;
   myObj = JSON.parse(response);
   console.log(myObj);

    }
};

xmlhttp.open("GET", "functions.php?action=getuserdata&id=" + document.getElementById('userID').innerHTML, true);
            xmlhttp.send();
// Probably will log incorrectly because of the timing, 
// This code is ran before the callback of the XHR, because the
// javascript interpreter wont wait for that callback to finish before 
// interpreting additional code (Which is good cause then the UI 
// doesn't pause while the request is being performed 
 console.log(myObj); 

我会再给你一个例子

  var foo = 1;
    function log(){
       var bar = 2
       baz = 4
       console.log(foo); // 1
       console.log(bar) // 2
       console.log(baz) // 3
    }


   console.log(foo); // 1
   console.log(bar) // undefined
   console.log(baz) // 3

另外我注意到你正在使用angularJS,但是你正在编写超级详细的XHR请求,我建议你查看HTTP服务。