I'm curious about whether there is any way to fake out Array.isArray() with a user-defined object.
From the book JavaScript Patterns:
Array.isArray([]); // true
// trying to fool the check
// with an array-like object
Array.isArray({
length: 1,
"0": 1,
slice: function () {}
}); // false
That object clearly fails, but is there any other way to do it? This is sheer curiosity, and not because I think that you could ever screw with .isArray() in regular client code (though it would obviously be fantastic to know if you could!).
Only if you set the internal [[Class]] property to "Array", which is not possible afaik. From the specification:
The isArray function takes one argument arg, and returns the Boolean value true if the argument is an object whose class internal property is "Array"; otherwise it returns false.
Or you go the other way round: Create a normal array and explicitly set every array method to undefined.
Array.isArray = function () { return true; }
And if you want to be naughty
Array.isArray.toString = function () {
return 'function () { [native code] }';
};
Related
Look at below code, what should it output ?
let obj = Object.create(null);
obj.valueOf = function () { console.log('hit valueOf!'); return "TO BE NaN";};
obj.toString = function () { console.log('hit toString!'); return "1";};
Number(obj)
// ?
According to professinal javascript, valueOf function returns "TO BE NaN" , and it will be convert to NaN, then toString function called.
Number Conversions
When applied to objects, the valueOf() method is called and the returned value is converted
based on the previously described rules. If that conversion results in NaN, the toString()
method is called and the rules for converting strings are applied.
As a matter of fact, it shows things here, function toString not called !
let obj = Object.create(null);
obj.valueOf = function () { console.log('hit valueOf!'); return "TO BE NaN";};
obj.toString = function () { console.log('hit toString!'); return "1";};
Number(obj)
// hit valueOf!
// NaN
Does it an error that professional javascript for web developers tell us how object convert to number?
Yes, that's a mistake in your book (and not the only one).
It should read more like1
When applied to objects, the valueOf() method is called and the returned value is converted based on the previously described rules if it is a primitive value. If that conversion results in NaN it returns an object, the toString() method is called and the rules for converting strings are applied.
Demonstrated:
const obj = Object.create(null);
obj.valueOf = function () { console.log('hit valueOf!'); return {};};
obj.toString = function () { console.log('hit toString!'); return "1";};
console.log(Number(obj))
1: Although still not quite correct. It should mention that the two methods are called only if they exist, and that an error is thrown if they both return an object.
Number(value), according to the specification, calls ToNumeric(value), which returns ToPrimitive(value, number). This second argument is the preferredType, resulting in:
If hint is string, then
Let methodNames be « "toString", "valueOf" ».
Else,
Let methodNames be « "valueOf", "toString" ».
For each element name of methodNames, do
a. Let method be ? Get(O, name).
b. If IsCallable(method) is true, then
Let result be ? Call(method, O).
If Type(result) is not Object, return result.
So in the case of Number(obj), the valueOf method really is supposed to be invoked first.
In other words, whatever the following sentence came from is incorrect:
When applied to objects, the valueOf() method is called and the returned value is converted based on the previously described rules. If that conversion results in NaN, the toString() method is called and the rules for converting strings are applied.
I'm looking at what the Boolean object works. It can't be used as reference value transfer. Because the value can't be changed. What's the use of using the new operator? The problem can be solved by creating a new boolean object myself. But that doesn't answer the question, why doesn't there be a set function in the boolean object? Creating a boolean object means nothing to me. Because you can't do anything. Is there a solution other than creating a new object? and what does the boolean object do?
let bool=true;
let boolObj=new Boolean(true);
let ref=boolObj;
//set booObj false
console.log(ref.valueOf());//expected out:false
Is there a solution other than creating a new object?
If the problem is that you want an object with mutable boolean state, then yes, that's the solution:
const boolObj = {flag: true, valueOf() { return this.flag; }};
boolObj.flag = false;
console.log(boolObj.valueOf());
Note that that uses boolObj.flag = false;, not boolObj = false;. The latter would store false in boolObj, not modify the state of the object.
What's the use of using the new operator?
There is almost never any reason to create a Boolean object. Boolean objects, like all the primitive wrapper objects, are immutable. Their primary purpose is to provide a specification mechanism by which "methods" can be called on primitives:
const b = false;
console.log(b.toString()); // "false"
b is a primitive, so how can it have a method? The answer is: It can't. But when the JavaScript engine sees b.toString, it "promotes" the primitive to the equivalent object and then gets the method from that equivalent object. (Theoretically; obviously, engines optimize that object creation away when they can.) This doesn't mean much with the built-in methods, but you can add methods. Before ES5's strict mode, that meant that there had to be an object representation of the primitive:
Object.defineProperty(Boolean.prototype, "example", {
value() {
console.log("typeof this = " + typeof this);
return !this;
},
configurable: true,
writable: true
});
false.example();
That was necessary because before ES5's strict mode, this always had to be of type "object" (null or a reference to an object), it couldn't be a primitive. As of ES5's strict mode, this is allowed to be a primitive:
"use strict";
Object.defineProperty(Boolean.prototype, "example", {
value() {
console.log("typeof this = " + typeof this);
return !this;
},
configurable: true,
writable: true
});
false.example();
I said "almost never" above because there is one use case for Boolean objects, but it's not a very good one: Tristate flags. You can use null for the indeterminate state, new Boolean(true) for the true state, and new Boolean(false) for the false state. Again, though, it's not a great use case. :-)
I am fairly new to programming and have come across this problem when exploring objects. It appears that an if-statement can search for a property inside of an object without the use of hasOwnProperty() or the keyword 'in' or anything else for that matter. You can just type something like:
if (object.property) {code here};
I searched the web but no content on why this is possible. Except some shallow discussions on truthy or falsy concepts. Which almost helped but were to shallow. Below is the sample code I used to discover this problem
var obj = {
prop1: {
propa: "x",
propb: ["b", "q", "y"],
prop3: "y",
prop4: "zz"
}
},
output = document.getElementById("output");
if (obj.prop1) {
output.innerHTML = "The propery exist."; //The property exist shows.
} else {
output.innerHTML = "The property does not exist.";
}
So the question is What is the process that a Javascript if-statement performs to return a boolean answer from a statement such as if (object.property) {}?
Like all programming languages, JavaScript expects an expression evaluating to a boolean value between the braces in if (expr). Now, when the expression does not evaluate to a boolean value, JavaScript uses what is known as coercion to convert the value. That is, it implictly runs if(Boolean(object.property)) {} when evaluating if (object.property) {}.
The outcome of this operation depends on the value of object.property and you may consult this table for how this works:
https://dorey.github.io/JavaScript-Equality-Table/
Or read the documentation on truthiness semantics from the docs.
Note however the difference between your discovery and checking whether a property exists:
const object = { property: false };
if (object.property) {
console.log("No go. The value evaluates to false.")
}
if ("property" in object) {
console.log("Yes. The property exists.");
}
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();
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."