YDKJS: this & Object Prototypes

Chapter 2. “this” All Makes Sense Now

Call-Site

In short: “this” is the call-site of the function.

Call-site of the the location where the function was called from (not where it was declared)

Call-stack is the stack of functions being called in the current moment.

Example

function baz() {
. // call-stack is: `baz`
. // so, our call-site is in the global scope
. console.log( “baz” );
. bar(); // < — call-site for `bar`
}
function bar() {
. // call-stack is: `baz` -> `bar`
. // so, our call-site is in `baz`
. console.log( “bar” );
. foo(); // < — call-site for `foo`
}
function foo() {
. // call-stack is: `baz` -> `bar` -> `foo`
. // so, our call-site is in `bar`
. console.log( “foo” );
}
baz(); // < — call-site for `baz`

Default Binding

So as a default case “ this” refers to the functions call-site.

function foo() {
console.log( this.a );
}
var a = 2;
foo(); // 2

Strict mode

In strict mode global scope cannot be used in this way, so the latest foo() function will return undefined.

Implicit Binding

function foo() {
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
obj.foo(); // 2

If the function is called from an owning or containing object than that object becomes a call-site and so forth “this”.

Implicit Lost

Consider:

function foo() {
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
var bar = obj.foo; // function reference/alias!
var a = “oops, global”; // `a` also property on global object
bar(); // “oops, global”

Function bar() is just a reference to the foo() function so its call-site leaked to global. Implicit binding works only when the whole path is entered, eg, obj.foo.

Explicit Binding

The easiest one. Consider

function foo() {
console.log( this.a );
}
var obj = {
a: 2
};
foo.call( obj ); // 2

Function call() forces obj to be the call-site (and “this”) for foo function.

Functions bind() and apply() has the same effect with respect to “this” binding.

“New” binding

In object-oriented languages there are constructors — special methods in class that are called when the class is initiated. In JavaScript there are no classes and the “new” behavior is different although the syntax is quite the same. In JS constructors are just functions, they just called with the “new” operator in front.

function foo(a) {
this.a = a;
}
var bar = new foo( 2 );
console.log( bar.a ); // 2

When the function is called with the “new” operator

  1. New object is created
  2. This object is [[Prototype]]-linked (WTF???)
  3. Fresh object becomes “this” for the function
  4. Unless the function returns another object — automatically that new object will be returned.

The Order

Four rules of “this” binding to be applied has the following order

  1. “new”
  2. .call
  3. Context object
  4. Global scope or undefined in strict mode.
Show your support

Clapping shows how much you appreciated Natalia Konovalova’s story.