0

I've been watching videos and experimenting regarding javascript OOP. But still having no good results when it comes to call() and apply() methods. I want to send a message to a player using a function from a mailman named send() but it is always telling me:

Cannot read property 'call' of undefined

Here is an example:

function Player(name) {
  this.name = name;
  this.inbox = [];
}
Player.prototype.viewInbox = function() {
  return this.inbox;
}
Player.prototype.msgRecieve = function() {
  this.inbox.push({
    to: arguments[0],
    msg: arguments[1]
  });
}

function Mailman(branch) {
  this.branchName = branch;
  this.send = function(to, message) {
    to.msgRecieve.call(arguments);

  }
}

var anthony = new Player('anthony');
var ph = new Mailman('PH');

console.log(anthony.viewInbox()); //[]
ph.send('anthony', 'hello anthony'); //send 
console.log(anthony.viewInbox()); // expecting [object{to:'anthony', msg:'hello anthony'}]

3
  • 3
    'antony' is a string, it doesn't have any 'msgRecieve' property. Commented Nov 13, 2014 at 8:01
  • 1
    anthony on the other hand (as opposed to 'anthony') is a Player object and will have the msgReceive property. Commented Nov 13, 2014 at 8:02
  • 2
    FWIW: It's "receive", not "recieve" ("'i' before 'e' except after 'c' or when sounded as 'a' as in neighbour and weigh"). Commented Nov 13, 2014 at 8:14

1 Answer 1

3

The first argument to call should be the value that this should have during the function call; in the above, you want it to be to. Then you list the arguments discretely, or you use apply instead and use an array (or an arguments object). In this case, you just want to pass in message because you're using to, so:

to.msgRecieve.call(to, message);

call uses the first argument you give it as this within the function it calls, and passes the function it calls any further arguments you give it. So for instance:

foo.call(something, 'a', 'b', 'c');

...will call foo, and during the call to foo this will be something and foo's arguments are 'a', 'b', and 'c'.

There's also apply, which is exactly the same except you give it the arguments for the function as an array (or as an arguments object):

foo.apply(something, ['a', 'b', 'c']);

There are a couple of other problems, though. As destroy points out, you've also used 'anthony', a string, rather than anthony, your variable. Then in send, you want to get name from to (or better yet, do it in msgRecieve.

function Player(name) {
  this.name = name;
  this.inbox = [];
}
Player.prototype.viewInbox = function() {
  return this.inbox;
}
Player.prototype.msgRecieve = function(msg) {
  this.inbox.push({
    to: this.name,   // <=== Change
    msg: msg         // <=== Change
  });
}

function Mailman(branch) {
  this.branchName = branch;
  this.send = function(to, message) {
    to.msgRecieve.call(to, message);  // <=== Change
  }
}

var anthony = new Player('anthony');
var ph = new Mailman('PH');

snippet.log(JSON.stringify(anthony.viewInbox())); //[]
ph.send(anthony, 'hello anthony'); //send // <=== Change
snippet.log(JSON.stringify(anthony.viewInbox())); // expecting [object{to:'anthony', msg:'hello anthony'}]
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Sign up to request clarification or add additional context in comments.

5 Comments

@loki9: I've updated to explain call and apply a bit more.
Thank you very much! i'll use this as my reference. :)
@T.J.Crowder Why did ECMA implement two different methods call and apply just differing by the way we provide arguments list?
@sabithpocker: First off, thank you again for another good edit. I really should drink my coffee before answering questions. :-) I don't know why Netscape (probably Eich himself) did that, but it's really convenient, so it's probably the reason for it. When you need to call another function with all of the arguments you were given, otherFunc.apply(this, arguments); is really handy. When you need to send discrete arguments, otherFunc.call(this, arg, arg2) is handy. We could have got by with just apply, but in the early days, creating the array might have been costly.
@T.J.Crowder Convenience looks like a good reason, thank you for that explanation. I will drop a mail for sure, always a big fan of your's :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.