简体   繁体   English

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

[英]Why is this javascript object property undefined?

I am using an approach described in detail at Dictionary Lookups in Javascript (see the section"A Client-Side Solution") to create an object that contains a property for each word in the scrabble dictionary. 我正在使用一种在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!');
  }


}

(updated code to use an earlier answer from Phil) (更新的代码以使用Phil的较早答案)

I can't figure out why dict.AAH is returning undefined, but the dict object looks fine in the console. 我不知道为什么dict.AAH返回未定义,但是dict对象在控制台中看起来很好。 Screenshots from Firebug below. 下面的Firebug的屏幕截图。

Console: 安慰:

安慰

Drilled down into "Object { }" 深入到“对象{}”

宾语

How can I check a given word ("AAH", in this case) and have it return true if it is a property in the dict object defined as true? 如果它是dict对象中定义为true的属性,如何检查给定单词(在这种情况下为“ AAH”)并使它返回true?

It's probably a race condition. 这可能是比赛条件。 You're loading the dictionary in a GET and then immediately (while the request is being made) those console.log commands are being called (and the one comes back undefined). 您将字典加载到GET ,然后立即(在发出请求时)调用那些console.log命令(并且该命令返回未定义的状态)。 Then the data is actually loaded by the time you debug. 然后,在调试时实际已加载数据。 Everything should be done in a callback or deferred. 一切都应在回调中完成或推迟。 It's an understandable quirk of debuggers that's caught me up before. 这是调试器的一个可理解的怪癖,之前引起我的注意。

You're trying to output dict before it has been populated by the $.get success handler. 您正在尝试在$.get成功处理程序填充dict之前输出dict

Try this: 尝试这个:

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

As another user commented, jQuery's $.when lets you chain such code. 正如另一个用户评论的那样,jQuery的$ .when让您链接这样的代码。

By the way, if all you want to do is know if a word is in the results you can do: 顺便说一句,如果您只想知道结果中是否有单词,您可以执行以下操作:

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');
    }
}

Get ajax requests are asynchronous. 获取ajax请求是异步的。 This means that while the whole operation that occurs in the ajax request is going, javascript keeps reading the next lines. 这意味着在进行ajax请求中的整个操作时,javascript会继续读取下一行。

The problem then is you are logging values that the ajax request did not manage to retrieve early enough. 然后的问题是,您正在记录ajax请求无法尽早检索的值。

To get around the issue you can include the log calls inside your ajax request callback as below 要解决此问题,您可以将日志调用包含在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);
});

//Stuff out here will run whether or not asynchronous request has finished //无论异步请求是否完成,这里的东西都会运行

I WOULD RECOMMEND USING THE WHEN METHOD IN JQUERY FOR THIS TYPE OF SCENARIOS EVEN MORE AS THE BEST SOLUTION 对于这种类型的场景,我建议在JQUERY中使用WHEN方法作为最佳解决方案

HERE IS HOW WHAT I THINK WOULD BE MOST PROPER FOR COMPLEX PROJECTS 对于复杂的项目,我认为这是最合适的方法

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

The problem isn't your code. 问题不在于您的代码。 You have invisible characters in your words, which you fail to clean up. 您的单词中有看不见的字符,您无法清除它们。

You can verify this by using this as your results parser 您可以将其用作结果解析器来验证这一点

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!');
  }

}

And you can fix it by whitelisting your characters. 您可以通过将角色列入白名单来解决此问题。

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!');
  }
}

I would recommend cleaning it up on the server side since running regex on every element in an array as large as seen in your live site might cause performance issues. 我建议在服务器端进行清理,因为在数组中每个元素上运行正则表达式时(如在实际站点中看到的一样大)可能会导致性能问题。

I think the problem lays in that you have dict defined as an object but use it as an array. 我认为问题在于您已将dict定义为对象,但将其用作数组。

Replace var dict = {} by var dict = new Array() and your code should work (tried with your live example on Google Chrome). var dict = {}替换为var dict = new Array() ,您的代码应该可以正常工作(与您在Google Chrome上的实时示例一起试用)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM