What does the assignment {} .toString mean?

I am learning JavaScript and I came across this snippet that demonstrates type detection:

var toClass = {}.toString // Copy a reference to toString for objects into toClass variable alert( toClass.call( [1,2] ) ) // [object Array] alert( toClass.call( new Date ) ) // [object Date] 

I don’t understand why empty braces in the first line are needed, so I delete them as follows:

 var toClass = toString 

And the code is still working. But in the following code

 function getAge () { alert(this.age); } var p1 = { age:1 }; var tellAge=getAge; tellAge.call(p1); //1 

if I change var tellAge=getAge to var tellAge={}.getAge , I get an error: I can not read the property "call" undefined. Why is this? Is it because toString is a built-in function?

+5
source share
4 answers

This is because toString is a built-in function

Not really, because both Object and window in javascript have a toString method.


{} in {}.toString represents a new object in javascript. The object has a toString method, and that is what you create the link to.

If you omit {} , this is equivalent to window.toString , and, with luck, the window object itself has a toString method. So everything continues to work.

When you execute {}.getAge , you are telling the interpreter to get the getAge method from an Object that does not exist, setting tellAge is undefined , which leads to an error cannot read property "call" of undefined

+7
source
  • {} returns a new object of type Object (1) .
  • toString() returns a string representing the object (2) .
  • For an object of type Object , toString() should return the value [object Object] .
  • call() executes a method with the given this value and arguments provided individually (3) .
  • Any function that is not explicitly assigned as a method for an object is implicitly assigned to a Window object. Using this in such a function always refers to a Window object.

Now back to your code, will we ?!

 var toClass = {}.toString 

First, a generic object of type Object . Then it returns the toString method (the method itself, not the return value.

This means that toClass is now a function. It uses the {} object as the value of this . Therefore, if you simply run toClass() , you should always get the value [object Object] .

Now here is the hard bit!

Take this command:

 toClass.call( [1,2] ) 

What's going on here? Well, this is like calling toClass() , except that your this value is no longer {} . Instead, it is replaced by [1,2] (4) . That is why you get [object Array] as a result!

Now take this command:

 toClass.call( new Date ) 

What's going on here? Well, actually. This is similar to calling toClass() or toClass.call( [1,2] ) , except that your this value is replaced with an object of type Date (5) . That is why you get [object Date] as a result!

Now take this function:

 function getAge () { alert(this.age); } 

What's going on here? Well, this function simply warns the age property of the this value in your method. By default, this property is unknown, because this is Window , and the Window object does not have an age property.

Now, take this command:

 var p1 = { age:1 }; 

Here you create an object with one property. This property is age and has a value of 1.

Now, take this command:

 var tellAge=getAge; 

Here you assign the getAge function to the getAge variable. By default, both functions use the same this value, which is a Window object.

 tellAge.call(p1); 

What's going on here? Well, it's almost the same as calling tellAge() or getAge() , except that your this value is no longer Window . Instead, it is replaced by p1 . You get 1 as a result because the p1 object has an age property and this property has a value of 1!

Now consider the following command:

 var tellAge={}.getAge 

Why does this cause an error? What you are trying to do here creates a generic object of type Object . Although by default it has a toSting method (which is defined in its prototype (6) ), it does not arrive using the getAge method. This is why you get an error message.

Now take the following code:

 var p2 = { age : 18 }; var p3 = { age : 25 }; var FObject = { getage : function() { return this.age; } }; var tellAge = FObject.getage; alert( tellAge.call(p2) ); //18 alert( tellAge.call(p3) ); //25 

So what does this do? Good:

  • First, you create an object called p2 that has an age property with a value of 18.
  • Then you create an object named p3 that has an age property with a value of 25.
  • Then you create another object called FObject , which has a getAge method.
  • Then you assign the FObject.getage method to the FObject.getage variable.
  • Then you call tellAge.call(p2) . This is similar to calling tellAge() , except that your this value is replaced with a p2 object. That's why you get 18 as a result!
  • Finally, you call tellAge.call(p3) . This is similar to calling tellAge() or tellAge.call(p2) , except that your this value is replaced with a p3 object. That's why you get 25 as a result!

I believe this last example provides a good overview of the behavior you are studying.


References:

+1
source

Oh my ... there’s a lot to answer in such a short time ... But you have a long way to go in JavaScript, but you will like it ...

1) The designation of the object. You must google for JSON.

An object designation means that you can define data in a specific format related to JavaScript.

{} in the designation of objects means an object ... more specifically, it is already an instance of an object.

You can also write this in simple javascript, it will look like this:

 new Object() 

2) Functions are first class citizens.

Well, features are indeed a very valuable asset in the JS ecosystem. This means that you can do basically everything you imagine. This includes copying a reference to a function that "belongs" to another object.

{}. toString is a function. You usually call it by executing {} .toString ()

Instead, you simply copy the function reference in the variable. In this case, you "store" the function in the variable "toClass"

3) The prototype chain. You have to google, well, prototype circuit haha.

A prototype chain, for simple things, is like "class inheritance." So this means that if class A has a blah method and class B is a child of class A, it will also have a blah method.

In the JS world, the top of the prototype is "Object." And many features are already defined in the prototype. object. Enabling "toString"

4) The general problem of relativity ... aka this, challenge and application.

Since functions are first-class citizens, they can, in principle, exist, not even belonging to a specific instance of an object.

This means that you can choose in which context you want to enable the function.

By default, when calling functions that seem to be “attached” to an object, this object becomes this context of this function call:

 {}.toString() // This executes toString in the context of {} 

But, as I said, you can simply choose where the function actually executes. There are “call” and “apply” methods for this.

Our previous example can be translated into:

 Object.prototype.toString.call({}) // This executes toString in the context of {} 

5) Global objects in your environment.

This is not a simple topic, because now JavaScript works not only in the browser, but also on the server ... NodeJS is a good example of this.

Assuming you run this in a browser ... there is a global object called window

You can call any function in a global object.

Thus, toString is equivalent to the .toString window , and the window is a descendant of Object, it will also get a method from Object.prototype.

Now your answer

getAge is not defined in Object.prototype, so you cannot call a non-existent function.

+1
source

Just made this example to make you understand. Jsfiddle

 var toClass = {}.toString; // type detection function person(age){ this.age = age; this.getAgePlusOne = function(){ return this.age + 1; }; } var you = new person(20); // create a new person object and set age propery to 20 console.log(you); var yourAge = you.getAgePlusOne(); // call created person object function getAgePlusOne() to retrieve value console.log(yourAge); console.log(toClass.call(you)); // object console.log(toClass.call(you.getAgePlusOne)); //function 
0
source

All Articles