为什么这个javascript对象属性未定义?

时间:2012-09-15 17:06:47

标签: javascript jquery object

我正在使用Dictionary Lookups in Javascript中详细描述的方法(请参阅“客户端解决方案”一节)来创建一个对象,该对象包含拼字游戏字典中每个单词的属性。

var dict = {};

//ajax call to read dictionary.txt file
$.get("dictionary.txt", parseResults);


function parseResults(txt) {
var words = txt.split( "\n");

  for (var i=0; i < words.length; i++){
      dict[ words[i] ] = true;
  }

  console.log(dict.AAH);
  console.log(dict);

  if (dict.AAH == true) {
     console.log('dict.AAH is true!');
  }


}

(使用Phil先前回答的更新代码)

我无法弄清楚为什么dict.AAH返回undefined,但dict对象在控制台中看起来很好。屏幕截图来自下面的Firebug。

控制台:

console

深入研究“对象{}”

Object

如何检查给定的单词(在这种情况下为“AAH”),如果它是dict对象中定义为true的属性,则返回true?

5 个答案:

答案 0 :(得分:1)

这可能是竞争条件。您正在GET中加载字典,然后立即(在发出请求时)调用那些console.log命令(并且返回未定义的命令)。然后,在您调试时实际加载数据。一切都应该在回调或延期中完成。这是一个可以理解的调试器的怪癖,之前引起了我的兴趣。

答案 1 :(得分:1)

您尝试在dict成功处理程序填充之前输出$.get

试试这个:

// If the browser doesn't have String.trim() available, add it...
if (!String.prototype.trim) {
    String.prototype.trim=function(){return this.replace(/^\s\s*/, '').replace(/\s\s*$/, '');};

    String.prototype.ltrim=function(){return this.replace(/^\s+/,'');};

    String.prototype.rtrim=function(){return this.replace(/\s+$/,'');};

    String.prototype.fulltrim=function(){return this.replace(/(?:(?:^|\n)\s+|\s+(?:$|\n))/g,'').replace(/\s+/g,' ');};
}

/**
 * Parses the response returned by the AJAX call
 *
 * Response parsing logic must be executed only after the
 * response has been received. To do so, we have to encapsulate
 * it in a function and use it as a onSuccess callback when we
 * place our AJAX call.
 **/
function parseResults(txt) {
    // clean the words when we split the txt
    var words = txt.split("\n").map($.trim);

    for (var i=0; i < words.length; i++){
        dict[ words[i] ] = true;
    }

    console.log(dict.AAH);
    console.log(dict);

    if (dict.AAH == true) {
       console.log('dict.AAH is true!');
    }
}

// global object containing retrieved words.
var dict = {};

//ajax call to read dictionary.txt file
$.get("dictionary.txt", parseResults);

正如另一位用户评论的那样,jQuery的$.when允许你链接这样的代码。

顺便说一句,如果您想要做的就是知道结果中是否有单词,您可以这样做:

function parseResults(txt) {
    // clean the words when we split the txt
    var words = txt.split("\n").map($.trim);

    if ($.inArray('AAH', words)) {
        console.log('AAH is in the result set');
    }
}

答案 2 :(得分:1)

获取ajax请求是异步的。这意味着当ajax请求中发生的整个操作进行时,javascript会继续读取下一行。

问题是您正在记录ajax请求无法及早检索到的值。

要解决此问题,您可以在ajax请求回调中包含日志调用,如下所示

var dict = {};

//ajax call to read dictionary.txt file
$.get("dictionary.txt", function( txt ){
    var words = txt.split( "\n");

    for (var i=0; i < words.length; i++){
        dict[ words[i] ] = true;
    }

    //Now inside these console.log will run once you DO have the data
    console.log(dict.AAH);
    console.log(dict);
});

//无论异步请求是否已完成,此处都会运行

我建议在这种类型的场景中使用方法,而不是最好的解决方案

这就是我认为对于复杂项目最合适的方式

var dict = {};

//ajax call to read dictionary.txt file
function getDictionary(){
    return $.ajax("dictionary.txt");
}

/*I recommend this technique because this will allow you to easily extend your 
code to maybe way for more than one ajax request in the future. You can stack 
as many asynchronous operations as you want inside the when statement*/

$.when(getDictionary()).then(function(txt){//Added txt here...forgot callback param before

   var words = txt.split( "\n");

    for (var i=0; i < words.length; i++){
        dict[ words[i] ] = true;
    }

    //Now inside these console.log will run once you DO have the data
    console.log(dict.AAH);
    console.log(dict);
});

答案 3 :(得分:1)

问题不在于您的代码。你的单词中有隐形字符,你无法清理它们。

您可以将此作为结果解析器进行验证

function parseResults(txt) {
  // clean the words when we split the txt
  var words = txt.split("\n")
                 .map($.trim)
                 .splice(0,3); // Keep only 3 first ones

  if(btoa(words[2]) !== btoa('AAH')){ // Compare in Base64
    console.log('YOU HAVE HIDDEN CHARS!');
  }

}

你可以通过将你的角色列入白名单来修复它。

function parseResults(txt) {
  // clean the words when we split the txt
  var words = txt.split("\n").map(function(el){
    return el.match(/[a-zA-Z0-9]/g).join('');
  });

  for (var i=0; i < words.length; i++){
      dict[ words[i] ] = true;
  }

  console.log(dict.AAH);
  console.log(dict);

  if (dict.AAH == true) {
     console.log('dict.AAH is true!');
  }
}

我建议在服务器端进行清理,因为在阵列中的每个元素上运行正则表达式都会像在实际站点中看到的那样大,这可能会导致性能问题。

答案 4 :(得分:0)

我认为问题在于您将dict定义为对象,但将其用作数组。

var dict = {}替换为var dict = new Array(),您的代码应该有效(尝试使用Google Chrome上的实际示例)。