Why I get the error:

Uncaught TypeError: Cannot read property 'indexOf' of undefined

According to the idea, the code should return the weapon or write that it does not exist, if there is no such in the swords array

var armory = {}; var swords = ["broadsword", "Katana", "Claymore", "Scimitar"]; armory.retrieveSword = function (request) { return (this.swords.indexOf(request) >= 0) ? this.swords.splice(this.swords.indexOf(request), 1)[0] : console.log("No " + request + ", baby"); }; var isKnight = true; var weapon = isKnight && armory.retrieveSword("Katana"); console.log(weapon); 
  • var swords = ... -> armory.swords = ... - Igor
  • Obviously, because this.swords == undefined . But why it is so - from your code is not clear - Kromster

3 answers 3

Because inside the retrieveSword function, this refers to an armory object that does not have the property of this.swords and therefore you have undefined .

Instead

 var swords = ["broadsword", "Katana", "Claymore", "Scimitar"]; 

You need to write

 armory.swords = ["broadsword", "Katana", "Claymore", "Scimitar"]; 

    1) swords is in the global object
    2) this points to armory.retrieveSword

    Honestly speaking, it's hard for me to judge how the code was conceived, but it seems you can do this:

     var armory = function() { this.swords = ["broadsword", "Katana", "Claymore", "Scimitar"]; var self = this; this.retrieveSword = function (request) { return (self.swords.indexOf(request) >= 0) ? self.swords.splice(self.swords.indexOf(request), 1)[0] : console.log("No " + request + ", baby"); }; }; 

    • oh wei, since I changed the way I created the object, I had to add a modified usage example, not to mention the fact that in this case it is not necessary to save this in the constructor. In this case, the problem is not the loss of context - Grundy
    • He has not changed ... - cipher_web
    • Okay, this context has changed in the retrieveSword function! - cipher_web
    • obviously changed: now armory is a function that can be a constructor, in the code in question armory is the object itself, so if you use the function as an object, the code will not work as expected. - Grundy
    • Obviously, it has not changed - as he was referring to armory, it remained so to her - Grundy

    Thanks figured it out. Now the code works as it was intended, namely:

    the code returns the weapon if it is in the swords array, and an error message if the specified weapon is not present - the armory.retrieveSword () method.

     var armory = { swords: ["Broadsword", "Katana", "Claymore", "Scimitar"], addSword: function (swords) { this.swords = this.swords || []; this.swords.push(swords); } }; armory.retrieveSword = function (request) { return (this.swords.indexOf(request) >= 0) ? this.swords.splice(this.swords.indexOf(request), 1)[0] : alert("No " + request + ", baby!"); }; var isKnight = true; var weapon = isKnight && armory.retrieveSword("123"); console.log(weapon);