Is there any possibility to change the __proto__ property of an object in IE9 or IE10?
Or is MS still not planning to include it in their JS engine?
I need it in a very special situation where I need to change __proto__ after the object is created.
__proto__ is going to be standardized in ES6. It is currently in Appendix B of the ES6 draft which in practice means that if it is implemented it needs to have the following semantics.
__proto__ is both available as an accessor on Object.prototype which means that all objects can read and write it by default. However, it can be removed from Object.prototype (using delete). Once deleted __proto__ will work as a normal data property with no side effects on setting.
__proto__ is also a special syntactic form in object literals. It will work to set the [[Prototype]] even if Object.prototype.__proto__ was deleted.
var p = {a: 1};
var o = {
__proto__: p,
b: 2
}
ES6 also introduces Object.setPrototypeOf (not in the appendix). This is preferred over setting __proto__.
__proto__ is available in all modern browsers, including Internet Explorer 11.
__proto__ is included in IE11 found in the leaked build of Windows Blue: http://fremycompany.com/BG/2013/Internet-Explorer-11-rsquo-s-leaked-build-395/
A nonanswer as a last case resort:
Change your code so that all the properties that would originally be accessed via the changed prototype are now accessed via explicit delegation over a normal property:
{
a: 17,
__proto__: { ... }
}
to
{
a: 17,
proto: {...}
}
I'm not sure what exactly it is you're after since your question didn't specify, but for most uses of proto, you should be able to use prototype.
var foo = new Bar();
//this also affects foo
Bar.prototype.baz = something;
Related
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)
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__.
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
On this JS MDN page it says this:
JavaScript 1.8.1 note
Starting in JavaScript 1.8.1, setters are no
longer called when setting properties in object and array
initializers.
I just can't figure out what this is trying to tell me.
This code-snippet:
var o = {};
o.seven = 7;
and this code-snippet:
var o = { seven: 7 };
are normally equivalent; but if they're preceded by this code-snippet:
Object.prototype.__defineSetter__('seven', function(x) { alert(x); });
then only the former will alert 7 (because the setter is called by o.seven = 7, but not by o = { seven: 7 }), and only the latter will actually set o.seven to 7.
I think this refers to the issue of JSON hijacking. Have a look at
Is it possible to do 'JSON hijacking' on modern browser?
http://incompleteness.me/blog/2007/03/05/json-is-not-as-safe-as-people-think-it-is/
http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx, http://haacked.com/archive/2009/06/25/json-hijacking.aspx
http://hackademix.net/2009/01/13/you-dont-know-what-my-twitter-leaks/
To repost my answer from this deleted question:
According to the specification, neither Array (EcmaScript 5.1
§11.1.4) nor Object literals
(EcmaScript 5.1 §11.1.5) should be
hijackable:
They call "the standard built-in constructor with that name", not what you might have overwritten at window.Array or window.Object
They use [[defineOwnProperty]], which does absolutely not take care of any setters on Object.prototype.
Nowadays, this should not be an issue any more in ES 5.1-compliant browsers.
I was browsing MDC about new functions added to Object. One of them, Object.preventExtensions, is said to prevent mutations to the object's prototype, which can be obtained by using Object.getPrototypeOf or __proto__.
On Chrome, however, it seems to simply allow mutations to the object's prototype. This can be confirmed by just executing the code on the relevant page:
// EXTENSION (only works in engines supporting __proto__
// (which is deprecated. Use Object.getPrototypeOf instead)):
// A non-extensible object's prototype is immutable.
var fixed = Object.preventExtensions({});
fixed.__proto__ = { oh: "hai" }; // throws a TypeError
I don't get this TypeError, and fixed.__proto__.oh === 'hai', so it has been set even though it should have been disallowed. I can also add it when coding like Object.getPrototypeOf(fixed).oh = 'hai'.
Does this mean Chrome has a different interpretation of this function? How can one prevent extensions to an object's prototype (in Chrome)?
Nope, Chrome and Mozilla both implement the standards part of the spec the same. Read carefully:
Object.preventExtensions only prevents
addition of own properties. Properties
can still be added to the object
prototype.
Everything to do with .__proto__ is non-standard, and Chrome can implement that differently. You showed only that Chrome implements details with .__proto__ differently, and in my opinion, more intuitively: The spec says that the prototype is still extensible, so it makes sense that you should still be able to mutate it. The question then becomes why did Mozilla implement it that way?
For example, the following code works the same on both Chrome and FF:
var fixed = Object.preventExtensions({});
Object.getPrototypeOf(fixed).p = 99;
fixed.p; // 99
Clearly the prototype is still mutable. That makes sense with Chrome's implementation of .__proto__.
So to prevent extensions of a prototype, do so separately:
var fixed = Object.preventExtensions({});
Object.preventExtensions(Object.getPrototypeOf(fixed));
Object.getPrototypeOf(fixed).p = 99; // TypeError: Can't add property p, object is not extensible
In ECMAScript 5, objects have a boolean internal property named [[Extensible]], this property is set to false when you call the Object.preventExtensions method, and after that, no new own properties can be added to the object.
On Chrome 14.0.786.0, the assignment to __proto__ throws a TypeError as you expect.
But remember that the __proto__ extension is non-standard, so it's behavior may vary, of course syntactically it is a "property assignment", but internally it doesn't "add an own property", it mutates the object's prototype, thing that is not possible to do by any standard method.
About the example of the Object.getPrototypeOf method you show us, it's simply retrieving the object's prototype, in the case of your fixed object, it's the Object.prototype object:
Object.getPrototypeOf(fixed) === Object.prototype; // true
So your example:
Object.getPrototypeOf(fixed).oh = 'hai'
Is equivalent to:
Object.prototype.oh === 'hai';