Subtle facts about Objects and `This`

This and Object are two of the most discussed topics in javascript, there are so many things to know about them we could just go on forever but is important to examine them very well and keep some key concepts handy, in order to get the most of them.



[ The content of this article is my take home from the great book of Kyle Simpson this & Object Prototypes of the series "You don't know JS", i really recommend to read it in order to fully grab these concepts! ]


this

this is probably one of the most explained concept in javascript tutorials. The learner is warn about the complexity of this simple world and its hiding behavior but honestly I hardly find tutorials which fully explain why we should be careful with it; at the end is a way of passing around an object reference and until now I didn't find anything misterious in that. But actually there are some subtle facts about this that help explaing why we have to be careful with it, or at least we need to be aware of what really is.

1) Is important to understand that this isn't native from javascript language. And more important, even if this is created every time we create a function, it doesn't automatically point to the function it self, we need to link this to the function object.
What is the self-created this before being bind to an object? Simply a global variable with NaN as value!

2) this doesn't refer to the lexical scope at all. It's true that scope is like an object with properties but the scope object isn't accessible from javascrip code.

function foo() {  
  var a = 2;
  bar();
}

function bar() {  
  console.log(this.a);
}

Writing this.a we are try to implicitly refer to foo lexical scope BUT this doesn't work!
So far this is not bind to any object.

3) this is created when the function is invoked. When a function is invoked, a "execution context" is created containing informations about where and how the function was called, which params are passed and so on.
One of the property of this context is the this.

4) To understand this binding we need to understand the call-site. Call-site, the location where a function is called, can be found checking the call-stack, chain of function calls listed in order. We must be careful to find the actual call-site from the call-stack because this is the only thing that matter to understand what this is bind to.
Why is the call-stack so important to understand this binding? Because according to the context of call-site, we can establish to what this is bind.
For example, if the function is standalone invocation and is called in the global scope, this is also bind to the global scope:

function foo() {  
  console.log(this.a);
}

var a = 2;  
foo(); //2

window.a === this.a // true  

But if the call-site is precede by an object reference, then this is bind to that object:

function foo() {  
  console.log(this.a);
}

var obj = {  
  a: 2,
  foo: foo
}

obj.foo(); // 2

this.a === obj.a // true  

The first example is called default biniding where the second is called implicit binding.
There are four of these in total (default, implict, explicit and new binding) and each of them as different rules and different severity level which play a foundamental role in determine where this is pointing.

Object

Objects are a core part of javascript, since everything is an object; for this reason we could talk endless about javascript objects but I wanted to highlight here some spare facts I found it very interesting and helpful to understand and work better with objects, some facts that are maybe brought out less.

1) Object Duplication.
Duplicate an object is something you will find your self doing quite often but so far there is no easy way or official way to do it.
The first official solution come with ES6.
But why is so complicated to create build-in copy() method?
The problem is that is not clear what it need to be duplicated.
Let's understand this by an example:
What about if our object has a reference to other objects as values?
Should we just do a copy of the object with its values or should we do a copy of the object with its values and also a copy of the other objects its values refered to?

var myObj = {  
 a: 2,
 b: otherObj, // reference, not a copy
 c: anotherObj // reference again
} 

But what happening if anotherObj has inside a reference to a third object? We could go on and on endless.
Until now there was no clear solution for duplicate object, different frameworks deal with it in different ways.
A large used solution for objects that are JSON-safe (they can be serialize to a JSON string and reversed to an object without lose structure or values) is:

var newObj = JSON.parse(JSON.stringify(myObj));  

Anyway with ES6 is decided that a shallow copy of the object is enough and it has less issues to deal with so we finally got Object.assign(...) where the first param is the target object and then one or more following are source objects.

var newObj = Object.assign({}, myObject);  

2) How an object actually finds its value?
Did you ever wonder how objects can access their properties?

var myObj = {  
 a: 2,
 b: 4
} 

myObj.a; // 2  

In order to myObj.a give back 2 the object doesn't just look for a property of the name a, it perform a [[GET]] operation (similar idea of a function call). [[GET]] is a default built-in operation of an object which first inspect the object for the wanted property and if it finds, it will return the value of it.
If the value isn't found, it return undefined (be aware that undefined could also be the actual value of the property).

But if there is a [[GET]] operation to get the property there should also be a [[PUT]] operation, correct? Correct!
[[PUT]] built-in operation is there to set or create a property. It's behavior is more complicated to explain since it depend from many factors but we can say that it follow these rules:

  • If property has [[Getter]] or [[Setter]] set, use those one.
  • If the property isn't writable, return Error.
  • If none of the above is true, set the value.



Here there is a short but very helpful list of HOW TO related to objects:

How To..

1) ..ask to an object if has a certain property:

  • myObj.hasOwnProperty('a') Check if a property is in the specific object.
  • ('a' in myObj); // true Check if a property is in the object and also looks up in the prototype chain.

2) ..ask how many properties are in an object:

  • For..in loop is preferably used for objects and for loop for Array. They work for both of them, but if we don't follow this rule is likely we will have unwanted behavior.
 for(var k in myObj) { 
    console.log(k, myObj[k]);
 } //a 2 
  • myObj.propertyIsEnumerable('a'); //true It test if the property exist on the object and is enumerable.

  • Object.keys(myObj); //['a', 'b', 'c'] It return an array of all enumerable properties.
    Object.getOwnPropertyNames(myObj); It return an array of all properties, enumerables or not.

3) ..iterates:
We all know for loop (which iterate over array's indices) and forEach loop (which iterate over values in array or object's properties but the order of the iteration is not guaranteed) but with ES6 an additional way to iterate is possible: for..of loop which iterates over values in array,

 for (var v of myArray){
   console.log(v);
 }

Conclusion

In this post i wanted to share in a form of notes, what i think is not always highlited but is important to know about this and objects in javascript.
In particular the objects part i believe is one of those handy list we should always have around to refer to when needed.
Of'course more we learn about objects and more the javascript specifics grow, more the list should grow!