I ask because I'm writing an Angular directive requiring me to reference the parent and grandparent element. This means I end up with long names for something like the 'grand parents' innerheight. Something like:
var grandParentInnerHeight = $grandParent.innerHeight();
A friend suggested using nth to name these, but using numbers also seems wrong when it comes to naming variables.
And I know some people might suggest to restructure my code so I don't need the grand parent, but in this case its necessary.
Any ideas?
I've seen people use abbreviations like
var gpInnerHeight = foo;
or
var grandPInnerHeight = foo;
But personally, I find no problem in writing the full name of a variable. It makes it clear to understand, but just takes a couple more ms to write it.
Also, for JQuery, I've seen some people who want to distinguish between JavaScript variables and JQuery variables by putting a $ in front of them like this.
var $grandParentInnerHeight = foo.innerHeight();
Here's a website that goes over some naming conventions that I see as useful.
Click me
Related
I have some trouble that comes from my Javascript (JS) codes, since I sometimes need to access the same DOM elements more than once in the same function. Some reasoning is also provided here.
From the point of view of the performance, is it better to create a jQuery object once and then cache it or is it better to create the same jQuery object at will?
Example:
function(){
$('selector XXX').doSomething(); //first call
$('selector XXX').doSomething(); //second call
...
$('selector XXX').doSomething(); // n-th call
}
or
function(){
var obj = $('selector XXX');
obj.doSomething(); //first call
obj.doSomething(); //second call
...
obj.doSomething(); // n-th call
}
I suppose that the answer probably depends by the value of "n", so assume that n is a "small" number (e.g. 3), then a medium number (e.g. 10) and finally a large one (e.g. 30, like if the object is used for comparison in a for cycle).
Thanks in advance.
It is always better to cache the element, if n is greater than 1, cache the element, or chain the operations together (you can do $('#something').something().somethingelse(); for most jQuery operations, since they usually return the wrapped set itself). As an aside, it has become a bit of a standard to name cache variables beginning with a money sign $ so that later in the code it is evident that you are performing an operation on a jQuery set. So you will see a lot of people do var $content = $('#content'); then $content.find('...'); later on.
The second is superior. Most importantly, it is cleaner. In the future, if you want to change your selector, you only need to change it one place. Else you need to change it in N places.
Secondly, it should perform better, although a user would only notice for particularly heavy dom, or if you were invoking that function a lot.
If you look at this question from a different perspective, the correct answer is obvious.
In the first case, you're duplicating the selection logic in every place it appears. If you change the name of the element, you have to change each occurence. This should be reason enough to not do it. Now you have two options - either you cache the element's selector or the element itself. Using the element as an object makes more sense than using the name.
Performance-wise, I think the effect is negligible. Probably you'll be able to find test results for this particular use-case: caching jQuery objects vs always re-selecting them. Performance might become an issue if you have a large DOM and do a lot of lookups, but you need to see for yourself if that's the case.
If you want to see exactly how much memory your objects are taking up, you can use the Chrome Heap Profiler and check there. I don't know if similar tools are available for other browsers and probably the implementations will vary wildly in performance, especially in IE's case, but it may satisfy your curiosity.
IMO, you should use the second variant, storing the result of the selection in an object, no so much as to improve performance but to have as little duplicate logic as possible.
As for caching $(this), I agree with Nick Craver's answer. As he said there, you should also use chaining where possible - cleans up your code and solves your problem.
You should take a look at
http://www.artzstudio.com/2009/04/jquery-performance-rules/
or
http://addyosmani.com/jqprovenperformance/
I almost always prefer to cache the jQuery object but the benefit varies greatly based on exactly what you are using for your selector. If you are using ids then the benefit is far less than if you are using types of selectors. Also, not all selectors are created equally so try to keep that in mind when you write your selectors.
For example:
$('table tr td') is a very poor selector. Try to use context or .find() and it will make a BIG difference.
One thing I like to do is place timers in my code to see just how efficient it is.
var timer = new Date();
// code here
console.log('time to complete: ' + (new Date() - timer));
Most cached objects will be performed in less than 2 milliseconds where as brand new selectors take quite a bit longer because you first have to find the element, and then perform the operation.
In JavaScript, functions are generally short-lived—especially when hosted by a browser. However, a function’s scope might outlive the function. This happens, for example, when you create a closure. If you want to prevent a jQuery object from being referenced for a long time, you can assign null to any variables that reference it when you are done with that variable or use indirection to create your closures. For example:
var createHandler = function (someClosedOverValue) {
return function () {
doSomethingWith(someClosedOverValue);
};
}
var blah = function () {
var myObject = jQuery('blah');
// We want to enable the closure to access 'red' but not keep
// myObject alive, so use a special createHandler for it:
var myClosureWithoutAccessToMyObject = createHandler('red');
doSomethingElseWith(myObject, myClosureWithoutAccessToMyObject);
// After this function returns, and assuming doSomethingElseWith() does
// not itself generate additional references to myObject, myObject
// will no longer have any references and be elligible for garbage
// collection.
}
Because jQuery(selector) might end up having to run expensive algorithms or even walk the DOM tree a bit for complex expressions that can’t be handled by the browser directly, it is better to cache the returned object. Also, as others have mentioned, for code clarity, it is better to cache the returned object to avoid typing the selector multiple times. I.e., DRY code is often easier to maintain than WET code.
However, each jQuery object has some amount of overhead. So storing large arrays of jQuery objects in global variables is probably wasteful—unless if you actually need to operate on large numbers of these objects and still treat them as distinct. In such a situation, you might save memory by caching arrays of the DOM elements directly and using the jQuery(DOMElement) constructor which should basically be free when iterating over them.
Though, as people say, you can only know the best approach for your particular case by benchmarking different approaches. It is hard to predict reality even when theory seems sound ;-).
I'm sure someone is going to shout at me for asking this question, but here goes: in Javascript, what is the best strategy for coping with the fact that the properties of objects are case-sensitive? If I create an object with a property called FavouriteDrink, but then I later start referring to it as favouriteDrink then I could end up in a mess.
I don't want a big library here, but is there any way to define the object so that FavouriteDrink is defined somewhere, and where in Visual Studio 2012 some intellisense will help me choose the correct property name if I can somehow contextualise the object I'm dealing with? It is only properties I'm pondering here.
Thanks.
It doesn't work this way
if i look at your your code and see :
FavouriteDrink() {}
the first thing will popup in my mind is this is a constructor function not just a normal function
and by looking at this following one
favouriteDrink() {}
i would tell that this is a normal function and i can't use it as a constructor - can't be called with new
Here is some other examples
first_name // variable
FIRST_NAME // uppercase variables shouldn't change
_first_name // local variable not intended to be used out of its scope
var FIRSTNAME = {} // name space
it’s a good idea to follow a convention as to how the words will be separated
see this Code Conventions for the JavaScript Programming Language
For the other part of your question i'm using VS 2012 and i installed JSEnhancements
and i can see all my object element
JavaScript shares the following conventions with Java and ActionScript 3.
ALL_UPPERCASE
Use this as the variable name when you define a constant, or a value that should never change.
For example, myObject.NUM_TIMES_CLICKED = 2 would be a poor candidate for a constant because it is likely to change. However, myObject.APPLE_FRENCH_SPELLING = 'pomme' would be appropriate here.
firstWordLowercaseAndTheRestAllUppercase
Use this when you are defining anything that is not a constant or a class. You would use this for most things, for example, myObject.numTimesClicked, myObject.myFunction(), myObject.returnString.
AllWordsCapitalized
Use this when you are defining a function that defines a "class," generally any function you would call with the syntax myObject.myClassInstance = new MyClass(). Notice how myClassInstance is in camel-case because it is an instance of the class. However, MyClass is all caps because it is meant to be invoked with new.
You would define the class initially like this: myObject.MyClass = function(){};
WebStorm and Sublime Text are great tools that offer the code intelligence you're looking for.
WebStorm does this out of the box, but my personal preference is Sublime Text with the SublimeCodeIntel plugin.
That being said, it's probably best for you to be using naming conventions:
UpperCamelCase is for classes
ALL_CAPS_SNAKE_CASE is for constants
lowerCamelCase is used for everything else
Due to performance and other issues, I want to split my code into seperate functions as before it was just one big ".ready" function.
I am new to javaScript/jquery but I thought I would give it a go myself. I have done exactly the way I thought it was done but my console is telling me things are undefined so I am guessing I have got things out of scope. I have read up on it in more detail, but still have not got anywhere.
My code works OK at the moment but I want to get into the habbit of clean coding. Can someone point out where I am going wrong so I can carry on myself?
Here is an example of what I have so far
//Global variables
var randomWord = [];
var listOfWords = [];
var populationNumber = [];
var attemptNumber = [];
var completionNumber = [];
var gridSize = [];
generateGrid();
startMusic();
randomizeReward();
//Click event to start the game
$(".start-btn-wrapper").click(function () {
startplay();
});
//Click event to restart the game
$(".restart-btn").click(function () {
restartplay();
});
Thanks
Fiddle: http://jsfiddle.net/QYaGP/
Fiddle with HTML: http://jsfiddle.net/QYaGP/1/
You need to start passing some information into the functions you're defining. If your functions all have no arguments, then you will have to use globally defined variables, hardcoded references to jquery selections etc in order to get anything done.
So as an example, you have a function
function replaySound() {
$("#hintSound").attr('src', listOfWords[randomWord].hintSound);
hintSound.play();
}
This is actually going to play the sound detailed in listOfWords[randomWord] via the element #hintSound. You could do that via:
function playSound(selector, wordlistEntry) {
$(selector).attr('src', wordlistEntry.hintSound);
$(selector)[0].play();
}
And then instead of calling replaySound(), you'd call:
playSound('#hintSound', listOfWords[randomWord]);
This way the behaviour that you want is wrapped up in the function, but the specifics, i.e. the data you need for it, are passed in via the arguments. That allows you to reuse the function to play any sound using any selector, not just #hintSound.
You'll find as you do that that you need to start choosing what a function will act on in the code that calls it, rather than in the function. That's good, because the context of what you're trying to achieve is there in the calling code, not in the function. This is known as 'separation of concerns'; you try to keep logic about a given thing confined to one area, rather than spreading it about in lots of functions. But you still want functions to allow you to encapsulate behaviour. This allows you to change behaviour cleanly and easily, without having to rewrite everything every time some part of the logic changes.
The result should be that you find several functions actually did the same thing, but with different specifics, so you can just have one function instead and reuse it. That is the Don't Repeat Yourself principle, which is also important.
If you are concerned about performance, I would look into using an framework such as AngularJS. You can inject modularized code. Even better, with MVC your view is bound to your model so by changing the model the view automatically updates itself.
Also, stop using class selectors. Use ID selectors. They are much faster. You also want to preload selectors (even with class selectors). That way you are only searching the DOM once:
var ele = $('#elementId');
$(ele).doSomething();
This way, you have a reference to the DOM element. You can use a datastructure to store all of your references outside of the global scope:
var elementReferences = {}; //declaration
elementReferences.mainPage = {}; //use
elementReferences.mainPage.root = $('#mainPage'); //load the root div of a page segment
elementReferences.mainPage.title = $(elementReferences.mainPage.root).children('#title'); //load the title
elementReference.mainPage.form = $(elementReferences.mainPage.root).children('#form'); //load the form
Now you can do this:
$(elementReference.mainPage.form).whatever();
and it doesn't have to search the DOM for the element. This is especially useful for larger apps.
If you put a function within document.ready, as per your fiddle, you are only able to access that function within the scope of the document.ready call. You really want to be able to load/unload functions as needed dynamically within the scope that they are required in, which is where angularjs comes into play.
You also, for the most part, want to remove your functions and variables from the global scope and put them into containers that are sorted by their dependencies and use. This is Object Oriented Programming 101. Instead of having a bunch of arrays sitting within the global scope where they could be overwritten by mistake by another developer, you want to put them within a container:
var arrays = {}; //create the object
arrays.whatever1 = [];
arrays.whatever2 = [];
Obviously, you will probably want a more descriptive name than "arrays". Functions work the same manner:
var ajax = {}; //ajax object
var ajax.get = function(){
};
var ajax.post = function(){
};
var ajax.delete = function(){
};
This generally promotes cleaner code that is more reusable and easier to maintain. You want to spend a good portion of your time writing a spec that fully documents the overall architecture before actually beginning development. NEVER jump the gun if you can help it. Spend time thoroughly researching and planning out the big picture and how everything fits together rather than trying to wing it and figure it out as you go. You spend less time having to reinvent the wheel when you do it this way.
It's developed by google, so it should be around for quite a while. I'm not sure if you are the guy in charge of your system's architecture, but if performance/reusability is an issue at your company it is definitely worth taking a look at. I'd be more than happy to give you a walkthrough regarding most of what I know in terms of software architecture and engineering. Just MSG me if you are interested. Always happy to help!
I am starting to learn jQuery. Looking though the MVC3 project that makes use of Awesome MVC Html helpers, I have stumbled upon a javasript code that I don't know how to understand yet:
$ae.autocomplete('Requestor'
What is $ae is calling a jQuery autocomplete on in this case? ae isn't an element, so this isn't an id or class selector.
P.S. And while you are at it, please let me know what $. as in $.getJSON calls getJSON on?
Assuming that there isn't a typo, $ae is a variable. Since $ is just a javascript function you can assign the result of it to a variable, $ae = $("#myid"). While I don't know that $ae is definitely the result of that, the naming convention ($ at the beginning) makes me suspect that it is.
In jQuery, the $ is a convenient alias for the jQuery object. So $.getJSON() is calling the getJSON() method of the jQuery object. This is pretty confusing at first, but once you get used to it it's nice and concise.
It seems like common practice in jQuery development to use a $ to prefix variables that result from selecting things with jQuery, like this:
var $myList = $('.list-item');
The $ is a legal character to use in variable names, so I guess it's a reminder that the object contains a jQuery wrapped set. It's a good idea to assign the results of your selections to variables if you'll use the selected items again; otherwise you're wasting resources.
In your example, the $ae is the equivalent of something like this:
$('#my-input').autocomplete('Requestor ...
i have a simple question about caching, this kind of confuses me lol
Im not sure if it depends on if your using handlers or not but...
is there any difference between these two?
var $something = $('.something');
or
var something = $('.something');
and also, is it possible to do this (depending on the correct way)
var something = $('something'),
somethingElse = $('somethingelse');
or this way
var something = $('something');
var somethingElse = $('somethingelse');
just want to be sure im heading in the right direction.
It's been bothering me. I've seen it done both ways actually, but i don't know which is right, or if either are wrong. I'm sure someone knows for sure though :)
Prefixing variables with $ is only used to remind the programmer (or others) that the variable holds a jquery object. It isn't a 'javascript thing' and does not provide any additional functionality. It's a good idea though :)
All the code you posted is valid.
It's your choice. Many people (including myself) prefix variables with $ to indicate that the variables represent jQuery objects (because $ is shorthand for jQuery). If you think it helps you along the same lines, then you're free to prefix your variables as such.
Declaring multiple variables comma-separated with a single var keyword is legal JavaScript.