I am just curious about the behavior of dynamically changing constructor's prototype in JavaScript. And I got the above result.
It seems like your already constructed instance will not share the "new" prototype's properties.
I was wondering if it's simply just the choice of such design? Because I expected to see the instance share the "new" prototype's properties. Thanks!
When an object is constructed, its prototype reference is set at that point according to the value of the constructor function's prototype property. If the constructor property later changes value, the already-constructed objects are not affected.
That's just how it works.
So, yes, that can cause problems. I guess you could exploit it for some purpose, but that'd be pretty strange.
Related
In javascript, it's possible to "override" properties or methods of Object.prototype. For example:
Object.prototype.toString = function(){
return "some string";
};
It can break an entire application if not used carefully. Are there any tools, techniques or approaches to avoid this (for example, some kind of 'strict mode' that doesn't allow the developer to override properties of Object)?
Object.freeze(YourConstructor.prototype) can help protect your constructor's associated prototype object from being mucked with. From MDN:
The Object.freeze() method freezes an object: that is, prevents new properties from being added to it; prevents existing properties from being removed; and prevents existing properties, or their enumerability, configurability, or writability, from being changed, it also prevents the prototype from being changed.
It works on the object itself, rather than making a copy that's frozen. It returns the same reference you pass it.
It's best to leave built-in prototypes alone, so using it on Object.prototype and such may not be a great idea. :-) Certainly you'd need to do a lot of testing if you did... See this thread on the es-discuss mailing list for relevant, useful info.
Can you convert a superclass reference into a subclass reference? A subclass reference into a superclass reference? If so, give examples. If not, explain why not
JavaScript doesn't have typed references at all. An object reference is just an object reference, the full and complete extent of any type information it has is that it's an object reference. So there's no need to convert a reference from a superclass reference to a subclass reference.
The object itself (not the reference) does have some information that, in some ways, links it back to its "class" (which is to say, its constructor function), indirectly via its prototype — assuming that A) The prototype isn't changed via Reflect.setPrototypeOf (a reasonable assumption, but there's no guarantee), and B) the prototype property on the constructor function doesn't get changed (also frequently a reasonable assumption, but not a guarantee, once the codebase is done initializing [and not until then]). For instance, if an object is created via a constructor function, in the normal case it inherits a constructor property from its prototype which, in the normal case, points back at the constructor function. You can't really rely on it, because if someone has modified the object referenced by the constructor function's prototype property it may not have a constructor property at all (and thus inherits it from its prototype) or may have one pointing at the wrong function.
It's important to remember that JavaScript is a prototypical language, not a class-based one. The new class semantics in ES6 are almost entirely syntactic sugar for setting up chains of constructors and their prototypes. ("Almost" because there's some plumbing related to subclassing builtins like arrays that we couldn't do previously.) One aspect of JavaSCript not being class-based is that questions like this don't really relate to it.
I tried changing the constructor function of a class by
className.proptotype.constructor = newConstrcutor;
This property now refers to the newConstructor but when i try to create an instance of the class, still the old constructor is executed. So, what exactly is the use of className.proptotype.constructor ?
Thanks
Each constructor has a pointer to an object called prototype. The prototype is the main mechanism that JavaScript supports to share properties and methods among objects of the same type.
In addition, the prototype can be used to support inheritance; not exactly in the way that it is done in other OO languages like Java, c# etc. So you can imagine that there is a mechanism that allows the interpreter to navigate from one prototype to another via a chain that is implicitly formed.
In the same way that constructor point to a prototype object, the prototype can also point to its constructor; You can think of it as a relation between constructors and prototypes.
One of the uses of the className.proptotype.constructor property is when you want to debug your code. A JavaScript debugger would clearly state the type (the constructor it was created from) of an instance.
for more details you can read this
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor
I am trying to build a custom collection (lets call it GenericList), which can hold n collections and act like it was just one.
To inherit all the functions of an ordinary Backbone collection, I set the prototype of GenericList to a new instance of Backbone.Collection. Then I overwrite the important ones like fetch(), reset(), on(), off() and so on. Now there are also functions that I want to kick out of GenericList (basically add and create).
So in order to delete these functions, I first get my instances prototype which is Backbone.Collection and then Backbone.Collections prototype, which simply is an Object that holds all the collection functions. When I delete the functions from there, what happens is, that all instances of Backbone.Collection throughout my app loose these functions, because they all inherit from that one Object.
So my question is, are there other techniques than delete to hide a function on an object, even if that function is defined anywhere in the objects prototype chain?
edit: links a fiddle... and the thing on github
Well, that's exactly how prototypes work in Javascript. When you reference a property inherited from a prototype in Javascript, what's actually happening is that Javascript looks for that property on the object itself first, and if it doesn't find it, it travels up the prototype chain to find the property. This happens at the time of the property lookup, and it happens on the actual prototype objects, not on an abstract prototype definition. So if you delete something from an object you're using as a prototype, then immediately following that you will no longer be able to reference that property, even in objects that inherit from that object.
To put it a different way, there's no such thing as a "class" and an "instance" in Javascript. There are only instances.
To do this properly, you need to delete the function from GenericList after creating it from Backbone.Collection. Otherwise you're actually modifying Backbone.Collection.
I have accomplished exactly what I want by not inheriting from new Backbone.Collection but from _.clone(Backbone.Collection.prototype). This way I have my own physical object as prototype and am able to delete whatever I want without it having an effect on other collections.
If you're interested in the code, I updated it on github (row 114).
I have, in many ocassions been able to register methods for all HTMLElements in both ways.
So I am curious, is there any difference?
Should I prefer one method over the other one?
What would be the right way to do it?
using prototype is making the function available to all objects in the prototype chain. Its basically extending the class. While other one is just adding a property to the current element. But as Felix suggest the right thing would be not to do this at all.
Because JavaScript is a prototype based language and not a Class based language they keyword .prototype.variable or .__proto__.variable (for Math) is used to directly access the prototype (Like the Class Definition in classed based languages) and modify it effecting ALL of its instances even if the instances has been created before the prototype is modified. Whereas .variable without accessing the prototype only affects the specified instance.
In short "HTMLElement.prototype.someFunc =" will allow ALL HTMLElements (and prototypes which inherit from HTMLElement" to access someFunc. And HTMLElement.someFunc should only be used to allow a specific instance of HTMLELement access to someFunc.