In Backbone, any difference between model.get('foo') and model.attributes.foo? - javascript

In Backbone.js, there are two ways you can get the value of a single attribute:
var foo = model.get('foo');
var foo = model.attributes.foo;
The .get() approach is the one recommended in the docs, but presumably it's a bit slower, as it involves an extra function call.
Are there any reasons why I shouldn't use the .attributes approach? Are there any cases where it would cause unexpected behaviour?

It's a matter of encapsulation. By using a get method you are saying I don't care how it's implemented I just want that attribute. So in future if you want to override your get method to return something more meaningful, you would not have make a code change everywhere you are using that attribute.
For e.g., If your model has an attribute cost associated with it which is a number.
model.get('cost') //would give you that number say 1999.99
Now in future suppose you want it to return a formatted string, you can override the get method.
model.get('cost') // same method would now give you $1999.99 or EUR 1999,99 in french :)
Also you are reducing the amount of code and increasing the readability.
model.get('foo') reads much better than model.attributes.foo; and it's shorter as well.

As you mentioned, in your question, the .get() approach is the one recommended in the docs. Although calling the attribute directly is going to save you a few nano seconds, you should not do it.
The reason is because it may encourage someone reading your code to use that same method to set an attribute: model.attributes.foo = 'blah';
I probably don't have to tell you that this would be bad. The code may appear to work because you're getting the correct value on the model, but you are bypassing all the change tracking logic built in to backbone. No events will be triggered if you set an attribute that way.
That being said - if no one else is reading your code or changing your code but you, and you care about those extra nanoseconds that much, and you know that you will never make that type of a mistake in the future. Then by all means, use the attributes property directly.

Related

Is it a bad practice to declare an Array in arguments?

validationError([elem1,elem2],type,shiftNo);
or
var arr = [elem1,elem2];
validationError(arr,type,shiftNo);
What I mean to ask is approach 1 of calling the function considered bad ( also does it have any performance ramifications). and for that matter is it a bad approach to declare strings, object and functions inside arguments.
Performance is not an issue, not in a language like JS, Ruby or whatnot. So all we can do is think about code readability. And this case is not strongly related to JS, so will be my examples.
move = ["E2", "E4"];
if chessboard.valid(move, player) {
...
}
This clearly states: "if the move (E2 E4) is valid for this chessboard, then...", you don't even need to look at the docs to know that. If we write that without assigning our array a name, the result looks a little cryptic (still easy to guess, but harder for such a tiny example):
if chessboard.valid(["E2", "E4"], player) {
...
}
What is this supposed to mean? What does valid stand for here? Maybe, it's asking whether these cells contain valid player's pieces? This is a sympthom of a design flaw, more precisely bad naming. It makes bold assumptions about how the chessboard code will be used. We can make it obvious that this array represents a move by renaming the chessboard's method:
if chessboard.valid_move(["E2", "E4"], player) {
...
}
This is better, but you may not have an API that allows your code to stay so readable without some additional naming.
So, I suggest a rule of thumb:
If the array will be used more than once, name it.
If the meaning of the array is not obvious from where it goes (function name), name it.
Don't name it, unless points 1 or 2 apply.
It doesn't make any difference really. Either way, you create a Javascript Array, which basically is an Object and get a reference in return (which you pass to your method). If you don't need to access that array (or other data) later in your code, the second approach is completely fine.
Are the contents of arr ever going to get used again? If so, then option 2 is definitely the way to go. If not... something as simple as this is probably just personal opinion.
Personally, I'd have to say that option 2 is better practice, even though sometimes I'm guilty of using option 1. Option 2 is easier to read, it's easier to follow and it's less likely someone will have to re-read it because they became temporarily confused or lost in flow of thought whilst reading through your code (especially newer programmers). For those reasons it's easier to maintain, you, and potentially future developers working with your code, will likely save time working with it.
The only negatives I can see would be generating an absolutely miniscule amount of overhead, and now you have 2 lines of code instead of 1. But I think that's irrelevant, the tiny potential benefits of option 2 outweigh the tiny negatives of option 1.
It is subjective, but in my opinion it is better to use the second approach.
As #jAndy said there is no difference in the code execution neither the performance of your code, but it is easier to debug and easier to read and understand the second approach.

How to correctly access properties of a Sencha model?

There appear to be a number of different ways how to access properties of a Sencha (Touch) model. However, I don't seem to be able to find proper documentation of which is the "correct" way of doing it.
Model creation
var model = Ext.create('MyApp.model.MyModel', {
name: value,
foo: bar,
...
})
Property access
model.get('name') or model.set('name', newValue)
model.data.name or model.data.name = newValue
model.raw.name seems to always return a string no matter what the data type in the model definition is?
Let's sort this all out:
get and set methods are the intended accessors for model field values.
model.data is the object that stores the client side model value, that is that have been converted from the data received from the server proxy using the fields configuration (type, convert method, etc.).
model.raw is the raw data that was received from the server proxy, before it was converted to client side application domain model values. You should avoid using it, or you will tie yourself to your proxy/server.
model['name']: as you've said, it doesn't work. Don't hope for it to come back (I don't even really understand that it worked at one point).
Now, which one should you use? Clearly, the last two ones are already out of the match.
The model.data object should give you the expected result in most cases (see bellow), and should give you a marginal performance gain other calling a function.
However, IMO you should always prefer to use the getters and setters, for two reasons.
First, it might happen that someone in your team (or you from the past) decides that the getter/setter is a good point to add some custom logic. In this case, bypassing the accessor by using the data object directly will also bypass this logic, and yield unpredictable result.
Secondly, getters and setters make it really easier to debug some situations, by making it easy to know from where modifications of the model values are coming. I mean, if one day you were to ask yourself "f**k, why is my model field value changing to this??". If all the code uses the getters, you'll just have to put a breakpoint in there, and you'll catch the culprit hand in bag. On the other hand, if the incriminated code uses the data object directly, you'll be stuck to do a whole project search for... You can't tell exactly what... data.name =? data['name'] =? name:? etc.
Now that I think about it, there is yet another reason. A deprecated one apparently. But the data object name used to be customizable using this persistenceProperty option. So, in some cases, the data object won't even be available, and code doing model.data.name instead of model[model.persistenceProperty].name would crash, plain and simple.
Short answer: use the accessors.

Elegant way to notice JavaScript object attribute changes

I am working on a JavaScript application with a server-side component. The aim is to have multiple different objects on a canvas that are synchronized (i.e., have the same appearance) between multiple browsers. The synchronization is done by the server-side component which broadcasts the individual changes to all browsers. Whenever an object changes, it has to notify the server about which will then take care of notifying the other browsers.
The objects on the canvas are represented by JavaScript objects whose attributes determine the appearance for the user. Of course, not all of the attributes are important for the appearance. Hence, only changes of important attributes have to be transmitted to the other browsers. There are different 'classes' of objects, but all objects 'inherit' from a common 'superclass' (I know, the class inheritance terminology doesn't really work in JavaScript, but in this case, I think it is easier that way).
Now, I have some trouble to send the client-server notifications in an elegant way. Currently, I have setter-methods for all the important attributes of the different objects. These setter-methods call a function which sends the notifications to the server.
I don't really like that solution, since it introduces much boilerplate code. Ideally, when I create a new object, I would like to be able to just specify the important attributes an be done with it. The logic that takes care of monitoring the changes of these attributes could be inside the 'superclass'. But I have no idea how to implement this. Maybe there is a way to build the setters dynamically at runtime? Or maybe there is some other way I did not think about?
If anyone can think of a solution to this problem, I would be glad to hear about it.
Thanks in advance!
Edit:
I had to revoke the accepted answer (creating getters and setters dynamically via Object.defineProperty) since though I thought it would solve my problem, it doesn't really. I now get notified when a property is changed via direct attribute assignment which fires the setter, e.g.:
SynchronizedObject.importantProp = 'someValue';
But as I noticed, in many cases the importantProp is some more complex object. And those objects are usually updated via the getter, not the setter.
SynchronizedObject.importantProp.x = 'someValue';
As far as I can see, I have no chance to notice changes done in this way with my dynamic getters/setters implementation. To use it, I have to change the way I am accessing my objects. Something that works:
prop = SynchronizedObject.importantProp;
prop.x = 'someValue';
SynchronizedObject.importantProp = prop;
That way, the setter is used and everything works out fine. But this feels really awkward and I don't want to have to think about the synchronization every time, I set a property. So it seems to me, the solution is not really usable.
Can anyone help?
How about one set function?
MyObj.prototype.set = function(key, value) {
this[key] = value;
// do other things
};
You could combine this with an EventEmitter implementation to make it easy to observe changes.
This is exactly what __defineSetter()__ is intended to support. Check out John Ressig's JavaScript Getters and Setters blog post for some good examples. It would be pretty simple to fire off an event from inside a setter.
You may want to consider the MeteorJS framework if wheel reinvention is not really your bag.

Access native form properties that were overridden by field names?

This is quite the vexing question, but please bear with me.
It's a well known feature of the javascript DOM that if you have a form field with name="something", the form's javascript DOM representation will have a something property that is a reference to the field's DOM representation.
Now, if the field's name ("something") is equal to one of the form's native properties, it will take its place in the javascript object. For instance, for a form:
<form id="Form"><input name="submit" /></form>
we'll have:
var s=document.getElementById("Form").submit; // s is the input
instead of
var s=document.getElementById("Form").submit; // s is the native submit function
Is there a way to access the native property at all in a situation like this?
Thanks.
Edit: Just to clarify two points:
I'd like to be able to access any property, not just functions
I mean this as a general question. A logical solution would be not to provoke name clashes in the first place.
I don't think there is a way to access the native function if you have an input named 'submit.' I just ran across this same topic in Chapter 11 of Secrets of the Javascript Ninja by John Resig and Bear Bibeault. I think if anyone knows the ins and outs of JS and the DOM, it's them.
The following should do the trick:
HTMLFormElement.prototype.submit.call(document.getElementById("Form"))
It will use the native method and invoke it in the context of the element that's on the page.
I tried to post this as an edit to Ivo's answer, but it was rejected. The message is cryptic, but if what they meant was that I added too much to the original, then I think it's wrong, since I was merely trying to complete it. If the reason was different, feel free to comment. With this edit I'd have accepted Ivo's answer, but without it I think it is incomplete.
Ivo's answer works for native functions, but it isn't applicable to attributes. For attributes it seems there is a number of ways, all similar but none of them perfect, to retrieve the value. I've tested the following on IE9, which is all I have available here, but http://www.quirksmode.org/dom/w3c_core.html#attributes indicates the behaviours are generally, if not completely, consistent:
form.attributes['name'] // node representing the 'name' attribute
form.getAttribute('name') // input with name="name"
form.attributes['submit'] // null
form.getAttribute('submit') // input with name="submit"
form.attributes['onsubmit'] // node representing the 'onsubmit' attribute,
// whose value is a string
form.getAttribute('onsubmit') // input with name="submit"
Based on this, it seems that (again, notice I didn't test it thoroughly):
For value attributes, one may use the attributes['attribute name'] approach, which should work down to IE6.
For prototype functions, one may use the prototype.fn.call approach
For function attributes, maybe one can retrieve the source code of the attribute and use that, but I'd rather not have to.
Since getAttribute seems to return the named input instead of the attribute, at least in IE, it seems pretty useless.
Answering my original question, it looks like in the majority of cases there will be ways to access the properties, but it will depend on the property and eventually the browser.

Selectors and performance

Is there any benefit to performance when I do the following in Mootools (or any framework, really)?:
var elem = $('#elemId');
elem.addClass('someClass');
elem.set('some attribute', 'some value');
etc, etc. Basically, I'm updating certain elements a lot on the DOM and I was wondering if creating a variable in memory and using that when needed was better than:
$('#elemId').addClass('someClass');
$('#elemId').set('some attribute', 'some value');
The changes to $('#elemId') are all over the place, in various different functions.
Spencer ,
This is called caching and it is one of the best practices.
when you say
$('#elemId');
It will go and query the DOM everytime , so if you say
var elem = $('#elemId');
elem acts as a cache element and improves performance a lot.
This is manly useful in IE as it has memory leaks promblem and all
ready this document which is really good
http://net.tutsplus.com/tutorials/javascript-ajax/14-helpful-jquery-tricks-notes-and-best-practices/
It depends how you query the dom. Lookups by ID are extremely fast. Second most is css classes. So as long as you're doing it by only a single ID (not a complex selector containing an id), there shouldn't be much of a benefit. However, if you're using any other selector, caching is the way to go.
http://code.google.com/speed/page-speed/docs/rendering.html#UseEfficientCSSSelectors
https://developer.mozilla.org/en/Writing_Efficient_CSS
You first approach is faster then your second approach, because you "cache" the search on #elemId.
Meaning the calls to addClass and set don't require extra lookups in the DOM for your element.
However! You can link function calls:
$('#elemId').addClass('someClass').set('some attribute', 'some value');
Depending on your application caching or linking might work better, but definitely not identical sequential lookups in the same block.
Depending on the situation, caching can be as much as 99% faster then using a jQuery object every time. In the case you presented it will not make much difference. if you plan to use the selector many times, you should definitely cache the object as a variable so it doesn't get created everytime you run it.
A similar questions was answered at Does using $this instead of $(this) provide a performance enhancement?.
Check performance log http://jsperf.com/jquery-this-vs-this
You are considering using a local variable to cache a value of a potentially slow lookup.
How slow is the call itself? If it's fast, caching won't make much a difference. If it's slow, then cache at the first call. Selectors vary significantly in their cost-- just think about how the code must fine the element. If it's an ID, then the browser provides fast access, whereas classes and nodes my require full DOM scans. Check out profiling of jQuery (Sizzle) selectors to get a sense of these.
Can you chain the calls? Consider "chaining" method calls where possible. This provides the efficiency without introducing another variable.
For your example, I'd write:
$('#elemId').addClass('someClass').set('some attribute', 'some value');
How does the code read? Usually if the same method is going to be called multiple times, it is clearer to DRY it up, and use a local variable. The reader then understands the intent better-- you don't force them to scan all the jQuery calls to verify that they are the same. BTW, a fairly standard convention is to name jQuery variables starting with a $-- which is legal in Javascript-- as in
var $elem = $('#elem');
$elem.addClass('someClass');
Hope this helps.

Categories