On my team, we usually do string concatentation like this:
var url = // some dynamically generated URL
var sb = new StringBuffer();
sb.append("<a href='").append(url).append("'>click here</a>");
Obviously the following is much more readable:
var url = // some dynamically generated URL
var sb = "<a href='" + url + "'>click here</a>";
But the JS experts claim that the + operator is less performant than StringBuffer.append(). Is this really true?
Your example is not a good one in that it is very unlikely that the performance will be signficantly different. In your example readability should trump performance because the performance gain of one vs the other is negligable. The benefits of an array (StringBuffer) are only apparent when you are doing many concatentations. Even then your mileage can very depending on your browser.
Here is a detailed performance analysis that shows performance using all the different JavaScript concatenation methods across many different browsers; String Performance an Analysis
More:
Ajaxian >> String Performance in IE: Array.join vs += continued
Internet Explorer is the only browser which really suffers from this in today's world. (Versions 5, 6, and 7 were dog slow. 8 does not show the same degradation.) What's more, IE gets slower and slower the longer your string is.
If you have long strings to concatenate then definitely use an array.join technique. (Or some StringBuffer wrapper around this, for readability.) But if your strings are short don't bother.
Yes it's true but you shouldn't care. Go with the one that's easier to read. If you have to benchmark your app, then focus on the bottlenecks.
I would guess that string concatenation isn't going to be your bottleneck.
Agreed with Michael Haren.
Also consider the use of arrays and join if performance is indeed an issue.
var buffer = ["<a href='", url, "'>click here</a>"];
buffer.push("More stuff");
alert(buffer.join(""));
Try this:
var s = ["<a href='", url, "'>click here</a>"].join("");
Like already some users have noted: This is irrelevant for small strings.
And new JavaScript engines in Firefox, Safari or Google Chrome optimize so
"<a href='" + url + "'>click here</a>";
is as fast as
["<a href='", url, "'>click here</a>"].join("");
JavaScript doesn't have a native StringBuffer object, so I'm assuming this is from a library you are using, or a feature of an unusual host environment (i.e. not a browser).
I doubt a library (written in JS) would produce anything faster, although a native StringBuffer object might. The definitive answer can be found with a profiler (if you are running in a browser then Firebug will provide you with a profiler for the JS engine found in Firefox).
In the words of Knuth, "premature optimization is the root of all evil!" The small defference either way will most likely not have much of an effect in the end; I'd choose the more readable one.
The easier to read method saves humans perceptible amounts of time when looking at the code, whereas the "faster" method only wastes imperceptible and likely negligible amounts of time when people are browsing the page.
I know this post is lame, but I accidentally posted something entirely different thinking this was a different thread and I don't know how to delete posts. My bad...
It is pretty easy to set up a quick benchmark and check out Javascript performance variations using jspref.com. Which probably wasn't around when this question was asked. But for people stumbling on this question they should take alook at the site.
I did a quick test of various methods of concatenation at http://jsperf.com/string-concat-methods-test.
I like to use functional style, such as:
function href(url,txt) {
return "<a href='" +url+ "'>" +txt+ "</a>"
}
function li(txt) {
return "<li>" +txt+ "</li>"
}
function ul(arr) {
return "<ul>" + arr.map(li).join("") + "</ul>"
}
document.write(
ul(
[
href("http://url1","link1"),
href("http://url2","link2"),
href("http://url3","link3")
]
)
)
This style looks readable and transparent. It leads to the creation of utilities which reduces repetition in code.
This also tends to use intermediate strings automatically.
As far I know, every concatenation implies a memory reallocation. So the problem is not the operator used to do it, the solution is to reduce the number of concatenations. For example do the concatenations outside of the iteration structures when you can.
Yes, according to the usual benchmarks. E.G : http://mckoss.com/jscript/SpeedTrial.htm.
But for the small strings, this is irrelevant. You will only care about performances on very large strings. What's more, in most JS script, the bottle neck is rarely on the string manipulations since there is not enough of it.
You'd better watch the DOM manipulation.
Related
UPDATE: After having the code out in the wild for a while, I found two issues on Citrix and iOS Safari. Both seem to be around the use of Eval. The citrix issue could have been resolved by updating the CSS to :
emailerrormessage = 'please enable Javascript'; ahref.attr('data-edomain') + '\0040' + ahref.attr('data-ename');
The iOS Safari issue was not something I managed to resolve. I ended up cutting out the CSS element altogether.
EDIT: I'm opening up this question for recommendations on why my solution might be considered bad programming in general, and if anyone else has a better way of obfuscating emails through a combination of CSS, HTML and JS. I've added an answer of my own findings, but haven't marked it as the answer in case someone else might have better insight into this technique.
I've been tasked to obfuscate email addresses on some webpages, and after encountering an answer suggesting use of CSS and data attributes I tried implementing it myself and found that getting the produced email address back into a mailto element was impossible without some JavaScript. The next problem encountered was that the JavaScript I ended up using to grab the rendered email address was not cross-browser as some browsers retrieve "attr(data-xx)" instead of the actual value. However I still like the idea of producing a solution that spans HTML, JS and CSS for maximum complexity. The last resort was to store a line of JS in the CSS content property, and use eval to produce the final email address.
Obfuscation is not supposed to be pretty, but I want to know if what I've done is potentially compromising security or performance by introducing eval() and/or storing JS in CSS. I haven't found another example of someone doing something similar (maybe for good reason).
My HTML is
<a class="redlinktext ninjemail" data-ename="snoitagitsevni" data-edomain="ua.moc.em" data-elinktext="click me"></a>
My CSS is
.ninjemail:before {
content: "'please enable Javascript'; ahref.attr('data-edomain') + '\0040' + ahref.attr('data-ename');"
}
My JavaScript is
$('.ninjemail').each(function () {
var fullLink = "ma";
var ahref = $(this);
fullLink += "ilto" + ":";
var codeLine = window.getComputedStyle(this, ':before').content.replace(/\"|\\/g, '');
var emailAddress = eval(codeLine);
emailAddress = emailAddress.split('').reverse().join('');
fullLink += emailAddress;
ahref.attr('href', fullLink);
var linkText = ahref.attr('data-elinktext');
if (linkText && linkText.length > 0) {
ahref.text(linkText);
} else {
ahref.text(emailAddress);
}
ahref.removeClass('ninjemail');
});
Based on the research I've done so far the only real drawback from using this method for obfuscation is that in teams where there is a clear separation of roles, Javascript in CSS files may confuse layout designers, and vice versa (programmers won't want to have to edit CSS files).
Performance wise there will always be more overhead in processing the email address across the three technologies. I can't say I'm an expert on performance testing, but I did a page refresh timing of before and after and got a DOMContentLoaded time of .956s vs .766s without obfuscation. Load time was 1.22s vs 1.17s without obfuscation. Not a concern for my own situation, but may be an issue on more intensive applications. Note that this was a once off test, and not an average of multiple runs in a controlled environment.
i am facing the problem that i have to translate a larger html and javascript project into several languages. The html content was no problem, but the numerous javascript files are problematic, since i was a bit lazy during the development process. For instance, if i needed a message text, i just added it in the concerning position.
My approach now is, that i am using a build-in file search (Eclipse) for every occurrence of " and ', which i am getting line-wise. This would be extremely time consuming and errors are unavoidable.
Here are some examples that occur in the files:
var d = "Datum: " + d.getDate()+"."+(d.getMonth()+1)+"."+d.getFullYear();
showYesNoDialog("heading text","Are you sure?",function(){};
Sometimes i am mixing " and ', sometimes a string goes over several lines:
var list="";
list+='<li data-role="list-divider">';
list+='Text To Translate';
list+='</li>';
Things i don't want to get, are jquery selectors, e.g.:
$("input[name^=checkbox]").each(function () {};
Do you see any time saving method to get all of the strings that i would like to translate?
Regex? A java interpreter? Grep?
I know, that is a bit unusual question.
So any suggestion would be great.
Thanks in advance!
It is better to use some kind of the lexical scanner that converts the code into the tokens and then walk over the list of tokens (or syntax tree). There is a number of such tools (I even created one of them myself - here you can find some of the examples https://github.com/AlexAtNet/spelljs/blob/master/test/scan.js).
With it you can scan the JS file and just iterate over the tokens:
var scan = require('./..../scan.js');
scan(text).forEach(function (item) {
if (item.str) {
console.log(item);
}
});
In JavaScript is the former or the latter more efficient? Or is there even a difference?
// Method one
var path = first_part + '/' + second_part + '/' + third_part;
// Method two
var path = [first_part, second_part, third_part].join('/');
Beyond the savings of a whopping two characters there's no visual reason to prefer one over the other. But I'm curious to know if in most JavaScript interpreters one is faster or more efficient than the other and if so, is it significantly so?
The second method is more efficient in terms of maintenance if you ever need to change the delimiter.
Using the concatenation operator is faster than using join():
See:
http://jsperf.com/concat-vs-vs-join
http://jsperf.com/array-join-or-concatenation
http://jsperf.com/concatenate-vs-join/2
See also:
Why is string concatenation faster than array join?
I just wanted to know the differences between the methods of adding html in jquery.
both will do samething right?
$('body').append($("<div><img src='somesource' alt='something'></div>"));
and
var div = $("<div>");
var img = $("<img>").attr({"src" : "somesource", "alt" : "something"});
div.append(img);
$('body').append(div);
which is the best practice to follow?
The second is better. Because you often see people doing this:
var alt = 'This is " the title containing a double quote';
$('body').append($('<div><img src="somesource" alt="' + alt + '"></div>'));
and then wonder why something got eaten :-). Whereas when you use the second you have absolutely nothing to worry about:
var alt = 'This is " the title containing a double quote';
var div = $('<div>');
var img = $('<img>').attr({ src : 'somesource', alt : alt });
div.append(img);
$('body').append(div);
UPDATE:
I was too hasty in saying that you have nothing to worry about with the second approach. As others have already pointed out you have to worry about performance.
The second method looks better and there are lesser chances of error. But performance wise, the second method is slower. So if you're going to be doing a lot of appending, I would recommend going with the the first case - albeit, carefully.
Here's a small test case up on JS-Perf comparing the two methods
Normally I would say DOM-scripting is the better option (the second approach); it's more structured, and easier to catch issues than by inserting a mass of HTML prepared as a string.
That said, there are performance concerns. Inserting loads of elements via DOM-scripting, particularly in a loop, can cause significant slowdown and there are cases where inserting as a string is much quicker.
Also, the fewer inserts you do - by whatever means - the fewer repaints/refreshes you force the browser to make. Again, these all require browser attention, so the fewer the better.
I believe you are better off using template libraries for inserting objects. An example of one such library is here: http://api.jquery.com/category/plugins/templates/
Those libraries are build for performance and ease the burden on parsing HTML blobs.
Adding a string of HTML content is about 10 times faster
than using second method
Here is a reference
See also my answer on When do you use DOM-based Generation vs. using strings/innerHTML/JQuery to generate DOM content?
The difference is that you have two variables pointing to the jQuery instances. You might can need them for eventListener-adding or manipulating them lateron in the code.
Also, DOM-based element generation has the advantage of automatically escaping the strings, which is especially useful when designing functions with parameters and absolutely needed for user input.
Therefore, the second method is most often preferred. You can also nest the appending process to make the structure clear (OK, in this example the one-liner would be clear as well):
var div = $("<div>");
var img = $("<img>", {"src":"somesource", "alt":"something"});
$('body').append(
div.append(
img
)
);
I would prefer the second one as the first one could lead to very long lines and if you need to bind events to certain elements you already have a variable that is pointing to it.
var str = '<div part="1">
<div>
...
<p class="so">text</p>
...
</div>
</div><span></span>';
I got a long string stored in var str, I need to extract the the strings inside div part="1". Can you help me please?
you could create a DOM element and set its innerHTML to your string.
Then you can iterate through the childNodes and read the attributes you want ;)
example
var str = "<your><html>";
var node = document.createElement("div");
node.innerHTML = str;
for(var i = 0; i < node.childNodes.length; i++){
console.log(node.childNodes[i].getAttribute("part"));
}
If you're using a library like JQuery, this is trivially easy without having to go through the horrors of parsing HTML with regex.
Simply load the string into a JQuery object; then you'll be able to query it using selectors. It's as simple as this:
var so = $(str).find('.so');
to get the class='so' elememnt.
If you want to get all the text in part='1', then it would be this:
var part1 = $(str).find('[part=1]').text();
Similar results can be achieved with Prototype library, or others. Without any library, you can still do the same thing using the DOM, but it'll be much harder work.
Just to clarify why it's a bad idea to do this sort of thing in regex:
Yes, it can be done. It is possible to scan a block of HTML code with regex and find things within the string.
However, the issue is that HTML is too variable -- it is defined as a non-regular language (bear in mind that the 'reg' in 'regex' is for 'regular').
If you know that your HTML structure is always going to look the same, it's relatively easy. However if it's ever going to be possible that the incoming HTML might contain elements or attributes other than the exact ones you're expecting, suddenly writing the regex becomes extremely difficult, because regex is designed for searching in predictable strings. When you factor in the possibility of being given invalid HTML code to parse, the difficulty factor increases even more.
With a lot of effort and good understanding of the more esoteric parts of regex, it can be done, with a reasonable degree of reliability. But it's never going to be perfect -- there's always going to be the possibility of your regex not working if it's fed with something it doesn't expect.
By contrast, parsing it with the DOM is much much simpler -- as demonstrated, with the right libraries, it can be a single line of code (and very easy to read, unlike the horrific regex you'd need to write). It'll also be much more efficient to run, and gives you the ability to do other search operations on the same chunk of HTML, without having to re-parse it all again.