Why Math.toString() return [object Math]? - javascript

I read here that :
By default, the toString() method is inherited by every object descended from Object. If this method is not overridden in a custom object, toString() returns "[object type]", where type is the object type.
So: result this code, must be [object object ] because typeof Math is object but , i see result is [object Math]
var toString = Object.prototype.toString;
console.log( toString.call(Math) ) ;
var toString = Object.prototype.toString;
console.log( toString.call(Math) ) ;
Tahnkyou!

The relevant parts within the specs are:
20.2.1.9 Math [ ##toStringTag ]:
The initial value of the ##toStringTag property is the String value "Math".
This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
19.1.3.6 Object.prototype.toString ( ):
Historically, this function was occasionally used to access the String value of the [[Class]] internal slot that was used in previous editions of this specification as a nominal type tag for various built-in objects. The above definition of toString preserves compatibility for legacy code that uses toString as a test for those specific kinds of built-in objects. It does not provide a reliable type testing mechanism for other kinds of built-in or program defined objects. In addition, programs can use ##toStringTag in ways that will invalidate the reliability of such legacy type tests.
So with the current specs the result of toString will be [object ##toStringTag].
In earlier versions it was defined as :
15.8 The Math Object
The value of the [[Class]] internal property of the Math object is "Math".
15.2.4.2 Object.prototype.toString ( )
Let class be the value of the [[Class]] internal property of O.
Return the String value that is the result of concatenating the three Strings "[object ", class, and "]".

What you are getting is exactly what is described and expected:
toString() can be used with every object and allows you to get its class.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString#Using_toString()_to_detect_object_class

Your answer lies here:
toString() can be used with every object and allows you to get its
class. To use the Object.prototype.toString() with every object, you
need to call Function.prototype.call() or
Function.prototype.apply() on it, passing the object you want to
inspect as the first parameter called thisArg.
Meaning when you preform:
var toString = Object.prototype.toString;
console.log(toString.call(Math));
You are getting and printing the class - object Math.
taken from developer.mozilla.

Related

What happens when you instantiate a new Object(1) with a parameter in JavaScript?

What happens when you call:
new Object(1)
When I tried it out, it returned:
[Number: 1]
I want to understand what is going on there. Any info would be appreciated.
You can look at the spec:
When new Object(arg) is invoked, we are essentially calling ToObject(arg).
ToObject is defined as
The abstract operation ToObject converts argument to a value of type Object according to Table 13
And the table says:
Number: Return a new Number object whose [[NumberData]] internal slot is set to the value of argument. See 20.1 for a description of Number objects.
So it's the same as calling new Number(1), i.e. it creates a number object.
The primitive data types String, Number and Boolean have equivalent object values that can be created by invoking the equivalent constructor functions. But that is not a common thing to do since object values behave differently than primitive values, i.e. a number primitive will behave different than a number object in certain cases.
Example:
Boolean(0); // false
Boolean(new Number(0)); // true
Here is the documentation for the default constuctor:
http://www.ecma-international.org/ecma-262/5.1/#sec-15.2.2.1
When the Object constructor is called with no arguments or with one
argument value, the following steps are taken:
If value is supplied, then
If Type(value) is Object, then
If the value is a native ECMAScript object, do not create a new object but simply return value.
If the value is a host object, then actions are taken and a result is returned in an implementation-dependent manner that
may depend on the host object.
If Type(value) is String, return ToObject(value).
If Type(value) is Boolean, return ToObject(value).
If Type(value) is Number, return ToObject(value).
Assert: The argument value was not supplied or its type was Null or Undefined.
Let obj be a newly created native ECMAScript object.
Set the [[Prototype]] internal property of obj to the standard built-in Object prototype object (15.2.4).
Set the [[Class]] internal property of obj to "Object". Set the [[Extensible]] internal property of obj to true.
Set all the internal methods of obj as specified in 8.12.
Return obj.

JavaScript Make a non-object variable with properties [duplicate]

I've been messing around with the ECMA-262 standard (ECMAScript Language Specification, 3rd edition, if it matters for this - I have not found any difference between the 3rd and 5th edition on String Type / String Object).
There's one thing that baffles me: the difference between the String Type and the String Object. Yes I know the difference in the sense that the String Type is a sequence of 16-bit UTF-16 units and the String Object is a built-in object with its internal Class property set to "String" and its internal Value property set to a value of the String Type.
But reading the specification, the string type does not seem to expose any methods; that is, it's just a value without any additional properties. Take this code, everything is exactly as expected:
document.writeln(typeof "foo"); // 'string'
document.writeln(typeof new String("foo")); // 'object'
The first type is the actual String Type and the second is the Object Type (it's an object of class String, but its data type is object). However, looking at this:
"foo".charAt(0);
fooStrObj = new String("Foo");
fooStrObj.charAt(0);
They both seem to expose the same functions, but there are no functions on the String Type defined in the ECMA-262 standard; all the functions it exposes are from the String.prototype object (and I can see no reference to the fact that the String Type magically exposes all the properties and functions of the String.prototype object in the ECMA-262 standard). So are the values of type String Type automatically promoted to a String Object with the original String Type value as its internal Value property?
And if they are treated exactly the same (which for all intents and purposes they seem to be), why have two different ways to represent a String?
Strings are a value type in JS, so they can't have any properties attached to them, no prototype, etc. Any attempt to access a property on them is technically performing the JS [[ToObject]] conversion (in essence new String).
Easy way of distinguishing the difference is (in a browser)
a = "foo"
a.b = "bar"
alert("a.b = " + a.b); //Undefined
A = new String("foo");
A.b = "bar";
alert("A.b = " + A.b); // bar
Additionally while
"foo" == new String("foo")
is true, it is only true due to the implicit type conversions of the == operator
"foo" === new String("foo")
will fail.
It's analogous to the difference between int and Integer in Java.
According to the standard, strings are automatically converted to String objects when you try to call a method. See ECMA 262-3 section 11.2.1; step 5 calls ToObject (which is defined in section 9.9).
11.2.1 Property Accessors
[...]
The production MemberExpression : MemberExpression [ Expression ] is evaluated as follows:
Evaluate MemberExpression.
Call GetValue(Result(1)).
Evaluate Expression.
Call GetValue(Result(3)).
Call ToObject(Result(2)).
Call ToString(Result(4)).
Return a value of type Reference whose base object is Result(5) and whose property name is Result(6).
9.9 ToObject
The operator ToObject converts its argument to a value of type Object according to the following table:
[...]
Create a new String object whose [[value]] property is set to the value of the
string. See 15.5 for a description of String objects.
As a specification technique, this is a hack to explain how strings can appear to have methods even though they're not really objects.
Apart from that, the wrapper objects are not very useful. I don't know why they're in the language. I rather wish they weren't. :)

Javascript toString making no sense to me

OK I just did it and scratched my head for a while. I tried following on my Chrome console:
var a = [];
toString.call(a); //[object Array]
a.toString(); //""
toString(a); //[object Object] I know it's blunder but still!
What is difference between the toString and .toString I definitely know they are from different scopes (objects), but which one should be used at what time? Why is it so messy?
First of all we have to clarify that toString refers to Object.prototype.toString:
> toString === Object.prototype.toString
true
How Object.prototype.toString works is explained in section 15.2.4.2 of the specification:
If the this value is undefined, return "[object Undefined]".
If the this value is null, return "[object Null]".
Let O be the result of calling ToObject passing the this value as the argument.
Let class be the value of the [[Class]] internal property of O.
Return the String value that is the result of concatenating the three Strings "[object ", class, and "]".
toString.call(a) is the same as Object.prototype.toString.call(a) and works according to the above algorithm: this refers to the array a (because you used .call), the internal [[Class]] property has the value Array, hence the output is [object Array].
a.toString(): Arrays overwrite the toString property, which is defined in section 15.4.4.2. In short, all array elements are concatenated and since the array is empty, you get an empty string as result.
toString(a) is the same as Object.prototype.toString(). The argument is simply ignored. Therefore this refers to Object.prototype, which is an object and according to the algorithm mentioned above, the output is [object Object]. The output would be same for any value of a.
which one should be used at what time?
That depends on what you want to do. Personally I find none of the built-in toString functions particularly useful, besides for some quick and dirty debugging.
toString.call(a) should be == a.toString()
Well, Object.prototype.toString and Array.prototype.toString are simply two different methods, hence you get different results.
You could argue that Object.prototype.toString should call the overwritten toString if it exists, but that's just not how toString is implemented.

Primitives and Objects

Definitive JavaScript by David Flanagan makes a distinction between Objects and Primitives.
He defines the primitives as Number, String, Boolean, Null, and Undefined, as does the standard.
However, would it be more accurate to define a primitive, as subset of object, i.e. to call them Primitive Objects.
Because they have their own methods and are complex entities.
Actual Question
Would Primitive Object be more accurate than Object when defining String, Boolean, and Number?
Objects and primitives are distinct:
typeof 42 === "number"
typeof new Number(42) === "object"
new Number(42) !== 42
However, when necessary, primitives are automatically wrapped by temporary objects, which can be automatically converted back into primitives:
(42).toString() === "42"
new Number(42) == 42
new Number(42) + 1 === 43
Especially in the context of the Java and C# programming languages, this sort of behavior is called autoboxing. As wrapper objects have some confusing characteristics, for example:
Boolean(new Boolean(false)) === true
it is good practice to avoid intentionally storing them in variables and instead use primitives whenever possible.
It's not about semantics, look:
var threePrimitive = 3;
var threeObject = new Number(3);
threePrimitive.toFixed(2); // 3.00
threeObject.toFixed(2); // 3.00
threePrimitive.foo = true
threeObject.foo = true;
threePrimitive.foo; // undefined
threeObject.foo; // true
Primitives are wrapped in objects when you try to call a method on them, but after initial use the object is thrown away.
As for how this is stated in the specification, I'm not 100% sure, but here is what I think (based on the tips left by Bergi in one of his answers. Section 11.2.1 states that the accessor properties should be evaluated as follows:
Let baseReference be the result of evaluating MemberExpression.
Let baseValue be GetValue(baseReference).
(...)
Then in 8.7.1 we see the following:
The following [[Get]] internal method is used by GetValue when V is a
property reference with a primitive base value. It is called using
base as its this value and with property P as its argument. The
following steps are taken:
Let O be ToObject(base).
Let desc be the result of calling the
[[GetProperty]] internal method of O with property name P.
If desc is
undefined, return undefined.
If IsDataDescriptor(desc) is true, return
desc.[[Value]].
Otherwise, IsAccessorDescriptor(desc) must be true so,
let getter be desc.[[Get]]. If getter is undefined, return undefined.
Return the result calling the [[Call]] internal method of getter
providing base as the this value and providing no arguments.
NOTE The
object that may be created in step 1 is not accessible outside of the
above method. An implementation might choose to avoid the actual
creation of the object. The only situation where such an actual
property access that uses this internal method can have visible effect
is when it invokes an accessor function.
Would Primitive Object be more accurate then Object when defining
String, Boolean, and Number?
Please note that I'm not saying that numbers are not objects here, I'm pointing out that it appears ambiguous. This is the kind of thing that confuses JavaScript newcomers.
The distinction is mostly academic, but there is one case where it seems ambiguous: literals represent primitive objects except when the literal appears to represent a number. You can't apply a method directly to a literal integer* symbol:
1.toString();
SyntaxError: identifier starts immediately after numeric literal
…but you can apply methods of Numbers:
Number(1).toString();
'1'
…and a name that contains a number is a Number:
x = 4;
x.toString();
'4'
I think this is actually a parsing problem, but I don't really know why the parser can't tell that 1 is a Number as easily as it can tell that "abc" is a String. I suppose it has to do with the semantic ambiguity of the . symbol. (Is it a decimal point or a method operator?)
*JavaScript doesn't actually have integers. I just mean a symbol that consists entirely of [0-9]+.

What is the .call() function doing in this Javascript statement?

I'm actively learning javascript, and I came across the following statement:
Object.prototype.toString.call([]);
And I don't know what it means or what it does.
I have a vague understanding of .call, in that it allows you to call a method in the context of a different object (I think), but I am having a hard time understanding what role the .call() function is playing in the above statement. So I was wondering if anyone could explain what .call() is doing here?
Thanks!!
The call method sets the this value of the invoked function to the object passed as first argument, in your example, you are executing the Object.prototype.toString method on an Array object.
Array objects, have their own toString method (Array.prototype.toString) that shadows the one from Object.prototype, if you call [].toString(); the method on the Array.prototype will be invoked.
For example:
function test() {
alert(this);
}
test.call("Hello"); // alerts "Hello"
Another example:
var alice = {
firstName: 'Alice',
lastName: 'Foo',
getName: function () {
return this.firstName + ' ' + this.lastName;
}
};
var bob = {
firstName: 'Bob',
lastName: 'Bar',
};
alice.getName.call(bob); // "Bob Bar"
In the above example, we use the Alice's getName method on the Bob's object, the this value points to bob, so the method works just as if it were defined on the second object.
Now let's talk about the Object.prototype.toString method. All native objects in JavaScript contain an internal property called [[Class]] this property contains a string value that represents the specification defined classification of an object, the possible values for native objects are:
"Object"
"Array"
"Function"
"Date"
"RegExp"
"String"
"Number"
"Boolean"
"Error" for error objects such as instances of ReferenceError, TypeError, SyntaxError, Error, etc
"Math" for the global Math object
"JSON" for the global JSON object defined on the ECMAScript 5th Ed. spec.
"Arguments" for the arguments object (also introduced on the ES5 spec.)
"null" (introduced just a couple of days ago in the ES5 errata)
"undefined"
As I've said before that property is internal, there is no way to change it, the specification doesn't provide any operator or built-in function to do it, and the only way you can access its value is through the Object.prototype.toString method.
This method returns a string formed by:
"[object " + this.[[Class]] + "]"
Only for expository purposes because [[Class]] cannot be accessed directly.
For example:
Object.prototype.toString.call([]); // "[object Array]"
Object.prototype.toString.call(/foo/); // "[object RegExp]"
Object.prototype.toString.call({}); // "[object Object]"
Object.prototype.toString.call(new Date); // "[object Date]"
// etc...
This is really useful to detect the kind of an object in a safe way, for detecting array objects, it's the most widely used technique:
function isArray(obj) {
return Object.prototype.toString.call(obj) == '[object Array]';
}
It might be tempting to use the instanceof operator, but that way will lead to problems if you work on cross-frame environments, because an array object created on one frame, will not be instanceof the Array constructor of another.
The above method will work without any problems, because the object will contain the value of its [[Class]] internal property intact.
See also:
instanceof considered harmful (or how to write a robust isArray)
Object.prototype.toString
Object Internal Properties and Methods
Because toString is mostly not invoked with a parameter, not toString('foo'), but bar.toString(). Which is where call comes in handy.
Different toStrings
I say "mostly" because there are different toStrings:
Object.prototype.toString returns a string representing object
Array.prototype.toString returns a string representing the specified array and its elements
Number.prototype.toString returns a string representing the specified Number object
String.prototype.toString returns a string representing the specified String object
Function.prototype.toString returns a string representing the source code of the function
Instance of Uses Separately
(new Object()).toString(); // "[object Object]"
["foo", "bar"].toString(); // "foo,bar"
(6).toString(2); // "110"
("meow").toString(); // "meow"
(function(){return 'x';}).toString() // "function (){return 'x';}"
Though all object prototypically inherit from Object, the latter ones don't inherit toString from Object's toString, which means that they're all different things and have different uses. To tell the type of an object, Object.prototype.toString is the useful one, since it returns a type:
Every object has a toString() method that is automatically called when the object is to be represented as a text value or when an object is referred to in a manner in which a string is expected. By default, the toString() method is inherited by every object descended from Object. If this method is not overridden in a custom object, toString() returns "[object type]", where type is the object type.
Call
Note that among them the only one that takes parameter is Number.prototype.toString, and it's for specifying base of the outcome number. Therefore, in order to invoke Object.prototype.toString for arrays, numbers and other object that has their own toString method, you need call to specify this:
Object.prototype.toString.call(Math); // [object Math]
Object.prototype.toString.call(new Date); // [object Date]
Object.prototype.toString.call(new String); // [object String]
Object.prototype.toString.call(Math); // [object Math]
// Since JavaScript 1.8.5
Object.prototype.toString.call(undefined); // [object Undefined]
Object.prototype.toString.call(null); // [object Null]

Categories

Resources