I know that all object properties have a name and have attributes like value, configurable, enumerable and writable. But in this post I read that objects too have attributes like prototype, class and extensible.
I understand that prototype attribute is for pointing for the parent object. But what I don't understand is what's class attribute? Is there such attribute? And isn't extensible is a method of object as isExtensible() ?
In this post I read that objects too have attributes like prototype, class and extensible.
They're not called "attributes" normally but internal slots. Usually they are denoted by double brackets to differentiate them from normal properties, i.e. [[prototype]], [[class]] and [[extensible]].
What is the [[class]] attribute? Is there such attribute?
Not in ES6 any more. The [[class]] internal slot contained information on which kind of builtin type (e.g. Array, RegExp, builtin wrapper) the object was. It was shown when you used the Object.prototype.toString method on the object. (Have a look at Why can Object.prototype.toString.call(foo) detect foo's type? or Why does `Object.prototype.toString` always return `[object *]`? for more details - it was also the best way to detect whether an object is an array before Array.isArray was available).
Since ES6, there is no such internal slot any more and Object.prototype.toString relies on the Symbol.toStringTag mechanism now.
And isn't extensible a method of object as isExtensible()?
No, the [[extensible]] internal slot is the thing that isExtensible() accesses, and that Object.preventExtensions() can set.
Related
I've read and tried understanding other answers similar to this question as well (like this one), But still the concept of prototypal inheritance is not very clear to me. and right now the thing that's confusing me the most is, that what is the actual difference between __proto__ and [[ Prototype ]]? As far as I've been able to understand is that [[ Prototype ]] is an "internal linkage that ties one object to another". But it gets ambiguous when I see a tutorial on youtube, because whenever they create an object and if they try to log it using console.log in their browser's console then it actually has the __proto__ property in it but when I try to do the same it outputs [[ Prototype ]] instead. So I'd like to know why is it so? and what is an "internal link"? Thanks in advance! :)
Below's the code that outputs "[[ Prototype ]]" in chrome and "<prototype>" in firefox.
function User(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
const user = new User("Someone", "Something");
console.log(user);
Each object's prototype is saved in the internal slot named as [[prototype]] and __proto__is just a getter/setter, defined in the Object.prototype object, to get the value of the [[prototype]] internal slot of any object.
Example:
const arr = [];
Each instance of an array gets Array.prototype as its prototype. So, in the above declaration of arr, [[prototype]] internal slot contains a reference to Array.prototype and in the following expression:
arr.__proto__ === Array.prototype // true
arr.__proto__ gets the Array.prototype object from the internal [[prototype]] slot.
As mentioned above, __proto__ is just a getter/setter that gets the value of [[prototype]] internal slot and is only there for compatibility reasons. It shouldn't be used in modern javascript code; following two methods should be used to set/get the prototype of any object:
Object.setPrototypeOf()
Object.getPrototypeOf()
There are other internal slots, apart from [[prototype]], mentioned in the Ecmascript specification and these internal slots are not accessible by the javascript code we write.
If you need to know more about internal slots, read:
What is an "internal slot" of an object in JavaScript?
The double square bracket notation comes from the ECMAScript specification where it always refers to an internal entity (field, attribute, slot,...) but is not a notation you can use in JavaScript code. It is information for the implementer of the language and helps to precisely define the behaviour of the language.
In a console you may see information represented with these double brackets, as is the case in the Chrome console. Firefox uses a different notation: <prototype>.
Now to the core of your question. The link between an object and its prototype object is not an own JavaScript property of that object. It is an internal slot:
Internal slots correspond to internal state that is associated with objects and used by various ECMAScript specification algorithms. Internal slots are not object properties and they are not inherited.
You can get the prototype object via .__proto__, but that __proto__ property is a getter on the Object.prototype object. So that is like running in circles: when you write obj.__proto__, the engine needs to know what the prototype chain is before it can find that __proto__ value for you, since it needs to get it via inheritance -- it is not a property of obj itself. And to find the inheritance link the engine will use the internal "slot" [[Prototype]].
I'm a little unclear on how RegExp objects are implemented in the ES spec even after reading the section on regular expression objects. I had assumed that all the properties (like flags, source, global, multiline) were instance properties since they contain data for a specific RegExp object, but MDN lists them as properties of the prototype instead.
How does that work? Are they defined as accessors on the prototype which check the value of hidden instance fields?
This snippet pretty much answers your question:
console.log(
Object.getOwnPropertyNames(RegExp.prototype).filter(
key => typeof Object.getOwnPropertyDescriptor(RegExp.prototype, key).get === 'function'
)
)
The answer is yes, RegExp.prototype defines getters for each of the member values that looks up values from internal slots on the instance object. You could have also looked at the ECMAScript specification to figure that out as well.
I think the spec is quite clear. The're own properties of the RegExp instance, created in the constructor.
Or at least, that's how it was in ES5. Since ES6, the properties are indeed getters on the prototype that access an immutable internal slot which is initialised from the constructor or .compile(). There's even a note:
Prior to ECMAScript 2015, RegExp instances were specified as having the own data properties ``source, global, ignoreCase, and multiline. Those properties are now specified as accessor properties of RegExp.prototype.
So your assumption was well founded, but MDN is correct as well :-)
Is it possible to add a Method to all Javascript Prototypes (Object,array,function,string,number,boolean)?
Just for Example.
If i would like to add a new Prototype getter, which returns the Type of the Variable, the create Timestamp or something else, how could I do that?
For Information: It's not about what this function does!
Edit:
I would like to access the Function like every other Prototypen Function:
myVariable.myMethod(myParam)
Every JavaScript variable is either an object, or it auto-boxes to an object (like string, boolean and number), or it is null or undefined explicitly.
So, it seems like if you want to add a method to all those, you can add a function to Object.prototype which they all extend like Bar suggested.
Object.prototype.myMagic = function(){
console.log("Hello");
};
"thisString".myMagic();
15.13.myMagic();
([]).myMagic();
Note that you are in fact not adding a function to the prototype of a string since a string is a primitive value and doesn't have a prototype, rather, you're adding a method to the prototype of Object - and strings "box" to String instances (which are objects) that extend Object and will have this method.
Also note that on ES5 systems, it's possible to create objects that do not extend Object.prototype via Object.create(null), in ES6 it's also possible to modify the prototype of objects via setPrototypeOf or __proto__. However, outside those edge cases it should work.
You can add it to Object.prototype. All other prototype instances extend Object.prototype, and will inherit it from there.
Object.prototype.myMethod=function() {
// ... whatever
};
Please note that extending built-in prototypes is not a recommended practice for "real-world" code.
I found a great description of the semantic difference between Properties and Methods (paraphrased, via http://www.webdeveloper.com/forum/showthread.php?133712-Properties-Vs.-Methods):
Properties are like nouns. They have a value or state.
Methods are like verbs. They perform actions.
A property can't perform an action and the only value that a method has is the one that is returned after it finishes performing the action.
e.g.
Property: door; Possible Values: open, closed
Method: openDoor; Action: to change the value of the door property to "open"
Creating an example: I understand this in theory but I can't come up with an example. Would it be possible to show me how the door/openDoor would look in actual Javascript code?
Really, you need to back up and read some of the links posted above. But as a quick example:
var house = {} ;
house.isDoorOpen = false ;
house.openDoor = function(){
house.isDoorOpen = true ;
}
Here house is the object. It has a property: house.isDoorOpen. Here, it is more like an adjective. Either the door is open (true) or closed (false). As it sounds, it describes a property of the house.
Also, it has a method openDoor (which is used like this: house.openDoor() ). That's something that it can do. In this case, the action openDoor affects the isDoorOpen property, making it true.
Let's look at how the javascript spec ECMA-262 describes the term property
http://www.ecma-international.org/ecma-262/5.1/#sec-4.3.26
4.3.26 property
association between a name and a value that is a part of an object
NOTE Depending upon the form of the property the value may be
represented either directly as a data value (a primitive value, an
object, or a function object) or indirectly by a pair of accessor
functions.
4.3.27 method
function that is the value of a property
NOTE When a function is called as a method of an object, the object is
passed to the function as its this value.
Also
Javascript's definition of attribute is different from Java's
4.3.29 attribute
internal value that defines some characteristic of a property
for in, loops through an object's enumerable properties, and that includes its functions
http://eloquentjavascript.net/1st_edition/chapter8.html
"A function is called as a method when it is looked up as a property,
and immediately called, as in object.method()."
There does seem to be a more standard definition of property..
https://en.wikipedia.org/wiki/Property_(programming)#JavaScript
"A property, in some object-oriented programming languages, is a
special sort of class member, intermediate between a field (or data
member) and a method. .... Some object-oriented languages, such as
Java, don't support properties, and require the programmer to define a
pair of accessor and mutator methods instead."
In that more standard, non-javascript definition of property
C# has properties, and Java doesn't have properties
Object in JavaScript is just key-value pairs stored in a Hash. The difference between b/w property and method is that - property is a value stored in the hash key, whereas method is a function stored in the hash key.
I am aware that the for in loop can help iterate through properties of objects, prototypes and collections.
The fact is, I need to iterate over String.prototype, and though console.log(String.prototype) displays the complete prototype, when I do
for (var prop in String.prototype) {
console.log(prop);
}
to display the name of the elements in the prototype, it displays nothing, as if it were empty.
Do the JavaScript engines hide the basic prototypes methods, or am I doing something wrong?
The specification says:
If the value of an attribute is not explicitly specified by this specification for a named property, the default value defined in Table 7 is used.
Table 7 — Default Attribute Values
...
[[Enumerable]] false
So it is not enumerable (as with all built-in properties).
Like others have said, all properties in String.prototype are non-enumerable. To get a list of all the properties, including non-enumerable, use Object.getOwnPropertyNames() (newer browsers only)
Native methods aren't visible through an for(prop in obj) iteration.
It's possible to find properties when you loop through a built-in object. In this case, the page has extended the prototype with a custom method. Frameworks (such as jQuery) often modify built-in objects in this way.