Eloquent Javascript:Uncaught TypeError:无法读取未定义的属性'indexOf'

时间:2015-06-25 17:14:54

标签: javascript

  1. 我正在学习基于Eloquent Javascript的JavaScript,在其中一章中遇到了这个错误。不知道我在这里做错了什么。我收到错误“无法读取未定义的属性'indexOf'对代码return journal.events.indexOf(event) != -1

  2. 此外,有人可以解释这条线是如何工作的吗?是不是IndexOf应该返回指定值出现的第一个位置(在这种情况下,事件)?但我在书中看到,行return journal.events.indexOf(event) != -1;返回true或false。

    var journal = [];
    
    function addEntry(events, didITurnIntoASquirrel) {
        journal.push({
            events: events,
            squirrel: didITurnIntoASquirrel
        });
    }
    
    addEntry(["work", "touched tree", "pizza", "running",
              "television"], false);
    addEntry(["work", "ice cream", "cauliflower", "lasagna",
              "touched tree", "brushed teeth"], false);
    addEntry(["weekend", "cycling", "break", "peanuts",
              "beer"], true); 
    
    function hasEvent(event, entry) {
        return entry.events.indexOf(event) != -1;
    }
    
    console.log(hasEvent("pizza", journal));
    

3 个答案:

答案 0 :(得分:3)

在示例代码journal中是一个数组

  var journal = []; <--- Array

因此,events应使用 索引 进行访问:

journal[0].events.indexOf(event)

        ^
        |
        |

在这里,您需要找到正确的索引来获取您的活动

答案 1 :(得分:2)

I'm unsure how far along you are with learning javascript, so forgive me if some of this sounds condescending or obvious.

Let's break this down one step at a time. You begin with an empty array.

var journal = [];
console.log(journal); //[]  
//it's defined. It's an empty Array.

By calling push on an array, you add something to the end of the array. More on Array.push.

I don't like this example for beginners because it expects you to know already that you can define an object while you're passing it as an argument. This is done this way because you don't truly need a variable reference to an object that's only used once and is therefore a good way of reducing bloat in code. But verbosity is much better when teaching someone, imho.

//Wait, what am I pushing into the journal array?
journal.push({
   events: events,
   squirrel: didITurnIntoASquirrel
});

This should make more sense: Create an object first. Then add that object to the "journal" array. function addEntry(events, didITurnIntoASquirrel) { var temporaryObject = { events: events, squirrel: didITurnIntoASquirrel }; journal.push(temporaryObject); }

Now journal is an array with an unnamed object at its first index.

   1. console.log(journal); // [temporaryObject]
   2. console.log(journal[0]); - //temporaryObject

The visibile difference is the lack of parens, but the difference is important. On line 1 you have the array itself, on line 2 you have what's inside it (i.e. the object). You need to get the object (via the technique on line 2) before you can access properties of that object, such as "events" or "squirrel". Moving on.

addEntry(["work", "touched tree", "pizza", "running", "television"], false);

Next, we invoke the addEntry function. Same confusion here. I've rewritten it slightly to make the arguments more understandable.

var entry = ["work", "touched tree", "pizza", "running", "television"];
addEntry(entry, false);
//repeat 2 more times with different data

So first we define an array, then we pass it to the addEntry function. when the addEntry function runs (it will run right when we invoke it), the "entry" argument will be represented function as the "events" parameter (simple way: events = entry and didITurnIntoASquirrel = false). some notes on parameters vs arguments.

So you should be able to understand now that you're passing an array and a boolean to the addEntry function. That function creates an object based on those values referencing them via their parameters. That object is then added to the journal array.

What you end up with is 4 levels of depth. You have an array called journal, which has objects in it. Those objects have a property called events, which is a different array. That array has several strings inside it. To access the events array and use indexOf to see if it has a given string in it, you need to traverse that depth one level at a time.

//journal is the array, journal[0] is the object, journal[0].events is the property of that object
console.log(journal[0].events) //["work", "touched tree", "pizza", "running", "television"].

Note this is the same data that we originally put in the entry variable. This may seem unnecessarily complicated, but trust me when I say this type of structure is useful in real life when you need to manage data hierarchy or other logical relationships between "things" in Object Oriented programming.

Now, all the work we've done so far is to add to the journal array. We now want a function to see what's inside it. Why a function? So you don't have to rewrite the same code over and over.

function hasEvent(event, journal) {
    return journal.events.indexOf(event) != -1;
}

By now I hope you can spot the error in this function. journal.events doesn't work, because journal is an array, not an object (you skipped a level, and your computer isn't smart enough to know what you mean) journal[0].events would work, because you are telling javascript ("from the journal array, I want the object in the first slot, and the events property of that object").

The simplest fix is to send journal[0] to the hasEvent function instead of journal. Beware, this will only check journals first index. Realistically you'd want a for loop inside the hasEvent function or wrapping the call to that function to check all indexes. For now we will hardcode them, since we know there are 3, but its not a good idea in real life, since later there may be more than 3 entries in the journal).

This funciton is returning the result of calling indexOf() (some number or -1) with -1. Let's again rewrite it so that it makes more sense.

New hasEvent function:

//I renamed the variable so it makes more sense what it really is. It's the object, not the journal array.
function hasEvent(event, journalEntry) {
    var index = journalEntry.events.indexOf(event);
    var result = (index != -1); //true if it was found, false if it wasn't found.
    return result; //a boolean based on the above comparison.
}

//Ack! My kingdom for a "for loop". Don't worry about that right now.
console.log(hasEvent("pizza", journal[0]));
console.log(hasEvent("pizza", journal[1]));
console.log(hasEvent("pizza", journal[2]));

TL;DR Here is a fiddle with working code: http://jsfiddle.net/o8dg1ts6/1/

答案 2 :(得分:0)

回答你的第二个问题:

&#34;不是IndexOf应该返回指定值的第一个出现位置&#34;

是的,如果数组中的值不是indexOf将返回-1。

因此,如果找到 事件,则表达式indexOf(event) != -1将评估为true