Skip to content

Instantly share code, notes, and snippets.

@theotherzach
Last active January 4, 2016 18:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save theotherzach/8661879 to your computer and use it in GitHub Desktop.
Save theotherzach/8661879 to your computer and use it in GitHub Desktop.

Breakdown of Kangax JavaScript Quiz #6

Here is the original quiz. #6 asks for the output of this code:

var foo = {
  bar: function() { 
    return this.baz;
  },
  
  baz: 1
};

(function(){
  return typeof arguments[0]();
})(foo.bar);

Knowing what this evaluates to requires that we understand

  • How this late binds during a function invocation.
  • The array-like arguments object.

Function Invocation

In the following code, what is the value of this?

var foo = {
  bar: function() { 
   return this.baz; 
  },

  baz: 1
};

Trick question. We have no way to know what the value of this is since this isn't bound until the function is invoked. exception

These walk through some accurate-enough-for-now heuristics for understanding this.

###6a

var foo = {
  bar: function() { 
    return this.baz; 
  },

  baz: 1
};

foo.bar;
//=>function() { 
//    return this.baz; 
//  }

Remember that foo.bar is a reference to a function. No (), no execution.

Here is a more complete explanation.

###6b:

var foo = {
  bar: function() { 
   return this.baz; 
  },

  baz: 1
};


foo.bar();
//=> 1

When we see someObject.method(), that's a method invocation. During a method invocation, this is a reference to the receiver, or the thing on the left side of the dot.

###6c

var fooOne = {
  bar: function() { 
   return this.baz; 
  },

  baz: 1
};

var fooTwo = {
  baz: 2
};


fooTwo.bar = foo.bar;

fooTwo.bar();
//=> 2

Just another reminder that this doesn't bind at the definition, but at invocation. Never assume that you know what this is referencing unless you see ().

###6d

baz = "globalBaz"

var foo = {
  bar: function() { 
   return this.baz; 
  },

  baz: 1
};

var bar = foo.bar;

bar();
//=> "globalBaz"

When you see functionName(), that is a function invocation, not a method invocation. no dot, no method The distinction isn't pedantic horseshit, it's important. this operates differently, it doesn't reference the thing on the left side of the dot, there is no dot. Instead, this becomes a reference to the global object during a function invocation exception

this Recap

  • We don't know what this is until its function is invoked.
  • Method Invocation - objectName.method() - this points to the thing on the left side of the dot
  • Function Invocation - functionName() - this points to the global object

##Arguments

###6e

var func = function(arg1, arg2){
  return arg1 + arg2;
};

func("one", "two", "three");
//=> "onetwo"

func("one");
//=> "oneundefined"

(arg1, arg2) is the function's formal parameter list which both sounds fancy and is optional. Note that we can invoke functions with more or fewer arguments than the formal parameter list specifies.

###6f

var func = function(){
  return arguments;
});

func("one", "two");
//=> ["one", "two"]

func();
//=> []

We can also use arguments, the built in array-like object that holds the arguments our function was called with.

###6g

var foo = {
  bar: function() { 
    return this.baz;
  },
  
  baz: 1
};

(function(){
  return arguments[0];
})(foo.bar);
//=>function() { 
//    return this.baz;
//  }

(function(){
  return arguments[0];
})(foo.bar());
//=> 1

(function(){
  return arguments[0]();
})(foo.bar);
//=> undefined

Now to put everything together. Remember to watch for () and to keep an eye on the dot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment