Are string literals objects or not? - javascript

Trying to get my JavaSscript fundamentals strong. So the question is about string literals. Aren't they Objects? If your answer is 'yes' then my question is why is instanceof returning false?
> var s = new String
> s.constructor.toString()
function String() { [native code] }
> typeof s
object
> s instanceof String
true
> s instanceof Object
true
> s instanceof Number
false
So far so good.
> typeof 'c'
string
> 'c' instanceof Object
false
> 'c' instanceof String
false
> 'c'.length
1
> 'c'.charAt(0)
c
> 'c'.constructor.toString()
function String() { [native code] }

String literals are primitives (String values), String objects can be created with the String constructor in a new expression:
"foo" instanceof String // false
new String("foo") instanceof String // true
Edit: Something that seems to be confusing (by looking at the accepted answer here), is that you can still access properties defined on the prototype objects of primitive values, for example:
"foo".indexOf == String.prototype.indexOf // true
"foo".match == String.prototype.match // true
String.prototype.test = true;
"foo".test // true
true.toString == Boolean.prototype.toString
(3).toFixed == Number.prototype.toFixed // true
// etc...
The reason of that relies on the Property Accessors, the dot notation . and the bracket notation [].
Let's give a look to the algorithm in the ECMA-262 specification:
The production MemberExpression : MemberExpression [ Expression ] (or MemberExpression . Identifier) 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).
In the Step 5, the ToObject internal operator type-converts the MemberExpression to object, depending on it's type.
The primitives are converted to Objects without noticing, and that's why you can access the properties defined on the prototype.

Great explanation of this here. Copied for reference below.
That's because those things are primitives, and unless they need to be used as objects (when you are calling methods on them, for example) they remain so. The only time they "become" objects is when they need to be wrapped. If you are familiar with the concept of "boxing" in .NET, then think of it in that way.
Here is an example - take a look at this code:
Number.prototype.times = function(func) {
for(var index = 1; index <= this; index++) {
func(index);
}
};
So, the following code will fail:
3.times(print); // assume 'print' writes to standard out
3, by itself is a primitive. That said, the following will work:
(3).times(print); // assume 'print' writes to standard out
That would display the numbers 1, 2, and 3. Because of the parenthesis, the JavaScript interpreter will temporarily wrap the primitive 3 in a Number object, call the method, and then garbage collect the object since it isn't needed any longer.
Anyway, a full discussion of this can be found in "JavaScript: The Definitive Guide."

Related

Are there any built-in methods for undefined data type in JavaScript?

Asking this question I want to evaluate the following statement true or false:
"There are methods built-in to every data type in JavaScript"
As undefined in data type in JavaScript. I try to find any build-in method for an "undefined" but it appears that it's an only primitive type that does not have one. Or there are some?
let undef = void 0;
console.log(undef.anyPotentialBuildInMethod());
Does any "anyPotentialBuildInMethod()" exists?
Methods are functions that are properties of objects.
Trying to read any property of undefined throws an exception.
undefined has no built-in methods and cannot be assigned any.
const foo = undefined;
console.log(foo.sampleMethod);
While it might appear so, not everything in Javascript is an object. Primitive values (like "foo", 12.34, undefined etc) are not objects and cannot have methods or properties. However, Javascript hides that fact by dynamically boxing (or "coercing") primitive values into objects when you access their properties. So when you do
x = "foo".length
what actually happens is
1. temp = new String("foo") // dynamically coerce a primitive value into an object
2. x = temp.length // get a property of that object
3. destroy temp // delete a temporary object
(Of course, Javascript engines don't actually allocate and then discard these temporary objects, this is just an algorithm defined by the standard, see (1) below).
Two primitive values: null and undefined are exception of this rule: any attempt to coerce them results in a TypeError. So when you do
x = undefined.something
Javascript tries to create a temporary object like in the step 1 above and fails.
The bottom line: null and undefined cannot have properties, because they are primitive values and cannot be converted to objects.
References:
https://262.ecma-international.org/11.0/#sec-getvalue
https://262.ecma-international.org/11.0/#sec-evaluate-property-access-with-identifier-key
https://262.ecma-international.org/11.0/#sec-requireobjectcoercible
No, property access on undefined always throws a TypeError in a standards-compliant engine.
From ECMA-262, 11th Ed., §12.3.2.1:
MemberExpression : MemberExpression [ Expression ]
[…]
Return ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict).
[…]
MemberExpression : MemberExpression . IdentifierName
[…]
Return ? EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict).
In both §12.3.3 and §12.3.4 have:
Let bv be ? RequireObjectCoercible(baseValue).
And in §7.2.1 we have:
The abstract operation RequireObjectCoercible throws an error if argument is a value that cannot be converted to an Object using ToObject. It is defined by Table 15:
Table 15: RequireObjectCoercible Results
Argument Type
Result
Undefined
Throw a TypeError exception.
Null
Throw a TypeError exception.
The only thing that can possibly be considered an exception is the document.all object, which compares loosely-equal (== not ===) to both undefined and null, and returns 'undefined' when passed to the typeof operator, but actually has properties. This is specified in §B.3.7; before the 9th edition of the standard, it was actually contrary to the specification.
I'm not sure of the reason why you are asking this, but, to let you understand better, what you are trying to do is like trying (but not the same) to find an 'x' value so that (0 * x) != 0; 0 is 0 and whethever you use as 'x' you got 0.
And 'undefined' var in javascript is nothing. This is because 'var' doesn't have a type, it can be string, integer, object, function ecc
you can do
var test = "test";
console.log(test);
test = 1;
console.log(test);
and so on, and you'll get no error. var are evauated at execution time, and and undefined var is simply a pointer to nothing so you can't have a function or a property in that

Why is 'true instanceof Boolean' equal to false in JavaScript [duplicate]

This question already has answers here:
Why does instanceof return false for some literals?
(10 answers)
Closed 7 years ago.
The following indicates the expression "true instanceof Boolean" evaluates to false. Why would this expression evaluate to false?
$(document).ready(function() {
var $result = $('#result');
if(true instanceof Boolean) {
$result.append('I\'m a Boolean!');
} else {
$result.append('I\'m something other than a Boolean!');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="result"></div>
The value true is a boolean primitive — that's "boolean" with a lower-case "b". It is not an object.
Similarly, "hello" is not an instance of String, because a string primitive is not an object either.
You can test for primitive types with the typeof operator.
The distinction between primitive values and object values can be a little confusing in JavaScript because the language implicitly wraps primitives in appropriate object wrappers when primitives are used like object references. That's why you can write
var length = "hello world".length;
The string is implicitly converted to a String instance for that . operation to work. You can even do that with a boolean:
var trueString = true.toString();
It happens with numbers too, though the syntax gets in the way sometimes:
var failure = 2.toString(); // an error
var success = (2).toString(); // works
The Boolean object is an object wrapper for a boolean value.
So the boolean value and the wrapper object are not the same thing.
Also, boolean objects are verboten. In other words it isn't good style to ever use a Boolean object.

What are the benefits / advantages of `in` operator in JavaScript?

in operator seems to be available since forever ago.
var obj = {foo: 'bar'};
if ('foo' in obj) {
console.log(obj.foo);
}
if (undefined !== obj.foo) {
console.log(obj.foo);
}
The two if blocks in the code above do the same thing. This example itself may be too simple, but by reading MDN, to me, I wouldn't use it. Besides typing less characters and readability, are there any benefits / advantages that I don't see? Can you give me a good example of in operator usage?
From MDN:
If you set a property to undefined but do not delete it, the in operator returns true for that property.
So, the in operator can be used to find if a property exists in an object, even if it is undefined. The second way you show, undefined !== obj.foo, will return false if the property doesn't exist, OR is undefined.
Example:
var obj = { myProp: undefined };
'myProp' in obj; // = true
obj.myProp !== undefined; // false
I can see this being useful if you want to confirm that a property exists on an object before assigning a value to it, since the assignment will work even if the property didn't previously exist.
Here's some example that shows a use case for this:
var obj = { foo: undefined }
obj.foo !== undefined; // false
'foo' in obj; // true
When using the in operator, you test if the property is specified in the given object and not its value.
Using the in operator in javascript we not also can check for a particular property but can iterate over the list.
The ES 5 specification details two distinct syntaxes for the for-in statement:
1.for (var variable in objectExpression) {statement}
2.for (LeftHandSideExpression in objectExpression) {statement}
For Ex.
If i have an Array object like
var objarray=new Array('rakesh','naresh','dinesh','nilesh');
then i can directly loop over the Array Object.
for(var a in objarray)
{
console.log(objarray[a])
};
The output we get is:
rakesh
naresh
dinesh
nilesh
So the 'in' operator has other benefits other than only checking value.

Javascript complicated valueOf method [duplicate]

This question already has answers here:
Object.prototype.valueOf() method
(2 answers)
Closed 9 years ago.
What does ({}).valueOf.call(myvar) do?
it converts any value to an object (an object remains unchanged, a primitive is converted to an instance of a wrapper type).
My question is how?Can someone give The longer answer how this is done behind the scene.Since valueOf() method is meant to return primitive values not object .
console.log{name:"sameer"}.valueOf() //returns an object but cant be displayed since toString() method will be called by js so [object Object] gets displayed which is a string ,how to display the exact return value from valueOf() method .Is there a way?
Hello again! Once more, we face the mighty opponent. Before we begin, let's dispel one false thought:
valueOf() method is meant to return primitive values not object .
Not accurate. valueOf returns an object if a primitive value was passed to it. If you do valueOf(object), you'd get the same object: valueOf(object) === object. You can trivially see that:
var obj = {};
obj.valueOf() === obj; //true
Now, for the more interesting question: How is valueOf defined? Let's look at the ES5 specification along with the v8 and spidermonkey sources.
valueOf (spec, v8, spidermonkey):
function ObjectValueOf() {
return ToObject(this);
}
As we can see, it simply returns ToObject, as defined in the spec. The rabbit hole emerges.
ToObject (spec, v8, spidermonkey)
function ToObject(x) {
if (IS_STRING(x)) return new $String(x);
if (IS_SYMBOL(x)) return new $Symbol(x);
if (IS_NUMBER(x)) return new $Number(x);
if (IS_BOOLEAN(x)) return new $Boolean(x);
if (IS_NULL_OR_UNDEFINED(x) && !IS_UNDETECTABLE(x)) {
throw %MakeTypeError('null_to_object', []);
}
return x;
}
Jackpot. We can see the entire flow here. If it's a string, number, boolean, etc return a wrapper ($String and $Boolean and the likes represent the actual String or Number; see here); if it's an invalid argument, throw an error; otherwise, return the argument.
The spidermonkey source for that one goes deeper down the rabbit hole. It defines ToObject as such:
JS_ALWAYS_INLINE JSObject *
ToObject(JSContext *cx, HandleValue vp)
{
if (vp.isObject())
return &vp.toObject();
return ToObjectSlow(cx, vp, false);
}
So if it's not an Object, call ToObjectSlow. Buckle up Alice, there'll be C++. We need to take a look at what ToObejctSlow does:
JSObject *
js::ToObjectSlow(JSContext *cx, HandleValue val, bool reportScanStack)
{
if (val.isNullOrUndefined()) {
...error throwing magic here...
return NULL;
}
return PrimitiveToObject(cx, val);
}
More indirection after looking whether the argument was null or undefined. The finale is here:
JSObject *
PrimitiveToObject(JSContext *cx, const Value &v)
{
if (v.isString()) {
Rooted<JSString*> str(cx, v.toString());
return StringObject::create(cx, str);
}
if (v.isNumber())
return NumberObject::create(cx, v.toNumber());
JS_ASSERT(v.isBoolean());
return BooleanObject::create(cx, v.toBoolean());
}
Pretty much the same as the v8 version, only with different taxonomy.
Now, as I said before, I think your question has more to do with the medium of representing the object you see. Firebug and chrome's devtools are more than apt at displaying an object. However, if you try to alert it, you'll see the unfortunate [object Object], because that's what ({}).toString() gives you (since it gives out a string of the form [object InternalClassName], again, as we've seen before).
As a bonus, try console.dir({foo : 'bar'})
To answer your first question
JavaScript has two main variable category types, primitives and Objects. You will often hear this, in JS everything is an Object. That is not entirely accurate. There are also primitive data types, which do nothing but hold values.
They have no methods and they are not instances of a wrapper type. So before you can call any method on them, they need to be converted to an object of the wrapper type. In JavaScript this conversion is automatic and it is called auto-boxing.
Allow me to demonstrate:
var firstString = "Test";
typeof firstString == "string"; // true
var secondString = new String("Test");
typeof secondString == "string"; // false
secondString.prototype.toString.call// [object String];
Notice what happens. There are actually two types above. One is string and the other one is [object String]. This tells you two things: secondString instanceof String is true. That is a wrapper type. Inside the core language you are seeing that String inherits from Object.
But the first string is just a memory reference, nothing more. When you call methods like firstString.replace(), firstString is automatically converted to its wrapper type. This is autoboxing.
The above behaviour stands for the following pairs:
Number autoboxing
var x = 5; var y = new Number(5);,
Boolean autoboxing
var x = false; var y = new Boolean(false);
RegExp autoboxing
var x = new RegExp("etc"); var y = /etc/;
Object.prototype.valueOf
The valueOf method is defined for any Object. In order for it to be called, it will convert all primitive types to their wrapper types and will leave existing objects unchanged. Now it will simply return the value held in the Object reference. So it's pretty simple and it is a way to FORCE AUTOBOXING. You are forcing the conversions I was mentioning earlier.
To answer your second question
Displaying the unfiltered result is simple. Use console.dir().
Look here.
({}).valueOf.call(myvar);
It is the exact equivalent of Object.prototype.valueOf.call(myVar);. Now you already know what valueOf does.
Assuming you know the way Function.prototype.call works, your statement will call the valueOf method in the scope of the object you pass as a this argument to Function.prototype.call(the first parameter is the this object reference).
var myvar = {
"name": "name"
};
({}).valueOf.call(myVar);
// is equivalent to
myVar.valueOf();

typeof for RegExp

Is there anyway to detect if a JavaScript object is a regex?
For example, I would like to do something like this:
var t = /^foo(bar)?$/i;
alert(typeof t); //I want this to return "regexp"
Is this possible?
Thanks!
EDIT: Thanks for all the answers. It seems I have two very good choices:
obj.constructor.name === "RegExp"
or
obj instanceof RegExp
Any major pros/cons to either method?
Thanks again!
You can use instanceof operator:
var t = /^foo(bar)?$/i;
alert(t instanceof RegExp);//returns true
In fact, that is almost the same as:
var t = /^foo(bar)?$/i;
alert(t.constructor == RegExp);//returns true
Keep in mind that as RegExp is not a primitive data type, it is not possible to use typeof operator which could be the best option for this question.
But you can use this trick above or others like duck type checking, for example, checking if such object has any vital methods or properties, or by its internal class value (by using {}.toString.call(instaceOfMyObject)).
alert( Object.prototype.toString.call( t ) ); // [object RegExp]
This is the way mentioned in the specification for getting the class of object.
From ECMAScript 5, Section 8.6.2 Object Internal Properties and Methods:
The value of the [[Class]] internal property is defined by this specification for every kind of built-in object. The value of the [[Class]] internal property of a host object may be any String value except one of "Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", and "String". The value of a [[Class]] internal property is used internally to distinguish different kinds of objects. Note that this specification does not provide any means for a program to access that value except through Object.prototype.toString (see 15.2.4.2).
A RegExp is a class of object defined in the spec at Section 15.10 RegExp(RegularExpression)Objects:
A RegExp object contains a regular expression and the associated flags.
Give the .constructor property a whirl:
> /^foo(bar)?$/i.constructor
function RegExp() { [native code] }
> /^foo(bar)?$/i.constructor.name
"RegExp"
> /^foo(bar)?$/i.constructor == RegExp
true
From underscore.js
// Is the given value a regular expression?
_.isRegExp = function(obj) {
return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
};
Works in google chrome:
x = /^foo(bar)?$/i;
x == RegExp(x); // true
y = "hello";
y == RegExp(y); // false
"Regexp" is not a native Javascript type. Most of the above answers tell you how to accomplish your task, but not why. Here's why.
There is no absolute way of checking this, so far the best answer is
var t = /^foo(bar)?$/i;
alert(t instanceof RegExp);//returns true
but there is one down side to this approach and that's it will return false if the regular expression object is commeing from an other window.
Here are two ways:
/^\/.*\/$/.test(/hi/) /* test regexp literal via regexp literal */
/^\/.*\/$/.test(RegExp("hi") ) /* test RegExp constructor via regexp literal */
RegExp("^/" + ".*" + "/$").test(/hi/) /* test regexp literal via RegExp constructor */
RegExp("^/" + ".*" + "/$").test(RegExp("hi") ) /* test RegExp constructor via RegExp constructor */
delete RegExp("hi").source /* test via deletion of the source property */
delete /hi/.global /* test via deletion of the global property */
delete /hi/.ignoreCase /* test via deletion of the ignoreCase property */
delete RegExp("hi").multiline /* test via deletion of the multiline property */
delete RegExp("hi").lastIndex /* test via deletion of the lastIndex property */
If a string literal is delimited by the regexp backslash delimiter, the regexp self test will fail.
If Object.seal or Object.freeze are run on a user-defined object, and that object also has all of the aforementioned properties, the delete statement will return a false positive.
References
ECMAScript 5, Section 15.10.4.1 new RegExp(pattern, flags)
What are some use-cases of when delete has been very useful in JavaScript?
Why is this configurable property not deletable?
Webkit JavaScriptCore source: ObjectConstructor.cpp
Object Properties in JavaScript
I was looking for typeof regex because I tried use it in type definition for TypeScript props on a function.
Then I do the next:
const RegexType = /$/;
type paramProps = {
regexParam: typeof RegexType;
}
You can test here:
const RegexType = /$/;
const t = /^foo(bar)?$/i;
console.log(typeof t == typeof RegexType) //true

Categories