Is there a way to access the super object when extending objects using $.extend?
I would like to extend an object, override a method, but call the overridden superclass method in the subclass method.
No, because there is no superclass. According to the docs for jQuery.extend:
Description: Merge the contents of two or more objects together into the first object.
In order to call a "superclass" method, you would have to keep a copy of the "superclass" around somewhere (perhaps as a parameter in the "descendant" object), and call the method directly on the "superclass".
If you are looking for javascript inheritance, you may be interested in this post from John Resig.
Not directly -- the old method is not longer around (except in the original object).
I've done two things: The first is to make a copy of the old method with a new name in the subclass:
var Super = {
a: function() {...}
};
var _SubFuncs: {
_superA: Super.a
a: function() {... this._superA(...) ... }
};
var Sub = $.extend(false, Super, _SubFuncs);
The other thing I've done when appropriate is to use the template pattern and have the super class call a method that for it has no behavior. The subclass then add behavior to the empty method. This only works if your call structure is such that "holes" can be added appropriately.
Edit: In my case, I was really trying to stick with prototypal objects so I was avoiding a general solution that makes my objects more class-like.
If you want to use the class inheritance and call the super class methods, then this blog from John Resig explains it all http://ejohn.org/blog/simple-javascript-inheritance/
Related
I've found folloing sample in which As if Service class has prototype property.
①Service is not instansiated, why Service = new Service() didn't need ?
②console.log(Service.prototype returned {},what is this object ? What is the merit to manipulate this?
beforeEach(async ()=>{
jest.spyOn(Service.prototype, 'execute')
})
I am totally novice to this concept, if someone has opinion will you please let me know.
Thanks
What this does is that whenever .execute(...) is called on any Service instance, your spying thingy would fire.
It doesn't need new Service() because it's not working on a single service instance, it is working on the class itself.
It works by replacing Service.prototype.execute with a wrapper function that logs the call and then calls the original function, something like this:
const oldExecute = Service.prototype.execute
Service.prototype.execute = function (...args) {
console.log('execute called!', args)
return oldExecute.call(this, ...args)
}
Class methods are nothing other than properties on the class' prototype, so if you have class Test { hello (x) { return x * 2 } } and you do console.log(Test.prototype.hello), it will log the method hello (x) { return x * 2 }, and if you do testInstance.hello(123) it essentially then calls Test.prototype.hello.call(testInstance, 123), i.e. it calls the function Test.prototype.hello with testInstance as this.
And the {} that you see is not everything there is, because the methods are by default non-enumerable. You should look at it in a debugger that also shows non-enumerable properties. Then you will see the class' methods there:
This is also the reason why when referring to the "full name" of a class method, often ClassName.prototype.methodName is used, because that's actually how you would get that method itself without referring to a particular class instance (to make use of it, you would have to call it with its this set to some instance, though, like what I did with .call above). For example, the slice function that exists on Array (when you write [1, 2, 3].slice(1) for instance) is referred to as Array.prototype.slice (in other languages this would be called Array::slice, Array#slice or the like). Sometimes you will also see people talking about Array.slice but that's technically not correct because slice is not a static method and doesn't exists on Array itself (unlike, for example, Array.from).
Further reading:
MDN: Object prototypes
MDN: Classes in JavaScript
MDN: Docs for Function.prototype.call (to understand the examples)
Jest docs for spyOn
I'm trying to get a better understanding of object oriented patterns in JavaScript. I particulary like the way EmberJS implements their classes with .extend and .create from Parent class Objects.
I've tried to implement a basic version of this on my own, but to no success, my newly instantiated Objects reference the same Object. I.e If I increment a private counter var in instance a via a public method, then separately do the same to instance b, b will reflect both increments.
I was able to achieve a de-referenced object via Object.create(myClass), however this is undesirable as I'd like to achieve this internally and also not rely on client support for that native method.
Here's a jsbin of what I've got: http://jsbin.com/zepaju/6/edit?js,console
Thanks for any help!
This is a pretty big subject, because there isn't a perfect way to make JavaScript work like Java-- you'll always have to invent some new coding idiom, and different people have different preferences.
Looking at your linked code, it's hard to be sure what you're gunning for but it looks like the problem is that you're thinking of an object's prototype as a "class", which is copied into each "instance" (like in Java)-- this isn't the case.
Your create() function is creating each "instance" by doing Object.create(Poll), which makes a new object with the Poll object as its prototype. When you refer to properties of the resulting objects, and those properties are not directly defined on the object, what you get is a reference to a property of the single Poll object.
The fact that you've sealed the Poll object's internal variables within a closure doesn't make any difference to this; the closure variables are hidden from the outside world, but they are accessible to the methods of the Poll object, and those methods are shared between all "instances".
If you want a function that spits out objects with a particular set of methods, and which hide their internal data in a closure, that might look like:
function Poll(challenger,incumbent) {
var challengerVotes=0;
var incumbentVotes=0;
return {
voteForChallenger: function() {challengerVotes++},
voteForIncumbent: function() {incumbentVotes++},
winner: function() {return challengerVotes>incumbentVotes ? challenger : incumbent}
}
}
var poll1 = Poll("Edward","Jacob");
var poll2 = Poll("Vanilla","Stilton");
poll1 and poll2 would not affect one another, and there would be no way to access the vote counts of either except through the supplied methods. I appreciate you're looking for a more generic approach but this is an example of how you might start.
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.
While going through this link
How to Deep clone in javascript
I came across a generic clone method (In the accepted answer) . I tried it out running directly in javascript and it runs giving perfect outputs.
I put that code in the native tag and am trying to clone an object in GWT.
My class which am trying to clone is
private class Container
{
Integer i = 5;
}
and when I try to do that, its just returning me the same object. Could anyone please help?
Ask me anything if its not clear. Thanks a ton.
Jonathan is right: the way (and the only one in GWT) is to use https://code.google.com/p/google-web-toolkit/wiki/AutoBean
This may seam awkward but it works perfectly since many concepts are related to that (EntityProxy in RequestFactory relies also on that mechanism, and it's the future of GWT).
Deep json persistence also works with auto beans.
The only thing you have to do is to create an interface that describes your class (and implement it in your class):
public interface ContainerBean {
Integer getI();
void setI(Integer i);
}
Then create your factory interface
interface MyFactory extends AutoBeanFactory {
// Factory method for a simple AutoBean
AutoBean<ContainerBean> container();
// Factory method for a non-simple type or to wrap an existing instance
AutoBean<ContainerBean> container(ContainerBean toWrap);
}
Now you can wrap your object and clone it (through json since)
clone()
An AutoBean and the property values stored within it can be cloned.
The clone() method has a boolean parameter that will trigger a deep or
a shallow copy. Any tag values associated with the AutoBean will not
be cloned. AutoBeans that wrap a delegate object cannot be cloned.
https://code.google.com/p/google-web-toolkit/wiki/AutoBean#clone()
therefore use this method instead:
https://code.google.com/p/google-web-toolkit/wiki/AutoBean#AutoBeanCodex
One way you could possibly achieve this is with AutoBeans.
I think the only trick with this method is that you'll have to use an AutoBeanFactory to create all of your classes.
Then, you could encode your autobean into a Splittable, then use the result to decode into a new autobean instance.
I see a lot of code like this:
function Base() {}
function Sub() {}
Sub.prototype = new Base();
However, if you do:
s = new Sub();
print(s.constructor == Sub);
This is false. This seems confusing to me, since s's constructor is, indeed, Sub. Is it conventional/better to do this?
function Base() {}
function Sub() {}
Sub.prototype = new Base();
Sub.prototype.constructor = Sub;
or does it not really matter?
'constructor' doesn't do what it looks like it does. This, in addition to its non-standardness, is a good reason to avoid using it - stick with instanceof and prototype.
Technically: 'constructor' is not a property of the 's' instance, it is a property of the 'Sub' prototype object showing through. When you create the 'Sub' function in Mozilla, you get a newly-minted default Sub.prototype object which has a 'constructor' pointing back to the Sub function as a courtesy.
However you then replace that prototype with a new Base(). The original default prototype with the link back to Sub is lost; instead, Sub.prototype is an instance of Base without any overriding 'constructor' property. So:
new Sub().constructor===
Sub.prototype.constructor===
new Base().constructor===
Base.prototype.constructor===
Base
...all the way down to the most basic object whose prototype you didn't change.
Is it conventional/better to do this?
When dealing with JavaScript objects/classes there is no one convention; every library's metaclass system behaves slightly differently. I haven't seen one that writes 'constructor' to each derived class manually, but it seems as good a solution as any if you really want to have the real constructor available; it will also make the code compatible with browsers/engines that don't give you 'constructor'.
I'd consider giving it a different name, though, to avoid confusion with the existing and differently-behaving 'constructor' property.
If you want to test whether an object is exactly an instance of Sub use the instanceof operator:-
print(s instanceof Sub);
If you want to know whether an object is an instance of Sub or an instance of a sub-class of Sub use the isPrototypeOf method:-
print(Sub.prototype.isPrototypeOf(s));
Yeah,
Sub.prototype.constructor = Sub;
let's you use instanceof but there's a better solution. Look here: ,TDD JS Inheritance on GitHub ,and find the Parasitic Combination Inheritance pattern. The code is TDD'd so you should be able to grok it very quickly and then simply change the names to get you started. This is basically what YAHOO.lang.extend uses (source: yahoo employee and author Nicholas Zakas's Professional JavaScript for Web Developer's, 2nd ED, page 181). Good book by the way (not affiliated in any way!)
Why? Because the classical pattern you're working with has staticy reference vars (if you create var arr = [1,2] in the base object, ALL instances will have read/write and will "share state" of 'arr'! If you use constructor stealing you can get around this. See my examples.