1

我很难理解 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);
4

2 回答 2

3

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
  }
}())
于 2012-07-22T23:31:48.180 回答
0

我想说这里的大问题更多是关于 AJAX 调用的异步编程,然后是回调本身。

您可以做的一件事就是从 ajax 回调中显式设置 styleData。请注意如何从内部范围访问和修改外部范围的“那个”变量。

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();

虽然这很容易做到,但它的缺点是您只能在转换完成运行后读取“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)
})

另一种可能性是利用 JQuery 中的承诺支持。诸如 ajax 之类的函数返回特殊的 Promise 对象,使异步编程更加方便(因为您可以编写代码返回值并使用“return”而不是被迫进行手动 CPS。

我真的不知道他们在 JQuery 中为此使用的名称,但在 Dojo 工具包中它看起来有点像

var styleDataPromise = dojo.xhr({
    url: /*...*/,
    load: function(data){
       return xmlToJSON(xml);
    }
})

styleDataPromise.then(function(styleData){
    console.log('got styledata', styleData)
})
于 2012-07-22T23:44:19.230 回答