JavaScript — Scope && .this

Scope

scope is the set of rules that determines how a variable can be looked up. In programming languages, there are two types of scope:

  • Lexical scope → defined at author time (when a code is written )
  • dynamic scope (.this)→ defined at run-time (where a function is called from)
“To be clear, JavaScript does not, in fact, have dynamic scope. It has lexical scope. Plain and simple. But the this mechanism is kind of like dynamic scope. The key contrast: lexical scope is write-time, whereas dynamic scope (and this!) are runtime. Lexical scope cares where a function was declared, but dynamic scope cares where a function was called from.” — Kyle Simpson

  • Global Scope

Variables declared globally have global scope and can be accessed by functions and their nested functions.

- Child functions have access to variables declared in their parent's and grandparents'(global)scope.
var globalVar = "window"

function parent() {
var parentVar = 'parent'
  function child() {
              //child has access to parent variable
//child has access to global variable
console.log(parentVar);
console.log(globalVar);
}
  child();
}
parent()
>> "parent"
>> "window"

  • Local Scope

Variables declared inside a function have a local scope and cannot be accessed outside that function.

- Parents have no access to their children's defined variables
function parent() {
   function child() {
var localVar = 'local'
//child has access to parent variable
//child has access to global variable
}
 console.log(localVar) 
}
// localVar cannot be accessed outside the child() function. parent() 
>> ReferenceError localVar not defined
  
// localVar is was not defined in the global scope. It is not visible outside its local scope.
console.log(localVar)
>> ReferenceError localVar not defined

  • Block level scope

ES6 introduced the let statement which allows for block level scope.

let allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. This is unlike the var keyword, which defines a variable globally, or locally to an entire function regardless of block scope.” -Mozilla Developer Network
var value = "string"
# using let: 
for(let i = 6; i <= value.length; i++) {
console.log(i) // 6
}
// variable #i is not visible outside the block where it was defined. 
console.log(i) // error
--------
# using var:
for(var i = 6; i <= value.length; i++) {
console.log(i) // 6
}
console.log(i) // 7

.this

Each time a function is executed, it gets a .thisproperty which is a variable with the value of the object on which the function is called. In order to understand the binding of .this, we have to find the location in the code where a function is called not when it was declared(the call-site).

The Global Context

.this in the global execution context is assigned to the value of the Window object(the global object in node.js)

variables executed in the global context: 
a = "I'm called on the window object";
console.log(window.a); // I'm called on the window object
a = "I'm still called on the window object";
console.log(this.a); // I'm still called on the window object
> this === window
>> true


The Function Context

the value of .thisinside the function context depends on how it was called.

  • invoking functions in the global context

when a function is executed in the global execution context, it is invoked by the the Window object. Therefore, .thisis assigned to the window object.

// here the function is invoked in the global context by the window object. "this" is bound to the window object.
function someFunction(){
console.log(this)
}
someFunction() // Window
  • Invoking a function on an object

when calling a function on an object. The value of .thisis set to that object.

var obj = {
someData: "a string",

someFunction: function myFun() {
console.log(this)
}
};
obj.someFunction() 
// { someData: 'a string', someFunction:[Function: myFun] }

In the example below, myFunc() function has the same functionality as the #someFunction() function. However, since it was executed in the global context, the value of .thisis set to the global object:

var obj = {
someData: "a string",

someFunction: function myFun() {
console.log(this)
}
};
var myFunc = obj.someFunction;
myFunc();
// Window
  • In Strict Mode

When using Strict Mode, the value of .this is undefined for global functions and anonymous functions that are not bound to any object.

  • Binding .this

.call, .apply and .bind are methods used to bind .this to a new object. Both call and apply perform very similar functions, they execute a function in the context, or scope, of the first argument that you pass to them.


Follow my coding journey here on Medium or find me on GitHub, Linkedin, and Facebook.