Created
September 2, 2015 21:12
-
-
Save etsuo/e23b7618027d08034f37 to your computer and use it in GitHub Desktop.
Javascript "this" behavior notes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/************* | |
/ Call #1 Default Binding | |
**************/ | |
function foo() { | |
console.log( ": " + this.a ); | |
} | |
// note var is dropped to make this global even when | |
// run with node.js that would otherwise cause the call | |
// site of foo to be called from within a module | |
// (function (exports, require, module, __filename, __dirname) { ... call site ...} ) | |
a = 'a from global'; | |
console.log('Call 1 (Default Binding): this points to global a'); | |
foo(); // call site > 'default binding' | |
nl(); | |
/************* | |
/ Call #2 Implicit Binding | |
**************/ | |
var obj = { | |
a: 'a from obj', | |
foo: foo | |
}; | |
console.log('Call 2 (Implicit Binding): this points to obj.a'); | |
obj.foo(); // call site > 'implicit binding' | |
nl(); | |
/************* | |
/ Call #3 Implicit Binding | |
**************/ | |
// Note that only the last context of a function call | |
// establishes the call site | |
var obj2 = { | |
a: 'a from obj2', | |
obj: obj | |
}; | |
console.log('Call 3 (Implicit Binding): last call site mean this points to obj.a, not obj2.a'); | |
obj2.obj.foo(); // call site > 'implicit binding' | |
nl(); | |
/************* | |
/ Call #4 Implicit Binding Lost | |
**************/ | |
// Watchout for implicit binding in wrapper functions | |
// this will happen in callbacks | |
function doFoo(fn) { | |
fn(); // << this just became the call site | |
// since there's no "a" in doFoo, this points to global a | |
} | |
var bar = obj.foo; // function reference / alias | |
console.log('Call 4 (Implicit Binding Lost): this points to global since bar is the call site'); | |
bar(); // call site | |
nl(); | |
/************* | |
/ Call #5 Implicit Binding Lost | |
**************/ | |
// what happened with bar() above is what happens when you pass a function | |
console.log('Call 5 (Implicit Binding Lost): this points to global since doFoo is the call site'); | |
doFoo(obj.foo); | |
nl(); | |
// this means if doFoo is a callback, this will lose its context for this... | |
/************* | |
/ Call #6 Explicit / Hard Binding | |
**************/ | |
console.log('Call 6 (Explicit / Hard Binding): this points to obj.a because it is hard bound with .call(...)'); | |
console.log('bar.call(obj)'); | |
bar.call(obj); | |
console.log('bar.call(obj2)'); | |
bar.call(obj2); | |
nl(); | |
/************* | |
/ Call #7 Explicit / Hard Binding | |
**************/ | |
console.log('Call 7 (Hard Binding with built in bind): this points to obj.a becaus it is hard bound with .bind'); | |
bar = foo.bind(obj); | |
bar(); | |
nl(); | |
// note, if bar took parameters, this would allow them... so, for example you could: | |
// bar = foo.bind(obj); | |
// bar(123); | |
// Assuming bar took parameters | |
/************* | |
/ Call #8 New Binding | |
**************/ | |
function newFoo(a) { | |
this.a = a; | |
} | |
a = 4; | |
var bar = new newFoo(2); | |
console.log('Call 8 New Binding): this points to the new newFoo'); | |
console.log(bar.a); | |
// Binding Order | |
console.log('new binding'); | |
console.log('explicit biding'); | |
console.log('implicit binding'); | |
console.log('default binding'); | |
////////// | |
function nl() { | |
console.log(''); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment