Javascript Closures vs Object.createProperty - javascript

My question is as follows : In most or all tutorials that I read about closures their first and foremost asset is described as them being able to define private members . For example , from the fabulous nettuts website : http://net.tutsplus.com/tutorials/javascript-ajax/digging-into-design-patterns-in-javascript/ .
My question is as follows - Why would you choose to create objects with closures , with their somewhat unnatural syntax , when you can use Object.definteProperty ? e.g
var o = {}; // Creates a new object
// Example of an object property added with defineProperty with a data property descriptor
Object.defineProperty(o, "a", {value : 37,
writable : false,
enumerable : true,
configurable : true});
// 'a' property exists in the o object and its value is 37
I must admit both ways are much longer than traditional OOP languages , but isn't the second way more natural ?
Why then are closures so popular , what other assets do they have and what is the difference between creating an object with a closure or with the way I just described?

Object.defineProperty still defines public properties, while closures allow privacy (you should not talk of private "members", it's just local variables).
Your example, using defineProperty to define a enumerable, writable and configurable data property can (and should) be abbreviated by the default property assignment (which works in older browsers as well):
o.a = 37;
Not all objects need to be created with closures (and in your example I can't think of any application), but you might want to learn How do JavaScript closures work?.

It is a matter of syntax preference and browser compatibility. One big gotcha, is if you want browser compatible code, the defineProperty method is only available in IE 9+ for non-dom objects.
As far as syntax goes, you can see that you loose a bit of what I call "visual encapsulation" when using defineProperty.
Each way has its own benefits, but both lack the simplicity of a language which supports privacy more directly.
Note:
I am assuming by priavate you mean you are setting the writable property to false.
Reference
MDN: defineProperty

Related

Mdn Docs __proto__ vs __proto__ Accessor

In mdn's doc's for the prototype chain, it states
All objects inherit the Object.prototype.__proto__ setter, which can be used to set the [[Prototype]] of an existing object (if the __proto__ key is not overridden on the object).
It then goes on to say that
Object.prototype.__proto__ accessors are non-standard and deprecated. You should almost always use Object.setPrototypeOf instead.
Along with this example:
const obj = {};
// DON'T USE THIS: for example only.
obj.__proto__ = { barProp: 'bar val' };
obj.__proto__.__proto__ = { fooProp: 'foo val' };
console.log(obj.fooProp);
console.log(obj.barProp);
The part that is confusing is they start the docs out with this example:
const o = {
a: 1,
b: 2,
// __proto__ sets the [[Prototype]]. It's specified here
// as another object literal.
__proto__: {
b: 3,
c: 4,
},
};
Stating that,
{ __proto__: ... } syntax is different from the obj.__proto__ accessor: the former is standard and not deprecated.
How is { __proto__: ...} different from obj.__proto__? Both are properties of an object, and I'm not quite clear on what the difference is here.
It's just the way the syntax was designed. (See here and here.) Assigning to the __proto__ of an existing object is deprecated, but specifying a __proto__ at the point when the object is created is not.
One reason for why an object literal can have it but doing so with an already existing object is not recommended is because, as MDN says on the subject of changing an object's prototype:
Warning: Changing the [[Prototype]] of an object is, by the nature of how modern JavaScript engines optimize property accesses, currently a very slow operation in every browser and JavaScript engine. In addition, the effects of altering inheritance are subtle and far-flung, and are not limited to the time spent in the Object.setPrototypeOf(...) statement, but may extend to any code that has access to any object whose [[Prototype]] has been altered. You can read more in JavaScript engine fundamentals: optimizing prototypes.
Because this feature is a part of the language, it is still the burden on engine developers to implement that feature performantly (ideally). Until engine developers address this issue, if you are concerned about performance, you should avoid setting the [[Prototype]] of an object. Instead, create a new object with the desired [[Prototype]] using Object.create().
In well-designed code, there should not be a need to dynamically change the internal prototype of an already existing object. In contrast, it's completely normal to want to specify an internal prototype when creating an object initially.
(Setting a new internal prototype of an object can be done with setPrototypeOf, which is not recommended, and by assigning to the object's __proto__, which is not only not recommended, but deprecated as well)

Difference between __proto__ and [[ Prototype ]] in javascript

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]].

Setting __proto__ to null and then re-setting it breaks instanceof in Javascript [duplicate]

This question already has an answer here:
__proto__ doesn't seem to work after a null assignment - bug or feature?
(1 answer)
Closed 7 years ago.
I came across some odd behaviour while messing around in JavaScript
function Class() {};
var a = {};
a.__proto__ = Class.prototype
a instanceof Class => true
Setting proto to null, and then re-assigning it the same value makes the instanceof operator return false rather than true.
a.__proto__ = null
a.__proto__ = Class.prototype
a instanceof Class => false
I'm directing your attention to: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto
Warning: Changing the [[Prototype]] of an object is, by the nature of how modern JavaScript engines optimize property accesses, a very slow operation, in every browser and JavaScript engine. The effects on performance of altering inheritance are subtle and far-flung, and are not limited to simply the time spent in obj.proto = ... statement, but may extend to any code that has access to any object whose [[Prototype]] has been altered. If you care about performance you should avoid setting the [[Prototype]] of an object. Instead, create a new object with the desired [[Prototype]] using Object.create().
And
Warning: While Object.prototype.proto is supported today in most browsers, its existence and exact behavior has only been standardized in the ECMAScript 6 specification as a legacy feature to ensure compatibility for web browsers. For better support, it is recommended that only Object.getPrototypeOf() be used instead.
In short, you're breaking things and then asking why they're broken. __proto__ isn't meant to be altered, and there isn't a standardized behaviour, so you can't depend on it doing what you want.
What are you trying to do? What is your end goal?
[![2 protos][1]][1]
Although i'm not sure why you'd do any of this, the inspector shows that the object has two proto properties. That is also an oddity, considering that property names should be unique. If you want somewhat of a semi explanation (non explanation), the two proto properties mess with instanceOf

Difference between proto link and Object.create

I want to know the difference between __proto__ and Object.create method. Take this example:
var ob1 = {a:1};
var ob2 = Object.create(ob1);
ob2.__proto__ === ob1; // TRUE
This implies Object.create method creates a new object and sets __proto__ link to the object received as parameter.
Why don't we directly use __proto__ link instead of using create method ?
__proto__ is nonstandard and won't be supported everywhere. Object.create is part of the official spec and should be supported by every environment going forward.
It also is implemented differently in different places.
From Effective Javascript:
Environments differ for example, on the treatment of objects with a
null prototype. In some environments, __proto__ is inherited from
Object.prototype, so an object with a null prototype has no special
__proto__ property
Moving forward the accepted way to create objects and implement inheritance is the Object.create function, and if you do need to access the prototype, you'll want to use Object.getPrototypeOf These functions are standardized and should work the same in all modern environments
Why don't we directly use proto link instead of using create method ?
Because __proto__ is a non-standard property and therefore not necessarily available in every browser.
However it seemed to be considered for ES.next. More info: MDN - __proto__.

ECMAScript Associative Array via Object w/ prototype null?

I see a lot of people doing this
Object.prototype.foo = 'HALLO';
var hash = {baz: 'quuz'};
for ( var v in hash ) {
// Do not print property `foo`
if ( hash.hasOwnProperty(v) ) {
console.log( v + " is a hash property" );
}
}
My question is rather than testing .hasOwnProperty each time you wish to use an Object as a hash why not just set the .__proto__ to null on the object? †
hash.prototype = null;
hash.__proto__ = null;
for ( var v in hash ) {
// Do not print property `foo`
console.log( v + " is a hash property" );
}
It has been brought to my attention that __proto__ is nonstandard. That still doesn't answer the question though...
var foo = Object.create(null);
Object.getPrototypeOf(foo);
This can't be an original question, but I can't find anything about changing __proto__ to null to eliminate the drawbacks of having to check for inheritance? What's wrong with this approach, seems to make code faster (don't have to check properties of Object) and cleaner?
† And the .prototype property if you plan on making future children of it.
There's nothing inherently wrong with creating [[Prototype]]'less objects to avoid hasOwnProperty-based checks during "hash" enumeration.
In fact, some of the libraries I know (fuse.js being one of them, IIRC) do exactly that.
Now on to the practical problems:
__proto__ is non-standard. See my compat. table. Notice how IE doesn't support __proto__ up until and including IE9. Of course, IE9 supports Object.create and so it becomes possible to create [[Prototype]]'less object with Object.create(null) but that still leaves IE6, IE7 and IE8. Oh and Opera <10.10, as you can see (which doesn't support Object.create). Fortunately, existence (and functionality) of __proto__ can be easily feature tested, which is why non-supporting browsers can be made to take hasOwnProperty-based or some other route.
Removing [[Prototype]] from the object "removes" all of the Object.prototype.* methods. Naturally. So, for example, myHash.toString() (or even myHash + '') will now error out unless you give that hash toString method. Ditto for valueOf, hasOwnProperty, and all the other Object.prototype.* methods. This isn't big deal, of course, as you can always define those methods (and probably should — to make them specialized for hash usage) but it's more work nevertheless.
As far not finding anything about this approach... I was talking about it at least 2 years ago :) — http://groups.google.com/group/comp.lang.javascript/msg/9451c45080b5e9f0 (likely earlier too, but can't find any other posts on comp.lang.javascript at the moment). There are more interesting findings about browsers' behavior with __proto__ === null in that thread. Check it out.
Not all JS implementations have __proto__ as it is non-standard feature.

Categories

Resources