I'm coming from C/C++ syntax family so some things here aren't familiar to me.
constructor: function(manufacturer, model, topSpeed, maxAltitude){
// initialise our config object
this.initConfig();
if(maxAltitude){
this.setMaxAltitude(maxAltitude);
}
// call the parent class' constructor
this.callParent([manufacturer, model, topSpeed]);
}
So, now when I'm calling a parent's constructor, why am I including data in []? When I did something similar in C#, I just send data like in any normal function.
Couldn't this just be:
this.callParent(manufacturer, model, topSpeed);
This example is from
Ext-JS 4 Web Application Development Cookbook
but I think it's a JavaScript problem.
Thank you.
Well .callParent() is a class system utility provided by ExtJS. It needs the arguments as an array because it's going to use .apply() to call another function.
They could have written it to build its own array if they'd wanted to. It's arguably more useful in the current form because it gives you more flexibility, and it's not like making an array is hard in JavaScript.
(I don't know exactly what it does because I don't use ExtJS.)
Related
I have noticed that if I write a method that only acts on local variables of calling methods (does not directly interact with a class variable) then I get a warning that the method can be static.
Sometimes it's nice to abstract a large piece of code into a separate method. Is this somehow consider bad practice in JavaScript/TypeScript?
Since I keep getting these warnings I'm taking a chance that the post police will pounce on me for asking a question that could invite opinions. Let me defend against that by saying that the warnings I'm getting are not opinions. They are definite warnings. That suggests that there exists an answer that is not opinion, at least from the perspective of the people who decided to create those warnings.
EDIT:
I was asked to put code here to provide a valid reason as to why I would want to do this. I personally don't think this adds any clarity to question I asked but here's an example of a method that was producing the warning in WebStorm.
//Change object array in *.content objects to values array
//noinspection JSMethodCanBeStatic
transformData(visibleData) {
const ret: any = {};
ret.headings = visibleData.headings;
ret.checkbox = this.checkBox; //add if the table needs checkboxes
ret.content = [];
for (let i = 0; i < visibleData.content.length; i++) {
ret.content.push(_.values(visibleData.content[i]));
}
return ret;
}
The point of this function is to take a clone of the instance, so as not to modify the instance itself, and create a different object, mainly a values only array, which will be used to databind in the template. I did this so my table template could be reusable since columns vary in number.
Code which does not interact with instance should be a free function or at least a static method of a class when you believe it is tightly coupled with class API.
Every additional method you add to API has to be supported. So larger classes require more support than smaller classes. In some languages, like Java, you can't have free function, so you have to attach function to some class, but TypeScript and JS are more flexible, so there is no need to pollute class API.
And you could consider it from the performance optimization point of view.
When JS evaluates class method it looks it up in the object instance, than in the object prototype, than in the parent's prototype, etc. Every lookup eats cpu time, so when you think about performance, free function is your choice.
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.
I have a model object with a property called definition that i am using across a class. I can access that property like model.attributes.definition
Every time that i want to use this property inside a method, and for the sake of clarity, i am creating a shortcut definition = model.attributes.definition at the very beggining so the method code does not get populated with boilerplate.
Because i am using it across several methods i thought that, instead of creating the shortcut on every method, i could create a little helper function to do the job:
getDefinition: (model) ->
model.attributes.definition
and then use it anywhere like
if getDefinition(model).name?
doSomething()
But aren't these function calls across my code innecessary/resource consuming for such a trivial task? What is a good approach in a situation like this?
You can also access object values via string:
definition = "attributes.definition"
then to access the value:
if model[definition].name?
doSomething()
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.
Is it possible to create an object container where changes can be tracked
Said object is a complex nested object of data. (compliant with JSON).
The wrapper allows you to get the object, and save changes, without specifically stating what the changes are
Does there exist a design pattern for this kind of encapsulation
Deep cloning is not an option since I'm trying to write a wrapper like this to avoid doing just that.
The solution of serialization should only be considered if there are no other solutions.
An example of use would be
var foo = state.get();
// change state
state.update(); // or state.save();
client.tell(state.recentChange());
A jsfiddle snippet might help : http://jsfiddle.net/Raynos/kzKEp/
It seems like implementing an internal hash to keep track of changes is the best option.
[Edit]
To clarify this is actaully done on node.js on the server. The only thing that changes is that the solution can be specific to the V8 implementation.
Stripping away the javascript aspect of this problem, there are only three ways to know if something has changed:
Keep a copy or representation to compare with.
Observe the change itself happening in-transit.
Be notified of the change.
Now take these concepts back to javascript, and you have the following patterns:
Copy: either a deep clone, full serialization, or a hash.
Observe: force the use of a setter, or tap into the javascript engine (not very applicable)
Notify: modifying the code that makes the changes to publish events (again, not very applicable).
Seeing as you've ruled out a deep clone and the use of setters, I think your only option is some form of serialisation... see a hash implementation here.
You'll have to wrap all your nested objects with a class that reports you when something changes. The thing is, if you put an observer only in the first level object, you'll only receive notifications for the properties contained in this object.
For example, imagine you have this object:
var obj = new WrappedObject({
property1: {
property1a: "foo",
property1b: 20,
}
})
If you don't wrap the object contained in porperty1, you'll only receive a "get" event for property1, and just that, because when someone runs obj.property1.property1a = "bar" the only interaction that you'll have with obj, will be when it asks for the reference of the object contained in property1, and the modification will happen in an unobserved object.
The best approach I can imagine, is iterating over all the properties when you wrap the first object, and constructing recursively a wrapper object for every typeOf(property) == "Object".
I hope my understanding of your question was right. Sorry if not! It's my first answer here :$.
There's something called reactive programming that kind of resembles what you ask about, but its more involved and would probably be overkill.
It seems like you would like to keep a history of values, correct? This shouldn't be too hard as long as you restrit changes to a setter function. Of course, this is more difficult in javascript than it is in some other languages. Real private fields demand some clever use of closures.
Assuming you can do all of that, just write something like this into the setter.
function setVal(x)
{
history.push(value);
value = x;
}
You can use the solution that processing.js uses.
Write the script that accesses the wrapped object normally...
var foo = state.get();
foo.bar = "baz";
state.update();
client.tell(state.recentChange());
...but in the browser (or on the server if loading speed is important) before it runs, parse the code and convert it to this,
var foo = state.get();
state.set(foo, "bar", "baz");
state.update();
client.tell(state.recentChange());
This could also be used to do other useful things, like operator overloading:
// Before conversion
var a=new Vector(), b=new Vector();
return a + b * 3;
// After conversion
var a=new Vector(), b=new Vector();
return Vector.add(a,Vector.multiply(b,3));
It would appear that node-proxy implements a way of doing this by wrapping a proxy around the entire object. I'll look into more detail as to how it works.
https://github.com/samshull/node-proxy