JavaScript OMG #21 to #25

The Blurb: This is mostly just a bit of fun and in form of some rough notes as I’ve been sticking my head into a few JavaScript books and thought I’d write down what strikes me as odd/interesting along the way. Of course, I’ve written some bits of JavaScript but I’ve never really sat down and read up on it. I’m not trying to be definitive and nor am I trying to take a particular view – just poking around Smile

OMG #21 – Everything’s a Function

There’s a piece of code in Crockford’s book that I had to read about 5 times. He (very tersely) defines a new method on all functions called method (this is his code below);

Function.protoype.method = function(name, func) 
  {
    this.prototype[name] = func;
    return(this);
  };

because it’s altering the prototype for Function I read that as adding a method (called method) to every Function object and that new method knows how to add another method of a given name and implementation to the prototype. Wow.

It’s used something like below and I think it’s fairly well known/understood/etc;

String.method(
  'lengthSquared', 
  function() 
  { 
    return(this.length * this.length); 
  }
);

My function here makes a new lengthSquared function available on on any string.

The brilliance of this is quite something but for the first few readings of it, I kept saying to myself;

“How can Function.protoype be used to add a method to a String when String is not a function. It’s a class or a type but not a function!!

because I wasn’t thinking like JavaScript – of course String isn’t a class or a type, it’s a function.

In fact – I think I’ll call this “Mike’s First Law of JavaScript – It’s a Function, Stupid” Smile

Reference: Crockford, “JavaScript, The Good Parts”, Page 33.

OMG #22 – array.sort() won’t sort numbers “correctly”

Not if you leave it to do its own thing, anyway.

Reference: Crockford, “JavaScript, The Good Parts”, Page 80.

OMG #23 – parseInt() needs help

I hadn’t appreciated that this would happen and that, by default, the “09” would be interpreted as octal;

var myString = "09";
var myOctalInteger = this.parseInt(myString);
var myDecimalInteger = this.parseInt(myString,10);
console.log(myOctalInteger);
console.log(myDecimalInteger);

Reference: Stefanov, “JavaScript Patterns”, Page 23.

OMG #24 – Callbacks and Scope

This one is going to be a very hard one to get used to. Let’s say I was writing some C# code that made use of simple, instance method passed as a callback;

 class MyType
  {
    string text = "some text";
    public void Print() { Console.WriteLine(this.text); }
  }
  class Program
  {
    static void Main(string[] args)
    {
      MyType m = new MyType();
      Wrapper(m.Print);
    }
    static void Wrapper(Action callback)
    {
      callback();
    }
  }

Pretty simple – the fact that the method Print is an instance method isn’t lost at the point where the function reference is passed to the Wrapper function which calls back to it and so this code prints “some text”.

I need to try and remember that JavaScript is very different;

var myObj = {
  text : "some string",
  print : function() { console.log(this.text); }
};

var wrapper = function(callback)
    {
      callback();
    };

// undefined. myObj.print is a function, not some
// combination of a function and an object reference
// to invoke it on.
wrapper(myObj.print);

and I guess to achieve a similar thing I’d need to make sure it was called on the right object with something like;

var myObj = {
  text : "some string",
  print : function() { console.log(this.text); }
};

var wrapper = function(instance, callback)
    {
      callback.call(instance);
    };

// logs "some string"
wrapper(myObj, myObj.print);

Reference: Stefanov, “JavaScript Patterns”, Page 64.

OMG #25 – Function Literals Create Functions

I’m not sure that I have the name of this “OMG!” correct but what I wanted to convey (partly, maybe mostly to myself) is to take care over where methods are created. Here’s a function that creates and returns an array of 2 functions;

var functionArray = 
    (function()
     {
       var i = 0;
       var arr = [];
       
       for (i = 0; i < 2; i++)
       {
         arr[i] = function() { return(1); }
     }
     return(arr);
    })();

console.log(functionArray[0] === functionArray[1]);

Now I would not be at all surprised if the interpreter were smart enough to see those 2 functions, spot them as identical and return the same function. However, as far as I know it doesn’t so creating functions like this in a loop would be a bad idea.

Reference: Crockford, “JavaScript, The Good Parts” Page 39

I’m not yet 100% sure how this does or doesn’t tie up with prototypes. Below, I’m trying to have an accessor method getName() which hides the instance state that it relies on. I do this by relying on the closure to capture the value of the parameter name to the constructor. Because of this, it feels like I’d have to have a separate function constructed for each instance of Turtle in order to capture the parameter value. I’m still pondering on that one so feel free to comment Smile

var Turtle = function(name)
    {
      this.getName = function()
        {
          return(name);
        };
    };

var t1 = new Turtle("Eric");
var t2 = new Turtle("Ernie");

console.log(t1.getName());
console.log(t2.getName());

// These are not the same method. I'm wasting methods!
console.log(t1.getName === t2.getName);

Reference: Stefanov, “JavaScript Patterns” Page 101

To be continued – you can find the rest of these “JavaScript OMG!!” entries here.