TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

All this, a comprehensive look at 'this'

6 pointsby halisaurusalmost 11 years ago

1 comment

moron4hirealmost 11 years ago
It&#x27;s confusing to me to read through this and understand the nature of variable declaration and reference in JavaScript with the emphasis on demonstrating scenarios rather than describing the basic principles. I understand though that some people would find this approach more useful than my personally prefered approach. So don&#x27;t take the rest of my post as criticism, but addendum for folks who think differently.<p>I think &quot;this&quot; in JavaScript becomes much more clear (though only subjectively) when you start playing with bind&#x2F;call&#x2F;apply.<p>There are three, separate contexts in JS. There is the declared function block (Basic lexical scope, and other types of blocks don&#x27;t create their own scope), there is &quot;this&quot; context, and then there is the much less understood context &quot;with&quot; which you&#x27;re working (a sort of dynamic scope that is determined lexically).<p>I call them &quot;contexts&quot; instead of &quot;scopes&quot;, because &quot;this&quot; isn&#x27;t a scope level, and it is not contained in any scope level. It&#x27;s a keyword that references an object value that is determined by a different set of rules than scope. If it were &quot;in scope&quot;, then we could arrange scenarios in which we could chain references to &quot;this&quot;. There is no such thing as window.this, or window[&quot;this&quot;].<p>All variables (and named functions are function objects bound to a variable name) are stored within an object somewhere. When you declare a variable, how you declare it specifically sets the context object in which you&#x27;re storing the variable. &quot;var x = 5&quot;, you&#x27;re setting the variable on the function block context. &quot;this.x = 5&quot;, you&#x27;re obviously setting on the &quot;this&quot; context. &quot;x = 5&quot; declares the variable in the &quot;with&quot; context, if it&#x27;s not already declared in the function block. In all cases, it&#x27;s first, &quot;figure out some obj on which to store this variable&quot; followed by &quot;set obj[fieldName] to value&quot;, where fieldName is a string (always a string).<p>Accessing the variable again is the same sort of process. &quot;Figure out what containing object we&#x27;re talking about, then access it as obj[fieldName]&quot;. In all cases. The complexity lies in the figuring out step.<p>Now that we know that, we can start to ask questions about how these three scopes are set.<p>Function block scope is always function block scope. Unless you create a new function block (and only function blocks get their own scope level), then bare variable references first check the function block scope. Also remember that variable <i>declarations</i> get &quot;hoisted&quot; to the top of the function. If you declare a variable in a function, it&#x27;s visible in the entire block. <i>But</i>, the variable is not <i>set</i> until the line on which it was originally declared.<p><pre><code> function(){ console.log(x); &#x2F;&#x2F; prints &quot;undefined&quot; &#x2F;&#x2F;console.log(z); would error, as no z is ever declared var x = &quot;foo&quot;; console.log(x); &#x2F;&#x2F; prints &quot;foo&quot; } </code></pre> &quot;with&quot; scope is determined at the call site, by walking up the call lexical scope until a declaration for the requested variable is found. If it gets all the way up to the top &quot;window&quot; and it&#x27;s still not found, you get an &quot;undeclared variable&quot; error.<p>When you reference a function, what it will use as &quot;this&quot; then depends on whether or not it was explicitly set with bind&#x2F;call&#x2F;apply, followed by where it was found by the scope rules. If this wasn&#x27;t set explicitly, then the object in which the variable was stored is used as &quot;this&quot;.<p>So that means, with respect to event handlers, that the handler functions must be getting stored as a property of the DOM element to which they are bound.<p>But you can always override &quot;this&quot; with bind&#x2F;call&#x2F;apply. Just be careful that you know what &quot;this&quot; means when you call &quot;func.bind(this)&quot;.<p>It&#x27;s not accurate, because the syntax suggests there is a higher context to check, but if it helps you, you could think of the global script level in a browser as:<p><pre><code> function window(){ with(window){ &#x2F;&#x2F; all the code in your script block } } window.call(window); </code></pre> Every &quot;var&quot; or bare or &quot;this&quot; declarations are going to get set on the window object, every bare or &quot;this&quot; references are going to be from the window object.<p>From there, a bare function call changes the function block scope, but not &quot;this&quot; or &quot;with&quot;. Calling with &quot;new&quot; changes function block and &quot;this&quot;, but not &quot;with&quot;. And creating a with block changes changes &quot;with&quot;, but not &quot;this&quot; or function block. Calling &quot;bind&quot; sets &quot;this&quot; explicitly, and prevents it from automatically changing--though it can be reset explicitly with another call to bind. There is no way for one function block scope to have &quot;this&quot; change.