What is the difference between a JavaScript object and primitive types?

Stoyan Stefanov in his excellent book Object-Oriented JavaScript says:

Any value that does not belong to one of the five primitive types listed above is an object.

With five primitive types, it stands for Number , String , Boolean , Undefined and Null . However, in the Google Chrome console, it seems that the number is not at all a primitive type (compared to C primitive types such as int ). It seems like a primitive number has methods:

 var a = 2.2; console.log(a.toFixed()); // logs "2" 

Thus, I assumed that I could work with the number as an object, so I tried to assign a property to it:

 var a = 2; a.foo = 'bar'; console.log(a.foo); // logs undefined 

I do not understand this behavior. If the number has a method, it should behave like an object, right? He even has a prototype:

 Number.prototype.foo = 'bar'; var a = 2; console.log(a.foo); // logs 'bar' 

So what is this magic? How does JavaScript handle objects compared to primitive types? I would prefer not to use the word primitive and replace it with simple objects. As I see it, these are objects that cannot be expanded with new properties, however they are built through their constructor, and they also have a prototype that can be extended like regular objects.

+10
javascript
Feb 21 '14 at 11:25
source share
1 answer

[...] It looks like a primitive number has methods

The primitive does not have its own properties. He receives coercion to the object in order to be able to access its "properties". A coherent object is not available outside the called method * (in strict mode, not even inside the method) *. Thus, the reference variable is always primitive.

Consider this simple example:

 Number.prototype.myTypeInAMethod = function () { console.log (typeof this.valueOf ()) //"number" => The primitive is wrapped in an object. return typeof this; } var num = 123; typeof num; //number num.myTypeInAMethod () //object 

Note: in strict mode ES5 this will be primitive and the type will have a number

Since the num variable is primitive, you can choose not to assign values ​​to it.

 num.foo = "bar"; num.foo //undefined 

If you instead create a number (or string) through your object constructor, its type is indeed an object. A quick check by adding a property indicates that it can be assigned.

 var objNum = new Number(123); typeof objNum ; //"object" objNum.foo = "bar"; objNum.foo //"bar" 



So what is this magic? How does JavaScript handle objects compared to primitive types?

This process is described in ES5 Β§8.7.1 GetValue

For an object:

  • If Type(V) not a link, return V.
  • Let base be the result of calling GetBase(V) .
  • If IsUnresolvableReference(V) , throw a ReferenceError exception.
  • If IsPropertyReference(V) , then
    • If HasPrimitiveBase(V) false , then let get be the internal method of the [[Get]] base, otherwise let there be a special internal method [[Get]] defined below.
    • Returns the result of calling the internal get method using the base as the value of this and passing GetReferencedName(V) for the argument.
  • Otherwise, the base should be an environment record.
    • Returns the result of calling GetBindingValue (see 10.2.1 ) the specific method for passing the GetReferencedName(V) and IsStrictReference(V) as arguments.

For primitive:

The [[Get]] internal method is used by GetValue when V is a property reference [1] using the base value . It is called using the base as its value and with the P property as an argument. The following steps have been taken:

  • Let O be ToObject(base) .
  • Let desc be the result of calling the [[GetProperty]] O internal method with property name P.
  • If desc is undefined , return undefined .
  • If IsDataDescriptor(desc) true , return desc. [[Value]].
  • Otherwise, IsAccessorDescriptor(desc) must be true , so let getter be desc. [[Get]].
  • If getter is undefined , return undefined .
  • Returns a result that calls the get [[Call]] getter internal method, providing the base as the value of this and not providing any arguments.

<sub> NOTE The object that can be created in step 1 is not accessible outside the above method. An implementation may decide to avoid actually creating the object. The only situation where such actual access to a resource that uses this internal method can have a visible effect when it calls the access function. Sub>

[1] IsPropertyReference(V) . Returns true if either the base value is an object or HasPrimitiveBase(V) is true ; otherwise returns false .

+10
Feb 21 '14 at 11:32
source share



All Articles