Last active
December 18, 2015 23:08
-
-
Save raganwald/5859117 to your computer and use it in GitHub Desktop.
This morning's "I made my very own WTF!?"
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
// I'm in the middle of a method, and I decide that I'll use an | |
// Immediately Invoked Function Expression ("IIFE") to create a new | |
// block scope so that I don't have to pollute the entire thing with | |
// resultJSON and contentJSON variables that would otherwise get | |
// hoisted. | |
// | |
// The current object DOES have a toJSON method, and so does the object called content. | |
// _.isFunction(this.toJSON) ==> true | |
// _.isFunction(content.toJSON) => true | |
� | |
return (function () { | |
var resultJSON = this.toJSON(), | |
contentJSON = content.toJSON(); | |
_.each(contentJSON, function (contentRow, rowIndex) { | |
var resultRow = resultJSON[extant + upperLeft.y + rowIndex]; | |
_.each(contentRow, function (contentCell, columnIndex) { | |
resultRow[extant + upperLeft.x + columnIndex] = contentCell; | |
}); | |
}); | |
return QuadTree.fromJSON(resultJSON); | |
})(); | |
// So what happens? | |
// TypeError: Cannot call method 'toJSON' of undefined | |
// Investigation reveals that the offending line is 14, | |
// "resultJSON = this.toJSON()" | |
// | |
// WTF!? |
The IIFE creates its own context when it's executed. Change the invocation from () to apply(this) and you'll be assigning the parent this scope to that function as well and things should be fine.
Yeah, that. By way of example:
var foo = { foo: 'bar' };
(function() {
console.log('outer', this);
(function() { console.log('inner', this) })();
}).apply(foo);
//=> outer Object { foo: 'bar' }
//=> inner Window
It's easily avoided in CoffeeScript with the fat arrow, but you wrote the book on it so, hey 😄
foo = { foo: 'bar' }
(->
console.log('outer', this)
do =>
console.log('inner', this)
).apply(foo)
#=> outer Object { foo: 'bar' }
#=> inner Object { foo: 'bar' }
You folks are spot on! I changed it to .call(this)
, but same thing. Good eyes!!
What happens if you pass the context into your IIFE? I.E.
return (function (that) {
var resultJSON = that.toJSON(),
contentJSON = content.toJSON();
_.each(contentJSON, function (contentRow, contentIndex) {
// Lots of copying from contentJSON to resultJSON
// ...
});
return QuadTree.fromJSON(resultJSON);
})(this);
Passing this
to that
works, as did:
return (function () {
var resultJSON = this.toJSON(),
contentJSON = content.toJSON();
_.each(contentJSON, function (contentRow, contentIndex) {
// Lots of copying from contentJSON to resultJSON
// ...
});
return QuadTree.fromJSON(resultJSON);
}).call(this);
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Comments, flames, instructions to go out and read a good JS book are all welcome. As are solutions and explanations :-)