Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/86.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript闭包&;可变范围_Javascript_Jquery_Closures_Scope - Fatal编程技术网

JavaScript闭包&;可变范围

JavaScript闭包&;可变范围,javascript,jquery,closures,scope,Javascript,Jquery,Closures,Scope,我很难理解JS中闭包和变量范围的概念。具体地说,如何访问类中的深度嵌套的styleData变量,然后访问从该类创建的对象 我肯定我这里还有一些其他的错误,所以请插进来,在你认为合适的地方纠正我。谢谢 var BuildJSON = { convert: function() { $.ajax({ type: "GET", url: "style2.xml", dataType: "xml",

我很难理解JS中闭包和变量范围的概念。具体地说,如何访问类中的深度嵌套的
styleData
变量,然后访问从该类创建的对象

我肯定我这里还有一些其他的错误,所以请插进来,在你认为合适的地方纠正我。谢谢

var BuildJSON = {
    convert: function() {
        $.ajax({
            type: "GET",
            url: "style2.xml",
            dataType: "xml",
            success: function(xml) {
                var styleData = $.xml2json(xml);
                return styleData; // Do I need to return this somehow?
            }
        //How to get access to styleData??
        });                 
    },

    styleData: this.convert();
};

var myClass = function() {
    this.info = BuildJSON.styleData;
};

var myObject = new myClass;

alert(myObject.info.Style[0].name);

JavaScript中的闭包是函数,因此在函数范围内声明的任何内容都只能在该函数内可见

在您的示例中,
styleData
是本地的,它属于
success
函数,不能在其他任何地方访问。最简单的解决方案是在
BuildJSON
范围的顶部声明该变量,在这种情况下,由于您将该对象声明为对象文本,因此可以将其初始化为该对象的属性:

this.styleData = '',

...

success: function(xml) {
  BuildJSON.styleData = $.xml2json(xml);
}
这种方法的“问题”在于
styleData
是公共的,而这可能不是您想要的。如果您想在BuildJSON中使用该变量,但不想让它公开访问,那么模块模式将起到帮助作用

var BuildJSON = (function(){
  var styleData = '', // local
      convert = function(){ ... } // You can use style data here

  return {
    convert: convert // Return only stuff you want to be public
  }
}())

我想说,这里的大问题更多地是关于AJAX调用的异步编程DU,而不是回调本身

您可以做的一件事就是从ajax回调显式地设置styleData。注意如何从内部作用域访问和修改外部作用域中的“that”变量

var BuildJSON = {
   convert: function() {
        var that  = this; // inner callbacks get separate "this" 
                          // variables so we save the BuildJSON in a separate variable.
        $.ajax({
            type: "GET",
            url: "style2.xml",
            dataType: "xml",
            success: function(xml) {
                that.styleData = $.xml2json(xml);
            }
        });                 
    }
};
BuildJSON.convert();
虽然这样做很简单,但它有一个缺点,即只允许您在converts完成运行后读取“styleData”属性,并且您编写代码的方式无法知道ajax调用已经完成(其他方法是使用setinterval轮询styleData变量,但这很愚蠢)

从异步函数“返回”内部值有两种主要方法。一种方法是像$.ajax本身那样,将函数转换为延续传递样式。这样,当您完成styleData的计算时,您将收到一个函数来调用它,而不是返回styleData结果

convert: function( onStyleData ) {
    $.ajax({
        // ...
        success: function(xml) {
            var styleData = $.xml2json(xml);
            onStyleData( styledata ); // <---
        }
    });                 
};

BuildJSON.convert(function(styledata){
    console.log('got styledata', styledata)
})

变量
myObject
BuildJSON
是否预先声明?在什么之前?BuildJSON是一个对象文字,myObject是从myClass创建的新对象,对吗?在上面发布的代码之前。如果这两个变量第一次出现在上面的代码中,您必须在它们前面放置一个
var
,如:
var BuildJSON={…
var myObject=…
这里的一个问题是样式数据是通过Ajax检索的,因此
警报(myObject.info.style[0].name);
将始终抛出,因为实例是在同一调用堆栈中创建的,而Ajax响应处理程序还无法执行。如果要使用Ajax响应中的样式数据,必须从Ajax响应处理程序中执行。
var styleDataPromise = dojo.xhr({
    url: /*...*/,
    load: function(data){
       return xmlToJSON(xml);
    }
})

styleDataPromise.then(function(styleData){
    console.log('got styledata', styleData)
})