Related to the answer https://stackoverflow.com/a/10619477/1076753 to cleate an element is better to use
$(\"\", {id: \"foo\", class: \"a\"});
With better or correct use in your case it depends on how frequently this code will appear in your page. @Quentin is correct in that there is only a two byte difference between the first and second option. Now if the code only appears a few times in the whole page then realistically unless you are recording a large amount of traffic on your server you will not see a significant difference between the two, on the other hand if you are running a medium to high traffic site or will be having a large number of instances of this javascript appearing on your page then the best option would be to go with option one as it is two bytes smaller and over a larger page with many instances of this code you will find measurable savings in the byte size of the page.
As for well formed tags for cross platform compatibility both the first and second options will result in the exact same end result in the browser so in your use case compatibility will not be affected by either option.
Based on these points I would suggest using option one as it provides the two byte advantage over option two, that is effectively the only difference between the two options in your use case.
From jQuerys website:
It makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler..
Notice that it doesn't mention HTML generation.
JavaScript provides the document.createElement method. jQuery utilizes this method if HTML-like string is passed as the selector.
The jQuery entry point ($(whatEverIFeelLikeDoingToday)
) type checks the selector for string, node or function, then handles the request accordingly. If the argument is string, it then passes through +/- 60 lines of code (Am I HTML? Am I a selector, am I an ID, am I a class?). After the HTML-like string is identified, it is then passed to another function (additional function calls) to be generated -therefore slow (see benchmark below). In fact, it doesn't add much value to the process, aside from uniformity, just slows it down.
I've found the best practice to be: not using jQuery for rather simple tasks (i.e. node creation) -wherever practice, eliminate the obstacles in it's way.
var div = document.createElement('div');
div.setAttribute("id", "foo");
div.setAttribute("class", "a");
div = $(div);
Notice the significant performance increase in this benchmark. (Just about 4x faster in Chrome). This solution is Faster than the two described above and inherently Cross platform.
I don't think that the argument for less bytes -vs faster execution time is in the scope of this thread. However, assuming you are minifying your code, I will throw out a the practical example of looping through an array to generate html rows for a table. Bytes aren't the problem, you only needed to load the script once -execution is what bogs you down.
If you go solely by metrics that can be easily measured: The first is better because it is 2 bytes shorter.
Once you start accounting for readability and other less tangible considerations, it becomes largely a matter of opinion.
So, at the end it's wrong to use one of the first two options for a div?
No, that section only applies "If the HTML is more complex than a single tag without attributes"
taking a look into the jQuery library, the following is the relevant section from v2.2.0 line 2827.
init = jQuery.fn.init = function(selector, context, root) {
var match, elem;
// HANDLE: $(""), $(null), $(undefined), $(false)
if (!selector) {
return this;
}
// Method init() accepts an alternate rootjQuery
// so migrate can support jQuery.sub (gh-2101)
root = root || rootjQuery;
// Handle HTML strings
if (typeof selector === "string") {
if (selector[0] === "<" &&
selector[selector.length - 1] === ">" &&
selector.length >= 3) {
// Assume that strings that start and end with <> are HTML and skip the regex check
match = [null, selector, null];
} else {
match = rquickExpr.exec(selector);
}
// Match html or make sure no context is specified for #id
if (match && (match[1] || !context)) {
// HANDLE: $(html) -> $(array)
if (match[1]) {
context = context instanceof jQuery ? context[0] : context;
// Option to run scripts is true for back-compat
// Intentionally let the error be thrown if parseHTML is not present
jQuery.merge(this, jQuery.parseHTML(
match[1],
context && context.nodeType ? context.ownerDocument || context : document,
true
));
// HANDLE: $(html, props)
if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
for (match in context) {
// Properties of context are called as methods if possible
if (jQuery.isFunction(this[match])) {
this[match](context[match]);
// ...and otherwise set as attributes
} else {
this.attr(match, context[match]);
}
}
}
return this;
You will see that it checks if the selector is a string
, and if it does then see's if it starts with <
and ends with >
.
if (typeof selector === "string") {
if (selector[0] === "<" &&
selector[selector.length - 1] === ">" &&
selector.length >= 3) {
Then, having in mind the regex rsingleTag
being:-
var rsingleTag = ( /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/ );
Which matches both "<div>"
and "<div />"
, returning div
as group[1]
.
The parseHTML
uses that to return a div
element, in the merge
:-
jQuery.parseHTML = function( data, context, keepScripts ) {
...
var parsed = rsingleTag.exec( data );
// Single tag
if ( parsed ) {
return [ context.createElement( parsed[ 1 ] ) ];
}
then using the regex again, and context
as your object for setting the properties:-
// HANDLE: $(html, props)
if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
it for
's over each property setting with this.attr(match, context[match]);
So, at the end it's wrong to use one of the first two options for a div?
As above shows, its personal preference. Both work the same.