All pastes #623002 Raw Edit

javascript scopes explained thro

public javascript v1 · immutable
·published 2007-07-17 08:22 UTC
rendered paste body
<html><!-- A feeble attempt to understand Javascript scopes through unit testing --><!-- (the prototype.js/scriptaculous.js way) --><!-- released by rafsoaken under the MIT-license --><!-- feel free to copy, distribute and change for whatever purposes you like --><!-- ver 0.1 --><head>    <title>Testing Javascript Scopes</title>    <!-- the following javascript files are needed and must be referenced correctly -->    <script type="text/javascript" src="js/prototype.js"></script>    <script type="text/javascript" src="js/scriptaculous/scriptaculous.js"></script>    <script type="text/javascript" src="js/scriptaculous/unittest.js"></script>    <link rel="stylesheet" href="js/scriptaculous/test.css" type="text/css"/></head><body><h1>Unit Test Results</h1><!-- Results of Unittests here --><div id="testlog"></div><!-- Testing--><script type="text/javascript">    new Test.Unit.Runner({        setup: function(){            /*runs before any tests*/        },                teardown: function(){            /*runs after every test*/        },                // ------------------------------ TESTS GO HERE -------------------------------        /*tests that start with 'test' will be run automagically*/                testJavascriptScopes: function(){ with(this){                        var ScopeObject = Class.create(); //global            ScopeObject.prototype = {                initialize: function(){},                                return_this: function(){return this;},                return_that: function(){return this.return_this();},                                return_again: function(){return (function(){return this;})();},                return_again2: function(){return (function(){return this;}.bind(this))();}               };            var myScopeObject = new ScopeObject;                        assertNotIdentical(window, this);            // We are are not in the global scope                        assertNotIdentical(this, myScopeObject.return_this());            // Our scope and the functions scope are not the same -            // 'this' in the function refers to the Object it was defined in (myScopeObject)!                       assertIdentical(myScopeObject, myScopeObject.return_this());            // proof                        assertIdentical(myScopeObject, myScopeObject.return_this());            // although chained this goes 'this' goes through                        assertNotIdentical(myScopeObject, myScopeObject.return_again());            // now this anonymous function defined inside return_that does not refer to global scope            // it does not even refer to our scope!                        assertNotIdentical(this, myScopeObject.return_again());            // but to the global scope!                        assertIdentical(window, myScopeObject.return_again());            // proof                        assertIdentical(myScopeObject, myScopeObject.return_again2());            // now the anonymous function inside return_again2 was bound to 'this' of return_again2            // much better: the anonymous function now accesses it instead of the global scope                        // now how about changing scope of the objects methods?            assertIdentical(this, myScopeObject.return_this.bind(this).call());            // works                        assertRaise('TypeError', myScopeObject.return_that.bind(this)); // assertRaise(exceptionName, method)            // that doesn't work, as the function 'return_that' calls this.return_this(),             // and 'this' refers now to our scope and not myScopeObject, so it is not function (nor exists)                       // what about chained binds?            assertIdentical(this, myScopeObject.return_this.bind(this).bind(this).bind(this).call());                        // and some mixed chained binds?            assertIdentical(window, myScopeObject.return_this.bind(window).bind(this).call());            assertIdentical(this, myScopeObject.return_this.bind(this).bind(window).bind(myScopeObject).call());            // from this we learn:            // -> the first bind determines the scope, further binds don't change a thing            // once bound, its bound and unreboundable...                        assertIdentical(window, myScopeObject.return_again.bind(this).call());            // the anonymous function can't be bothered by our bind..                        assertIdentical(this, myScopeObject.return_again2.bind(this).call());            // this one in contrast works fine when bound         }}    });</script></body></html>