4

I am currently in the mist of reading Addy Osmani's JavaScript Design Patterns which can be found here: http://addyosmani.com/resources/essentialjsdesignpatterns/book/.

I am finding it quite enjoyable and very helpful. I do have a question about one of the patterns in the book, namely the Command Pattern.

In the book, Addy explains the Command Pattern is helpful to decouple objects and method calls a little better.

Here is my version of his example:

var person = {
    sayName: function (name) {
        return "My name is " + name;
    },
    sayAge: function (age) {
        return "My age is " + age;
    },
    sayGender: function (gender) {
        return "My gender is " + gender;
    }
}
person.execute = function (name) {
    return person[name] && person[name].apply(person, [].slice.call(arguments, 1));
}
console.log(person.execute("sayName", "Sethen"));

The magic is done in the execute method. As you can see, you pass the method name and arguments and the method takes care of the rest.

My confusion stems from what the execute method is actually returning. When you look at it, it looks like a short circuit with the && which I always thought returned a boolean due to JavaScript conversion.

However, if you try the code it works exactly as it should, logging My name is Sethen.

Furthermore, I've found that simply using return person[name].apply(person, [].slice.call(arguments, 1); produces the same results and in my mind much easier to read.

So, my question is how the return works in the original execute method:

return person[name] && person[name].apply(person, [].slice.call(arguments, 1));

and how the && operator works in this instance to make it work??

Sethen
  • 11,140
  • 6
  • 34
  • 65
  • 2
    Sorry but could you try to make the question more concise, is the only important part that last line you wrote – aaronman Jul 19 '13 at 17:43
  • 1
    See: http://stackoverflow.com/questions/5049006/using-s-short-circuiting-as-an-if-statement. That could even be a duplicate. – Andrew Whitaker Jul 19 '13 at 17:44
  • possible duplicate of [Do the && and || operators convert their operands to booleans?](http://stackoverflow.com/questions/7601962/do-the-and-operators-convert-their-operands-to-booleans) – Bergi Jul 19 '13 at 17:46
  • 1
    Interesting that this pattern will return `undefined` when you try to execute a method that doesn't exist as opposed to throw an exception. – go-oleg Jul 19 '13 at 17:47
  • `execute` is very nearly useless here. Since properties can be looked up dynamically, you can easily say like `person['sayName']('Sethen');`. – cHao Jul 19 '13 at 17:48
  • @cHao Perhaps the benefit comes from not writing the `execute` function like this, rather, writing a set of methods in an object called `methods` and than creating a lot of different objects with values that those methods can act upon. That seems more valuable to me. – Sethen Jul 19 '13 at 17:51
  • @SethenMaleno: So, in essence, turning objects into data to be acted on, rather than data that acts on its own. You know that's basically a step backwards from OOP, right? – cHao Jul 19 '13 at 17:52
  • @cHao I guess I am not sure how that is a step backwards. Seems like it would be pretty useful to me. – Sethen Jul 19 '13 at 17:53
  • It's a step backwards in that the data and the behavior have been divorced. One of the main things about OOP is that objects have their own behavior, their own interface, and their own rules about how they work. Once you have methods in some other class that act on the values, and the object just finds a method by name and runs it blindly, you've pretty much thrown out encapsulation. If all the methods are in one object and are shared by everyone, you've tossed out inheritance. And without the ability for an object to override `sayName`, you've lost polymorphism. – cHao Jul 19 '13 at 18:01
  • Come to think of it, it sounds like pretty much the *opposite* of OOP. – cHao Jul 19 '13 at 18:04
  • @cHao Ahh, okay. So, what about this example, you believe this would be a step back: http://jsfiddle.net/Eay4g/ ... To me, this seems like what the command pattern is doing, except it doesn't belong to the `person` object like above, it's just a function that calls an object and the method with some arguments. – Sethen Jul 19 '13 at 18:04
  • @cHao Really what I am trying to do is understand this patterns place in JavaScript, because I tend to agree with you. Why use this if we can look up things dynamically?? – Sethen Jul 19 '13 at 18:14
  • 1
    That's not the Command pattern. Check out http://jsfiddle.net/eAyCF/1/ for an example -- and an explanation of why JS doesn't need it. – cHao Jul 19 '13 at 18:18
  • @cHao Ahh, I see. So, really the only difference between our examples is you are returning a function in your `command` function and invoking it later, rather than immediately. Also, I can see how in your example why the command pattern isn't useful. – Sethen Jul 19 '13 at 18:23
  • 1
    @SethenMaleno: Yep. Encapsulating an action to potentially be performed later is basically the whole point of the Command pattern. And once functions can be values, the pattern's no longer useful -- instead of having a command object, you just use a closure. – cHao Jul 19 '13 at 18:32
  • @cHao I appreciate the lesson. Thanks for all of this! – Sethen Jul 19 '13 at 18:33
  • I don't think Andy describes the best implementation of the classical Pattern which you can find here https://en.wikipedia.org/wiki/Command_pattern#JavaScript – Alex P. Sep 10 '15 at 11:42

2 Answers2

6

The && operator does not always return boolean. It returns the value of the last subexpression it evaluates. If the requested method name exists, then that expression will return the result of the .apply() call.

So:

return person[name] && person[name].apply(person, [].slice.call(arguments, 1));

means:

if (!person[name])
  return person[name];

return person[name].apply(person, [].slice.call(arguments, 1));
Pointy
  • 405,095
  • 59
  • 585
  • 614
  • So, essentially the first part just checks to make sure that the method name actually exists?? – Sethen Jul 19 '13 at 17:46
  • @SethenMaleno yes, exactly. (Well, strictly speaking, the method name could exist as a property of the "person" object, but if its value doesn't look "truthy" then the test fails. For the purpose of the example, of course, it's checking to make sure the method exists.) – Pointy Jul 19 '13 at 17:47
  • 3
    @aaronman the behavior of `&&` and `||` are some of the smartest design decisions in the language, in my opinion :) They're so much more useful than (for example) the Java version. – Pointy Jul 19 '13 at 17:48
  • yeah, if it weren't for leaky assignments, you'd have to do defaults with a ternary, like in other languages. && allows single-expression queries, which are incredibly fast: return a && a.prop=='ok' && a; – dandavis Jul 19 '13 at 18:06
1

In this case the && is acting sort of like an if statement.

If you were to pass in something that was not a method on that object it would be false, and not continue to execute the rest of the statement.

Morgan ARR Allen
  • 10,556
  • 3
  • 35
  • 33