Node.js querystring.parse() method returns what looks like to be an object, but one without a constructor. According to https://nodejs.org/api/querystring.html :
"... The object returned by the querystring.parse() method does not prototypically inherit from the JavaScript Object. This means that typical Object methods such as obj.toString(), obj.hasOwnProperty(), and others are not defined and will not work."
This easily causes bugs because typically you would assume that every Object understands some basic methods like toString() and that it has a "constructor" which more or less tells us its "type".
What's the best way to handle these rather incapable Objects? I tried:
let myOb = new Object(dumbObject);
But that produces a result which does not have the toString() -method either and does not have the property 'constructor'.
What's the best way to turn these dumb objects into ordinarily behaving ones? And, why would anybody want to create such objects in the first place?
I think (from the top of my head)
let newObject = JSON.parse(JSON.stringify(dumbObject))
should work.
If you want a more generic way to call toString() on an object, you can call it from Object.prototype using .call().
var s = Object.prototype.toString.call(smartObject);
But why? It's just going to give you "[object Object]" on any plain object. Why is it important to get that string?
var p = {};
var s = Object.create(null);
console.log(p.toString());
console.log(Object.prototype.toString.call(s));
typically you would assume
No, you wouldn't. If you make such assumptions, document them in your interface.
What's the best way to turn these dumb objects into ordinarily behaving ones?
Use Object.assign with an ordinary object as the target. Alternatively, you can also change the prototype by using Object.setPrototypeOf, but that's not recommended.
Or just create the properties like .toString or .constructor that you need. See this example.
And, why would anybody want to create such objects in the first place?
Because you need this safety when using objects instead of Maps. See this example.
Explicitly set the prototype of your dumb object with Object#setPrototypeOf
var dumbObject = Object.create(null);
Object.setPrototypeOf(dumbObject, Object.prototype);
dumbObject.toString() //runs fine
Thanks for all the answers, one of which contained a link to another question which really was my question as well, even if I didn't know that at first. That other question is: How to create a JS object with the default prototype from an object without a prototype?
From it I found the answer which I think is the simplest solution so far: Use Object.assign(). Like this:
let orphan = require('querystring').parse("{}") ;
// console.log ( "Got value: " + orphan ) ;
// Above causes the error:
// -> TypeError: Cannot convert object to primitive value
let oa = (x) => Object.assign({}, x);
console.log ("Got value: " + oa (orphan) ) ;
Note the issue is not particularly about "querystring" but with objects which have no prototype in general. Yes we should probably call these poor objects "orphans" instead of "dumb". But I think "dumb" is still quite good term as well. An object which has no prototype has very few (or no?) methods so it can answer very few if any questions we would like to ask it.
Related
Is it possible to make an object callable by implementing either call or apply on it, or in some other way? E.g.:
var obj = {};
obj.call = function (context, arg1, arg2, ...) {
...
};
...
obj (a, b);
No, but you can add properties onto a function, e.g.
function foo(){}
foo.myProperty = "whatever";
EDIT: to "make" an object callable, you'll still have to do the above, but it might look something like:
// Augments func with object's properties
function makeCallable(object, func){
for(var prop in object){
if(object.hasOwnProperty(prop)){
func[prop] = object[prop];
}
}
}
And then you'd just use the "func" function instead of the object. Really all this method does is copy properties between two objects, but...it might help you.
ES6 has better solution for this now. If you create your objects in a different way (using class, extending 'Function' type), you can have a callable instance of it.
See also: How to extend Function with ES6 classes?
Following the same line of #Max, but using ES6 extensions to Object to pass all properties and prototype of an object obj to the callable func.
Object.assign(func, obj);
Object.setPrototypeOf(func, Object.getPrototypeOf(obj));
Others have provided the current answer ("no") and some workarounds. As far as first-class support in the future, I suggested this very thing to the es-discuss mailing list. The idea did not get very far that time around, but perhaps some additional interest would help get the idea moving again.
https://esdiscuss.org/topic/proposal-default-object-method
"CALLABLE OBJECTS"
I haven't seen mention of this type of answer yet.. but this is how I do "callable" objects:
<< PSEUDO CODE >>
{...objectWithFunctionsInside}[keyString](optionalParams)
short example defining first, simplest and preferred method if I just want a "callable object," in my definition:
let obj = {
o:()=>{return("oranges")},
b:()=>{return("bananas")},
s:"something random here, doesn't have to be functions"
}
obj["o"]()
short example of nameless object being run within a function's return, with parameters (note parameters works in the first example too):
function autoRunMyObject(choice,param){
return{
o:(p)=>{return(p+"oranges")},
b:(p)=>{return(p+"bananas")},
}[choice](param)
}
autoRunMyObject("b","orange you glad I didn't say ")
and that's pretty much it
You could even get weirder with it and do nameless functions that auto-run themselves and produce an output right away... for no reason, lol.
... hit F12 and copy this code into your browser console and press enter, you'll get an output right away with the full string:
((autoparam="o")=>{return{
o:(p)=>p+"oranges",
b:(p)=>p+"bananas",
}[autoparam]("I guess this time it's ")})()
You could even pass in the string of "b" in the final parenthesis for a different output from the default "o".
Also, each of my examples (minus the pseudo code first example) are easily copy/paste-able into the browser console for quick testing -- it's a nice place to experiment with JS.
In summary -- this is how I like to do "callable objects"
It's much better than
SWITCH(){CASE:BREAK;};
statements and
IF{}ELSE IF(){}ELSE IF(){};
chains.
Incoming "noob" question:
Javascript has an includes method on arrays.
It looks like:
Array.includes()
But when I go to the Javascript Manual to understand this method, the heading on that page (for an appropriate technical reason, I realize) is:
Array.prototype.includes()
Similar things in the Javascript Manual have caused me to not like the manual at all (and alas, I rely on W3Schools more than the manual).
However, I really really want to learn to interpret the manual.
So, my question is: what's the significance of including the word .prototype in Array.prototype.includes() in the documentation, when the actual usage looks like: Array.includes()?
(Also, if anyone has suggestions on how I can improve my comprehension of the official Javascript Manual, I'd appreciate suggestions.)
So, my question is: what's the significance of including the word .prototype in Array.prototype.includes() in the documentation, when the actual usage looks like: Array.includes()?
The significance is that actual usage doesn't look like Array.includes():
Array.includes();
That will throw a TypeError: Array.includes is not a function because Array.includes doesn't exist. Accessing a non-existing property evaluates to undefined, so Array.includes evaluates to undefined and thus Array.includes() is trying to call undefined as if were a function.
You can see that in action here:
console.log(Array.includes);
undefined();
The includes() method is defined on the prototype of the Array global object so that you can call it on instances of Array:
[].includes();
You can see that [].includes is a function:
console.log([].includes);
Compare this to Array.from which is defined on the Array constructor, not on the Array prototype:
console.log(Array.from);
You can use it like this:
console.log(Array.from({ length: 10 }, (_, num) => num << 2));
If the documentation said Array.includes() you would literally type it like this (example):
Array.includes(1);
Instead it says Array.prototype.includes() which means it isn't called on the Array type itself, but on an instance of it. So in this case you would write:
const numbers = [1, 2, 3];
numbers.includes(1);
JavaScript is often described as prototype-based language, prototypes is simply how inheritance works in JavaScript.
What does prototype means ?
Both of us agree that almost everything in JavaScript is an object (I said "Almost" because primitives are not considered objects) cool?
Okay, now every Object in JS has an internal property called [[Prototype]] and by internal I mean that you can't access it directly the same way you access a JS object's property.
If we want to know the prototype of an object that we have created we either pass the instance of our object to Object.getPrototypeOf or through the __proto__ property of our object
For example:
let myArray = [1,2,3,4];
console.log(myArray.__proto__)
// Expected output: Array []
If you expand the resulting object you get from the little code snippet above you will find the includes method you were asking about and all of the methods available on any array you create in a JS code!
That's because myArray and all arrays in JavaScript are said to share the properties and methods defined on Array.prototype!
Now, if you look again at the methods of the resulting object which you have from the code snippet above you will notice a method called constructor, defined on the Array.prototype just like includes and the other methods
That's the function invoked when you create an instance of the JavaScript Array object!
What do we mean by the JavaScript Array object?
It's a global JavaScript object that is used in the construction of arrays, it's the Array in Array.prototype.includes() (you may call it a class for convenience buuuuut classes did not exist practically until the release of ES6...before then there was no such thing as class in JS)
So to keep it simple and wrap it up think of Array as the global object that alll JS arrays are instances of, and think of Array.proto as it's prototype which wraps the properties and methods that all of its instances share!
And regarding the documentation, being able to read the documentation and have a considerable understanding of what you read is actually something good so I believe you're just fine !
how the prototype works ? why the "xc" can not be accessed from e object?
please look down to the code , see the comments , i testing it in the chorme
var x={a:"xa",b:"xb",c:"xc"};
var e={a:"ea",b:"eb"};
console.log(Object.prototype); // this is {} why? i am expecting it to be null
console.log(e.prototype);
e.prototype=x;
console.log(e.prototype);
console.log(x.c);
console.log(e.c);//this is undefined , why? i am expecting it to be "xc"
console.log(e.a);
console.log(e.b);
console.log(e.prototype.a);
console.log(e.prototype.b);
i first think it would useful in css merging ,later i think for working out the dependency, then re-write css is more reasonable, however the knowledge is real. thanks very much.
var css={
'classSelectorExpressionIDOnly1':{
css_Ruls_name1:xxxx,
css_Rulss_name2:xxxx
}
'classSelectorExpressionIDOnlyX':{
css_Ruls_name1:xxxx,
css_Rulss_name9:xxxx
}
'classSelectorExpressionIDOnly2':{ '()inherit':["classSelectorExpressionIDOnly1","classSelectorExpressionIDOnlyX"]
css_Ruls_name3:xxxx,
css_Rulss_name5:xxxx
}
}
var mergeResult = Object.create(css.classSelectorExpressionIDOnly2);
for(var entry in mergeResult){
mergeResult[entry]= mergeResult[entry];
}
mergeResult.__proto__=css.classSelectorExpressionIDOnly1;
for(var entry in mergeResult){
mergeResult[entry]= mergeResult[entry];
}
mergeResult.__proto__=css.classSelectorExpressionIDOnlyX;
for(var entry in mergeResult){
mergeResult[entry]= mergeResult[entry];
}
------dependency re-write--------
.classSelectorExpressionIDOnly1,.classSelectorExpressionIDOnly2{
css_Ruls_name1:xxxx,
css_Rulss_name2:xxxx
}
.classSelectorExpressionIDOnlyX,.classSelectorExpressionIDOnly2{
css_Ruls_name1:xxxx,
css_Rulss_name9:xxxx
}
.classSelectorExpressionIDOnly2{
css_Ruls_name3:xxxx,
css_Rulss_name5:xxxx
}
That's not what the .prototype property is for. Despite the name, the .prototype property of functions isn't actually the prototype of the objects you're used to working with. This is one of the hardest things to understand about JavaScript, so it's not just you.
The key to understanding the prototype system in JavaScript is that the new operator creates two objects, not one. I'm going to talk about this in terms of four variables:
[[myPrototype]]
The prototype of an object. Every object theoretically has one (though for some objects, it might be undefined).
[[Constructor]]
The function that is being called with the New operator
[[newObject]]
The object that will eventually be returned
[[newPrototype]]
The object that will become [[newObject]].[[myPrototype]]
Note that these aren't valid JavaScript names (in fact, they're not valid names in most programming languages). All of this happens behind the scenes, and most implementations don't use these names either. I'm doing this to make clear that you can't normally see these objects.
When you use the new operator, JavaScript does roughly the following steps.
Create an object [[newPrototype]].
Set [[newPrototype]].[[myPrototype]] to [[Constructor]].prototype
Create an object [[newObject]].
Set [[newObject]].[[myPrototype]] to [[newPrototype]]
Set [[newObject]].[[myPrototype]].constructor to [[Constructor]]
Call [[Constructor]], with [[newObject]] as "this".
Note that [[newObject]].[[myPrototype]] isn't a perfect match for either [[newObject]] or [[Constructor]].prototype. That's why we need a third object between them: it carries the information you want to inherit (through [[newPrototype]].[[myPrototype]]), but it also carries information specific to the object you're creating (in [[newObject]].constructor).
And so we get to what the .prototype function is for. It's not the function's [[myPrototype]], and it's not the [[myPrototype]] for the objects you create with new. It's actually two levels back in the prototype chain, not one.
I hope this explanation helps you understand what the .prototype function is for. This isn't simple stuff, and not every explanation clicks with everybody. That's part of why we have so many explanations here.
When you first create an object, you can set its prototype directly with Object.create(). This function works with IE9 and higher (plus all other modern browsers), and it can be polyfilled if you need to work with older browsers. To see that prototype later, you use Object.getPrototypeOf(), which also has decent browser support (though IE only supports it in version 9 and higher). Using only these two functions, you might create your objects like this:
var x = {a:"xa",b:"xb",c:"xc"};
var e = Object.create(x);
x.a = "ea";
x.b = "eb";
console.log(Object.getPrototypeOf(Object));
console.log(Object.getPrototypeOf(e));
console.log(x.c);
console.log(e.c);//this is undefined , why? i am expecting it to be "xc"
console.log(e.a);
console.log(e.b);
console.log(Object.getPrototypeOf(e).a);
console.log(Object.getPrototypeOf(e).b);
Once an object has been created, there isn't a standard way to reset its prototype yet. ECMAScript 6 defines one (the Object.setPrototypeOf() function), but so far only Chrome and Firefox support it: IE and Safari do not. Still, if that's OK, you could do things like this:
var x = {a:"xa",b:"xb",c:"xc"};
var e = {a:"ea",b:"eb"};
console.log(Object.getPrototypeOf(object));
console.log(Object.getPrototypeOf(e));
Object.setPrototypeOf(e, x);
console.log(Object.getPrototypeOf(e));
console.log(x.c);
console.log(e.c);
console.log(e.a);
console.log(e.b);
console.log(Object.getPrototypeOf(e).a);
console.log(Object.getPrototypeOf(e).b);
There is a non-standard way to reset an existing object's prototype, and it even enjoys good browser support nowadays. To do this, you set the .__proto__ property on any standard object. You could use it like this:
var x = {a:"xa",b:"xb",c:"xc"};
var e = {a:"ea",b:"eb"};
console.log(object.__proto__);
console.log(e.__proto__);
e.__proto__ = x;
console.log(e.__proto__);
console.log(x.c);
console.log(e.c);
console.log(e.a);
console.log(e.b);
console.log(e.__proto__.a);
console.log(e.__proto__.b);
Now, onto your last question: why is Object.prototype equal to {}, rather than undefined? Because the Object constructor function has a .prototype property, which becomes the default prototype of all Objects created through it. The specs call this object [[ObjectPrototype]], and it's where things like the .hasOwnProperty() function live.
Have a look here:
https://stackoverflow.com/a/9959753/2768053
After reading that, you will turn your code into this:
var x={a:"xa",b:"xb",c:"xc"};
var e={a:"ea",b:"eb"};
console.log(Object.prototype.__proto__);
console.log(e.__proto__);
e.__proto__=x;
console.log(e.__proto__);
console.log(x.c);
console.log(e.c);
console.log(e.a);
console.log(e.b);
console.log(e.__proto__.a);
console.log(e.__proto__.b);
and you will get the results you expect :)
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How does JavaScript .prototype work?
Coming from Java background, I'm trying to understand javascript.
Please let me know if these are right.
Like in java, there is a supreme Object, from which all other objects inherit.
The prototype property is like a pointer that points to the parent object (classes in java)
For "Object" object, the prototype is null.
prototype property's values are strings denoting the objects nomenclature and aren't pointers like in C. The pointer concept is implemented using the hidden attribute,[[PROTOTYPE]] that is not accessible in script.
I'm using node.js instead of browser to learn JS.
I tried,
var human = Object.create(null); // same as var human;
console.log(Object.getPrototypeOf(human)); //null
var man = Object.create(human);
console.log(Object.getPrototypeOf(man));
//{}
//expected 'human'
var person = Object.create(Object.prototype); // same as var person = {}
console.log(Object.getPrototypeOf(person));
//{}
//expected 'object'
Yes, with the exception of Object.create(null) which doesn't inherit from anything.
Not sure what "parent object" is, but the prototype of a function consists of functions that are accessible by instances. Because Object.prototype.toString exists, so does {}.toString - it is inherited.
Yes, the prototype chain ends here.
No, .prototype (or the value returned by Object.getPrototypeOf) is an object which you can extend with properties, so that those properties are inherited by instances.
Your examples:
var human = Object.create(null); // same as var human;
No, it creates an empty object that doesn't inherit from anything. var human; sets human to undefined - which is not an object but a primitive value (not everything is an object in JavaScript).
var man = Object.create(human);
console.log(Object.getPrototypeOf(man));
//{}
//expected 'human'
Object.getPrototypeOf(man) returns the object human. This is an empty object; node shows it as {}. It is not a string. In fact, objects can be assigned to multiple variables. An object does not have a variable bound to it, so by design it is not possible at all to get a string. To check equality, you could do Object.getPrototypeOf(man) === human which yields true.
var person = Object.create(Object.prototype); // same as var person = {}
console.log(Object.getPrototypeOf(person));
//{}
//expected 'object'
This is indeed the same as {} - an empty object that inherits directly from Object. As said above, the prototype is Object.prototype and not a string. It looks empty but that's because Object.prototype's functions are available by default and hidden.
First, you need to read about the create method before you attempt to use it.
Second, invoke objects in the following manner:
var human = {}, man = {}, person = {};
Third, this is not Java. In Java classes and an understanding of classes are pretty important. Prototypes are completely optional in JavaScript. The only performance benefit offered by prototypes comes when you code makes heavy reuse of functions by reference in different scopes. If this style of coding does not apply to you then you likely do not need to use prototypes.
Prototypes are inherited from the parent, or some ancestor, object. A JavaScript parser will first look for local assignments and if none exist will then examine the current object's prototype for the presence of the named reference. In a nutshell this all you need to know at this early point in writing JavaScript.
Firstly, IMO, don't start off with node. Node is going to drag you into a pool of quicksand if you don't know javascript yet. Secondly, when I started off with function based code, then OO and only then I moved to prototypes. But if you really want to know, this question has already been answered over here. Feel free to ask me if you have any more questions!
I read a few questions and answers about javascript dictionary implementations, but they don't meet my requirements:
the dictionary must be able to take objects as keys
the values must be accessible by the []-operator
So I came up with the idea to overwrite the valueOf-method in Object.prototype, as follows:
Object.__id__ = 0;
Object.prototype.valueOf = function() {
if(!this.__id__)
this.__id__ = ++Object.__id__;
return "__id__" + this.__id__;
}
Object.prototype.toString = Object.prototype.valueOf;
//test
var x = {p1: "5"};
var y = [6];
var z = {};
z[x] = "7";
z[y] = "8";
console.log(z[x], z[y]);
I tested this with google-chrome and it seems to work well, but I'm a bit sceptical, whether this will cause some drawbacks, since it was so easy to implement.
Considering that the valueOf method is not used for other purposes in the whole code, do you think there are any disadvantages?
It's an interesting idea. I suggest my jshashtable. It meets your first requirement but not the second. I don't really see the advantage of insisting on using the square bracket property access notation: do you have a particular requirement for it?
With jshashtable, you can provide a hashing function to the Hashtable constructor. This function is passed an object to be used as a key and must return a string; you could use a function not dissimilar to what you have there, without having to touch Object.prototype.
There are some disadvantages to your idea:
Your valueOf method will show up in a for...in loop over any native object;
You have no way determining which keys should be considered equal, which is something you may want to do. Instead, all keys will be considered unique.
This won't work with host objects (i.e. objects provided by the environment, such as DOM elements)
It is an interesting question, because I had so far assumed that any object can be used as an index (but never tried with associative arrays). I don't know enough about the inner workings of JavaScript to be sure, but I'd bet that valueOf is used somewhere else by JavaScript, even if not in your code. You might run into seemingly inexplicable problems later. At least, I'd restrict myself to a new class and leave Object alone ;) Or, you explicitly call your hashing function, calling it myHash() or whatever and calling z[x.myHash()] which adds clutter but would let me, personally, sleep better ;) I can't resist thinking there's a more JavaScript-aware solution to this, so consider all of these ugly workarounds ;)
If you came upon this question looking for a JS dictionary where objects are keys look at Map Map vs Object in JavaScript