Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.javascript > #17925 > unrolled thread
| Started by | Cezary Tomczyk <cezary.tomczyk@gmail.com> |
|---|---|
| First post | 2013-01-03 22:58 +0100 |
| Last post | 2013-01-06 21:38 +0100 |
| Articles | 12 on this page of 32 — 6 participants |
Back to article view | Back to comp.lang.javascript
Two versions of code - advantages and differences Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2013-01-03 22:58 +0100
Re: Two versions of code - advantages and differences Stefan Weiss <krewecherl@gmail.com> - 2013-01-04 00:41 +0100
Re: Two versions of code - advantages and differences Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2013-01-04 09:15 +0100
Re: Two versions of code - advantages and differences Gregor Kofler <usenet@gregorkofler.com> - 2013-01-04 11:26 +0100
Re: Two versions of code - advantages and differences Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2013-01-04 14:29 +0100
Re: Two versions of code - advantages and differences Gregor Kofler <usenet@gregorkofler.com> - 2013-01-04 14:56 +0100
Re: Two versions of code - advantages and differences Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2013-01-04 16:52 +0100
Re: Two versions of code - advantages and differences Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2013-01-04 09:19 +0100
Re: Two versions of code - advantages and differences Gregor Kofler <usenet@gregorkofler.com> - 2013-01-04 11:25 +0100
Re: Two versions of code - advantages and differences Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-01-04 15:31 +0100
Re: Two versions of code - advantages and differences David Mark <dmark.cinsoft@gmail.com> - 2013-01-05 08:37 -0800
Re: Two versions of code - advantages and differences Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-01-05 18:14 +0100
Re: Two versions of code - advantages and differences David Mark <dmark.cinsoft@gmail.com> - 2013-01-05 10:51 -0800
Re: Two versions of code - advantages and differences Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-01-05 20:46 +0100
Re: Two versions of code - advantages and differences David Mark <dmark.cinsoft@gmail.com> - 2013-01-05 17:12 -0800
Re: Two versions of code - advantages and differences David Mark <dmark.cinsoft@gmail.com> - 2013-01-06 17:43 -0800
Re: Two versions of code - advantages and differences Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-01-07 03:58 +0100
Re: Two versions of code - advantages and differences David Mark <dmark.cinsoft@gmail.com> - 2013-01-06 19:23 -0800
Re: Two versions of code - advantages and differences Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-01-07 05:19 +0100
Re: Two versions of code - advantages and differences Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2013-01-06 22:30 +0100
Re: Two versions of code - advantages and differences Stefan Weiss <krewecherl@gmail.com> - 2013-01-07 02:35 +0100
Re: Two versions of code - advantages and differences Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2013-01-07 22:45 +0100
Re: Two versions of code - advantages and differences Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-01-07 04:36 +0100
Re: Two versions of code - advantages and differences Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2013-01-07 23:06 +0100
Re: Two versions of code - advantages and differences Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-01-08 12:35 +0100
Re: Two versions of code - advantages and differences Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2013-01-09 08:34 +0100
Re: Two versions of code - advantages and differences David Mark <dmark.cinsoft@gmail.com> - 2013-01-05 09:13 -0800
Re: Two versions of code - advantages and differences Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2013-01-06 11:09 +0100
Re: Two versions of code - advantages and differences David Mark <dmark.cinsoft@gmail.com> - 2013-01-06 12:56 -0800
Re: Two versions of code - advantages and differences Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2013-01-07 22:53 +0100
Re: Two versions of code - advantages and differences Luc Yen <luc@goal.tw> - 2013-01-05 12:54 -0800
Re: Two versions of code - advantages and differences Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2013-01-06 21:38 +0100
Page 2 of 2 — ← Prev page 1 [2]
| From | Stefan Weiss <krewecherl@gmail.com> |
|---|---|
| Date | 2013-01-07 02:35 +0100 |
| Message-ID | <kcd8op$4k3$1@news.albasani.net> |
| In reply to | #17989 |
On 2013-01-06 22:30, Cezary Tomczyk wrote:
> I've just wrote something like this:
>
> var main = {
> [...]
>
> apply : (function(){
> var tempImg = document.createElement('img'),
> t, img;
> tempImg.width = '10';
> tempImg.height = '10';
>
> return function(o){
> img = tempImg.cloneNode(false);
> img.alt = o.alt;
> img.src = o.src;
> t = document.createElement('span');
> t.appendChild(document.createTextNode('\u00a0'));
> t.appendChild(img);
> t.appendChild(document.createTextNode('\u00a0'));
> window.setTimeout(function(){ examplefn(t); }, 100);
> };
> }
)(),
>
> [...]
> };
>
> As I understand (correct me if I am wrong) this is inefficient because:
>
> * closure need extra memory and will be always in memory because
> returned function refers to variables that are outside of returned function.
In your example, the returned function closes over tempImg. If this
element is actually needed, you will have to store it _somewhere_. It
won't take up more memory just because it's in a closure. If it's not
needed, and you're concerned about memory usage, then don't create it.
Keeping a value around in a closure when it's not strictly needed can be
convenient (from a programmer's perspective), and it can speed up
execution later on, at the cost of some memory. You could look at it as
an optimization measure that favors speed over memory usage.
In another message, you asked about the performance penalty of closures
compared to non-closure* functions. I was about to reply that the
difference is insignificant, but thought I'd better provide a benchmark
for support. That's when I ran into my little benchmark problem with
Chrome, and I forgot to reply :-/ Anyway, having a closure does not by
itself cause a noticable difference in performance. You'd need millions
of calls to see any difference at all, and then the result is mixed. In
some cases/implementations, the closure variant was actually executed
faster than the function+variable variant. You'll have to take my word
for that or test it yourself, because I'm done with benchmarks for today :)
(* technically, every function call creates a closure, but that
definition of a closure is so broad that it becomes almost useless)
> * "apply" is parsed immediately which is not needed always
Nitpick: the whole script is parsed before anything can be executed. You
probably meant to say that the anonymous function is executed
immediately, and a tempImg element is created even though it may not be
needed.
Creating a handful of elements when a script is loaded won't make much
of a difference. If you still want to reduce the overhead, you could
initialize such elements lazily (ie, only when they are needed):
apply: (function () {
var tempImg;
function prepareImg() {
if (!tempImg) {
tempImg = document.createElement("img");
tempImg.width = 10;
tempImg.height = 10;
}
}
return function (o) {
prepareImg(); // (or inlined)
...
};
})(),
To be honest, I don't see the need for a tempImg (or a closure) at all
in this method. The element just gets cloned every time apply() is
called. Why not simply create the actual image element when you need it?
> Anything else inefficient or wrong?
Nothing wrong, just more from the nitpick department:
I would avoid the name "apply" for a method. It's not wrong, but it can
lead to confusion for others who read your code.
The 't' and 'img' variables should be declared where they are used, not
in the surrounding function.
\u00a0: ten years ago, a typical HTML document was littered with
non-breaking spaces, but they are rarely needed today (except when you
actually need a non-breaking space between words). Manually creating DOM
text nodes for them is a waste. Use CSS to create fillers and margins
instead.
tempImg.width = '10'; - should be an number, not a string.
HTH,
- stefan
[toc] | [prev] | [next] | [standalone]
| From | Cezary Tomczyk <cezary.tomczyk@gmail.com> |
|---|---|
| Date | 2013-01-07 22:45 +0100 |
| Message-ID | <kcffmh$1vn$1@speranza.aioe.org> |
| In reply to | #17992 |
W dniu 2013-01-07 02:35, Stefan Weiss pisze:
> On 2013-01-06 22:30, Cezary Tomczyk wrote:
>> I've just wrote something like this:
>>
>> var main = {
>> [...]
>>
>> apply : (function(){
>> var tempImg = document.createElement('img'),
>> t, img;
>> tempImg.width = '10';
>> tempImg.height = '10';
>>
>> return function(o){
>> img = tempImg.cloneNode(false);
>> img.alt = o.alt;
>> img.src = o.src;
>> t = document.createElement('span');
>> t.appendChild(document.createTextNode('\u00a0'));
>> t.appendChild(img);
>> t.appendChild(document.createTextNode('\u00a0'));
>> window.setTimeout(function(){ examplefn(t); }, 100);
>> };
>> }
>
> )(),
Ah, yes. A typo. My mistake.
>>
>> [...]
>> };
>>
>> As I understand (correct me if I am wrong) this is inefficient because:
>>
>> * closure need extra memory and will be always in memory because
>> returned function refers to variables that are outside of returned function.
>
> In your example, the returned function closes over tempImg. If this
> element is actually needed, you will have to store it _somewhere_. It
> won't take up more memory just because it's in a closure. If it's not
> needed, and you're concerned about memory usage, then don't create it.
I create it because I discovered that cloning node with already defined
properties is faster than creating node with new properties.
> Keeping a value around in a closure when it's not strictly needed can be
> convenient (from a programmer's perspective), and it can speed up
> execution later on, at the cost of some memory. You could look at it as
> an optimization measure that favors speed over memory usage.
I know that this can depend on situation, eg. more complex things and
results can be cached. After some discussion here I know that I would
write it now in a much simpler way. No extra closure here is needed.
> In another message, you asked about the performance penalty of closures
> compared to non-closure* functions. I was about to reply that the
> difference is insignificant, but thought I'd better provide a benchmark
> for support. That's when I ran into my little benchmark problem with
> Chrome, and I forgot to reply :-/ Anyway, having a closure does not by
> itself cause a noticable difference in performance. You'd need millions
> of calls to see any difference at all, and then the result is mixed. In
> some cases/implementations, the closure variant was actually executed
> faster than the function+variable variant. You'll have to take my word
> for that or test it yourself, because I'm done with benchmarks for today :)
Yes, I saw your post and even I did some tests. The results are
surprised for me. Google Chrome and Safari was incredibly fast, while
Firefox and Opera was very slow.
> (* technically, every function call creates a closure, but that
> definition of a closure is so broad that it becomes almost useless)
Actually, yes.
>> * "apply" is parsed immediately which is not needed always
>
> Nitpick: the whole script is parsed before anything can be executed. You
> probably meant to say that the anonymous function is executed
> immediately, and a tempImg element is created even though it may not be
> needed.
Indeed. Execution and parsing is not the same thing.
> Creating a handful of elements when a script is loaded won't make much
> of a difference. If you still want to reduce the overhead, you could
> initialize such elements lazily (ie, only when they are needed):
>
> apply: (function () {
>
> var tempImg;
>
> function prepareImg() {
> if (!tempImg) {
> tempImg = document.createElement("img");
> tempImg.width = 10;
> tempImg.height = 10;
> }
> }
>
> return function (o) {
> prepareImg(); // (or inlined)
> ...
> };
>
> })(),
>
> To be honest, I don't see the need for a tempImg (or a closure) at all
> in this method. The element just gets cloned every time apply() is
> called. Why not simply create the actual image element when you need it?
As I mentioned above: cloneNode working faster than creating new node
and add new properties. Well, on the other hand this could be called as
a "premature optimization" ;-)
I think that after some discussion in this topic I would rather rewrite
my code and use much more simpler version. No closure needed.
>> Anything else inefficient or wrong?
>
> Nothing wrong, just more from the nitpick department:
>
> I would avoid the name "apply" for a method. It's not wrong, but it can
> lead to confusion for others who read your code.
That was only an example, but I know that developer should / must avoid
using reserved words or words that can confuse others.
> The 't' and 'img' variables should be declared where they are used, not
> in the surrounding function.
Ok, because every function is a closure then 't', 'img' are really
outside of returned function. So, they should be defined inside returned
function.
> \u00a0: ten years ago, a typical HTML document was littered with
> non-breaking spaces, but they are rarely needed today (except when you
> actually need a non-breaking space between words). Manually creating DOM
> text nodes for them is a waste. Use CSS to create fillers and margins
> instead.
Nice idea, but for some reason I can not see non-breaking-space (and any
other content) before and after img. Tested on Firefox 17.0.1 and IE 9
(Windows 7, 64 bit). See:
http://jsfiddle.net/w7BAu/
> tempImg.width = '10'; - should be an number, not a string.
Ok
> HTH,
Yes, it helps. Thanks.
--
Cezary Tomczyk
http://www.ctomczyk.pl/
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2013-01-07 04:36 +0100 |
| Message-ID | <1603326.gHQpjbgioL@PointedEars.de> |
| In reply to | #17989 |
Cezary Tomczyk wrote:
[Indentation fixed]
> W dniu 2013-01-04 15:31, Thomas 'PointedEars' Lahn pisze:
>> Cezary Tomczyk wrote:
>>> I have a two versions of code. They are just only examples and contains
>>> simple operations, but I want to understand more deeply some general
>>> things.
>>>
>>> Version 1
>>>
>>> var el = document.getElementById('test');
>>> var fn = function(){
>>> if( !el ){
>>> // fallback if el is not available and then return
>>> }
>>> return el;
>>> };
>>>
>>> Version 2
>>>
>>> var fn = (function(){
>>> var el = document.getElementById('test');
>>>
>>> if(el){
>>> return function(){
>>> return el;
>>> }
>>> } else {
>>> // fallback if el is not available and then return
>>> }
>>> }());
>>
>> […]
>>> […]
>>> Anything else what can be said about advantages or differences between
>>> them?
>>
>> Static code analysis has a hard(er) time recognizing that “fn” actually
>> refers to a function in Version 2. AFAIK, the JSDoc Toolkit cannot deal
>> with it at all (but my JSdoc is going to).
>
> True, but they are two different examples.
Your point being?
>> Another advantage of Version 1 over Version 2 is that it does not matter
>> if “el” is initialized, or its initialization value is available, before
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> or after the definition. For example, you would not want to use Version
^^^^^^^^^^^^^^^^^^^^^^^
>> 2 in a library that is loaded before the document has been loaded,
>> because ”el” will be a false-value then. The document need not have been
>> parsed to after the element in question, and the document tree not been
>> populated as much, before the document has been loaded. If you skip the
>> initialization of “el” in Version 1, you can load the code and still
>> initialize “el” later, when appropriate.
>
> Yes, but the examples are really simple and I wanted to demonstrate some
> general idea. The "el" doesn't have to be always an reference to object.
> This could be anything and could be more complex.
I was pointing out a general problem with self-calling functions, using an
example.
> I've just wrote something like this:
>
> var main = {
> [...]
>
> apply : (function(){
> var tempImg = document.createElement('img'),
> t, img;
> tempImg.width = '10';
> tempImg.height = '10';
>
> return function(o){
> img = tempImg.cloneNode(false);
> img.alt = o.alt;
> img.src = o.src;
> t = document.createElement('span');
> t.appendChild(document.createTextNode('\u00a0'));
> t.appendChild(img);
> t.appendChild(document.createTextNode('\u00a0'));
> window.setTimeout(function(){ examplefn(t); }, 100);
> };
> }
^^
JFYI: This is not going to work.
> [...]
> };
>
> As I understand (correct me if I am wrong) this is inefficient because:
>
> * closure need extra memory and will be always in memory because
> returned function refers to variables that are outside of returned
> function.
>
> * "apply" is parsed immediately which is not needed always
>
> Anything else inefficient or wrong?
Your code does not make sense to me at all, regardless of possible
inefficiencies. You are creating on initialization an ”img” object only to
clone it non-recursively (assuming this works) when the returned function is
called only to skip the “width” and “height” assignment – seriously?
I would have written
apply: function (o) {
var img = document.createElement('img');
img.width = 10;
img.height = 10;
img.alt = o.alt;
img.src = o.src;
var t = document.createElement('span');
t.appendChild(document.createTextNode('\u00a0'));
t.appendChild(img);
t.appendChild(document.createTextNode('\u00a0'));
window.setTimeout(function() { examplefn(t); }, 100);
}
here, and further optimized (with regard to maintenance effort and
compatibility) to
apply: (function () {
var _createElementFromObj = jsx.dom.createElementFromObj;
var _runAsync = jsx.dom.timeout.runAsync;
return function (o) {
var t = _createElementFromObj({
type: "span",
childNodes: [
"\u00a0",
{
type: "img",
properties: {
width: 10,
height: 10,
alt: o.alt,
src: o.src
}
},
"\u00a0"
]
});
_runAsync(function () { examplefn(t); }, 100);
};
}())
(Wrappers like that are functionally optional of course, but I find them
very useful. Although it escapes me here why you would want to insert the
equivalent of “ ” before and after the image; this should be done with
the “margin” CSS property instead.)
There are times when extra closures are a good idea, and there are times
when they are not. There is no definitive answer here, but my code should
give you some idea.
--
PointedEars
Twitter: @PointedEars2
Please do not Cc: me. / Bitte keine Kopien per E-Mail.
[toc] | [prev] | [next] | [standalone]
| From | Cezary Tomczyk <cezary.tomczyk@gmail.com> |
|---|---|
| Date | 2013-01-07 23:06 +0100 |
| Message-ID | <kcfgto$4hj$1@speranza.aioe.org> |
| In reply to | #17996 |
W dniu 2013-01-07 04:36, Thomas 'PointedEars' Lahn pisze:
> Cezary Tomczyk wrote:
[...]
>>> Cezary Tomczyk wrote:
[...]
>>>> Version 1
>>>>
>>>> var el = document.getElementById('test');
>>>> var fn = function(){
>>>> if( !el ){
>>>> // fallback if el is not available and then return
>>>> }
>>>> return el;
>>>> };
>>>>
>>>> Version 2
>>>>
>>>> var fn = (function(){
>>>> var el = document.getElementById('test');
>>>>
>>>> if(el){
>>>> return function(){
>>>> return el;
>>>> }
>>>> } else {
>>>> // fallback if el is not available and then return
>>>> }
>>>> }());
[...]
>>> Static code analysis has a hard(er) time recognizing that “fn” actually
>>> refers to a function in Version 2. AFAIK, the JSDoc Toolkit cannot deal
>>> with it at all (but my JSdoc is going to).
>>
>> True, but they are two different examples.
>
> Your point being?
I was thinking that even if the functions are different then variable
name is the same. I thought that JSdoc will catch this, but this doesn't
make sense. When both of functions will be used in the same scope then
Version 2 will overwrite Version 1.
[...]
>> Yes, but the examples are really simple and I wanted to demonstrate some
>> general idea. The "el" doesn't have to be always an reference to object.
>> This could be anything and could be more complex.
>
> I was pointing out a general problem with self-calling functions, using an
> example.
Indeed.
>> I've just wrote something like this:
>>
>> var main = {
>> [...]
>>
>> apply : (function(){
>> var tempImg = document.createElement('img'),
>> t, img;
>> tempImg.width = '10';
>> tempImg.height = '10';
>>
>> return function(o){
>> img = tempImg.cloneNode(false);
>> img.alt = o.alt;
>> img.src = o.src;
>> t = document.createElement('span');
>> t.appendChild(document.createTextNode('\u00a0'));
>> t.appendChild(img);
>> t.appendChild(document.createTextNode('\u00a0'));
>> window.setTimeout(function(){ examplefn(t); }, 100);
>> };
>> }
> ^^
> JFYI: This is not going to work.
Sorry, fast typing. A typo.
>> [...]
>> };
>>
>> As I understand (correct me if I am wrong) this is inefficient because:
>>
>> * closure need extra memory and will be always in memory because
>> returned function refers to variables that are outside of returned
>> function.
>>
>> * "apply" is parsed immediately which is not needed always
>>
>> Anything else inefficient or wrong?
>
> Your code does not make sense to me at all, regardless of possible
> inefficiencies. You are creating on initialization an ”img” object only to
> clone it non-recursively (assuming this works) when the returned function is
> called only to skip the “width” and “height” assignment – seriously?
I made a test and seems that creating once img node with properties and
clone them later every time is faster than creating new img node and
adding new properties. Just a small optimization.
> I would have written
>
> apply: function (o) {
> var img = document.createElement('img');
> img.width = 10;
> img.height = 10;
> img.alt = o.alt;
> img.src = o.src;
>
> var t = document.createElement('span');
> t.appendChild(document.createTextNode('\u00a0'));
> t.appendChild(img);
> t.appendChild(document.createTextNode('\u00a0'));
> window.setTimeout(function() { examplefn(t); }, 100);
> }
Yes. After some discuss in this topic I would change it to a simpler
version.
> here, and further optimized (with regard to maintenance effort and
> compatibility) to
>
> apply: (function () {
> var _createElementFromObj = jsx.dom.createElementFromObj;
> var _runAsync = jsx.dom.timeout.runAsync;
>
> return function (o) {
> var t = _createElementFromObj({
> type: "span",
> childNodes: [
> "\u00a0",
> {
> type: "img",
> properties: {
> width: 10,
> height: 10,
> alt: o.alt,
> src: o.src
> }
> },
> "\u00a0"
> ]
> });
>
> _runAsync(function () { examplefn(t); }, 100);
> };
> }())
>
> (Wrappers like that are functionally optional of course, but I find them
> very useful. Although it escapes me here why you would want to insert the
> equivalent of “ ” before and after the image; this should be done with
> the “margin” CSS property instead.)
Tried to use CSS, but it doesn't work for img. See:
http://jsfiddle.net/w7BAu/
Tested on Firefox 17.0.1 and IE9 (Windows 7, 64 bit).
> There are times when extra closures are a good idea, and there are times
> when they are not. There is no definitive answer here, but my code should
> give you some idea.
I think that I created little bit overcomplicated my code and now I
rewrite it in a simpler version. No need extra closure in that case,
like mine.
--
Cezary Tomczyk
http://www.ctomczyk.pl/
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2013-01-08 12:35 +0100 |
| Message-ID | <1718550.E62eDaYUNW@PointedEars.de> |
| In reply to | #18013 |
Cezary Tomczyk wrote:
> W dniu 2013-01-07 04:36, Thomas 'PointedEars' Lahn pisze:
>> Cezary Tomczyk wrote:
> [...]
>>>> Cezary Tomczyk wrote:
> [...]
>>>>> Version 1
>>>>>
>>>>> var el = document.getElementById('test');
>>>>> var fn = function(){
>>>>> if( !el ){
>>>>> // fallback if el is not available and then return
>>>>> }
>>>>> return el;
>>>>> };
>>>>>
>>>>> Version 2
>>>>>
>>>>> var fn = (function(){
>>>>> var el = document.getElementById('test');
>>>>>
>>>>> if(el){
>>>>> return function(){
>>>>> return el;
>>>>> }
>>>>> } else {
>>>>> // fallback if el is not available and then return
>>>>> }
>>>>> }());
> [...]
>
>>>> Static code analysis has a hard(er) time recognizing that “fn” actually
>>>> refers to a function in Version 2. AFAIK, the JSDoc Toolkit cannot
>>>> deal with it at all (but my JSdoc is going to).
>>> True, but they are two different examples.
>> Your point being?
>
> I was thinking that even if the functions are different then variable
> name is the same. I thought that JSdoc will catch this, but this doesn't
> make sense. When both of functions will be used in the same scope then
> Version 2 will overwrite Version 1.
Not all functions need be documented, so a documentor should consider the
documentation for a function to be finished when it sees the next “function”
keyword at the same nesting level. However, an exception needs to be made
for extra closures, because the outer function that returns the actual
function is not the function, and its parameter list does not contain the
parameters, that you usually want to document. Yet the identifier is
assigned the return value of that outer function, and you do want to
document the identifier if it is globally available or forced by the
developer to be documented.
>> Your code does not make sense to me at all, regardless of possible
>> inefficiencies. You are creating on initialization an ”img” object only
>> to clone it non-recursively (assuming this works) when the returned
>> function is called only to skip the “width” and “height” assignment –
>> seriously?
>
> I made a test and seems that creating once img node with properties and
> clone them later every time is faster than creating new img node and
> adding new properties. Just a small optimization.
Even if that was so (never trust benchmarks), it adds a dependency on
Node::cloneNode().
>> […] it escapes me here why you would want to insert
>> the equivalent of “ ” before and after the image; this should be
>> done with the “margin” CSS property instead.)
>
> Tried to use CSS, but it doesn't work for img. See:
> http://jsfiddle.net/w7BAu/
>
> Tested on Firefox 17.0.1 and IE9 (Windows 7, 64 bit).
AISB, use the “margin” property.
--
PointedEars
[toc] | [prev] | [next] | [standalone]
| From | Cezary Tomczyk <cezary.tomczyk@gmail.com> |
|---|---|
| Date | 2013-01-09 08:34 +0100 |
| Message-ID | <kcj6j1$p6v$1@speranza.aioe.org> |
| In reply to | #18019 |
W dniu 2013-01-08 12:35, Thomas 'PointedEars' Lahn pisze: > Cezary Tomczyk wrote: [...] >> I was thinking that even if the functions are different then variable >> name is the same. I thought that JSdoc will catch this, but this doesn't >> make sense. When both of functions will be used in the same scope then >> Version 2 will overwrite Version 1. > > Not all functions need be documented, so a documentor should consider the > documentation for a function to be finished when it sees the next “function” > keyword at the same nesting level. However, an exception needs to be made > for extra closures, because the outer function that returns the actual > function is not the function, and its parameter list does not contain the > parameters, that you usually want to document. Yet the identifier is > assigned the return value of that outer function, and you do want to > document the identifier if it is globally available or forced by the > developer to be documented. I am just playing with JSdoc. Will see how it works. >>> Your code does not make sense to me at all, regardless of possible >>> inefficiencies. You are creating on initialization an ”img” object only >>> to clone it non-recursively (assuming this works) when the returned >>> function is called only to skip the “width” and “height” assignment – >>> seriously? >> >> I made a test and seems that creating once img node with properties and >> clone them later every time is faster than creating new img node and >> adding new properties. Just a small optimization. > > Even if that was so (never trust benchmarks), it adds a dependency on > Node::cloneNode(). I made (also) benchmark as a standalone test and time I measured using simple new Date object. As for dependency: yes, I know, but in this case there should be no problem. >>> […] it escapes me here why you would want to insert >>> the equivalent of “ ” before and after the image; this should be >>> done with the “margin” CSS property instead.) >> >> Tried to use CSS, but it doesn't work for img. See: >> http://jsfiddle.net/w7BAu/ >> >> Tested on Firefox 17.0.1 and IE9 (Windows 7, 64 bit). > > AISB, use the “margin” property. Yes, this may work. However, I need to test it. Thanks. -- Cezary Tomczyk http://www.ctomczyk.pl/
[toc] | [prev] | [next] | [standalone]
| From | David Mark <dmark.cinsoft@gmail.com> |
|---|---|
| Date | 2013-01-05 09:13 -0800 |
| Message-ID | <04c4a734-68df-451c-9caa-8a9d93ccb9da@f8g2000yqa.googlegroups.com> |
| In reply to | #17925 |
On Jan 3, 4:58 pm, Cezary Tomczyk <cezary.tomc...@gmail.com> wrote:
> I have a two versions of code. They are just only examples and contains
> simple operations, but I want to understand more deeply some general things.
>
> Version 1
>
> var el = document.getElementById('test');
> var fn = function(){
> if( !el ){
> // fallback if el is not available and then return
> }
> return el;
>
> };
>
> Version 2
>
> var fn = (function(){
> var el = document.getElementById('test');
>
> if(el){
> return function(){
> return el;
> }
> } else {
> // fallback if el is not available and then return
> }
>
> }());
>
> Correct me, if I am wrong.
>
> a) Version 1 has an advantage over Version 2, because Version 2 is
> slower (?) and consumes more memory (?).
> b) Version 2 has a closure and inside fn everything is not available
> outside (except what return "return").
>
> Anything else what can be said about advantages or differences between them?
>
> --
var fn;
var el = ...
if (el) {
fn = ...
}
Now, before you start another bit of that *requires* the "fn"
function, make sure it exists:
if (fn) {
...
}
[toc] | [prev] | [next] | [standalone]
| From | Cezary Tomczyk <cezary.tomczyk@gmail.com> |
|---|---|
| Date | 2013-01-06 11:09 +0100 |
| Message-ID | <kcbiha$f20$1@speranza.aioe.org> |
| In reply to | #17959 |
W dniu 2013-01-05 18:13, David Mark pisze:
[...]
> var fn;
> var el = ...
>
>
> if (el) {
> fn = ...
> }
>
> Now, before you start another bit of that *requires* the "fn"
> function, make sure it exists:
>
> if (fn) {
> ...
> }
Yes, this is a "well-known style" that I know from My Library which I
mostly use. :-)
As for above code: maybe it is better to catch exception like this
(example):
if (fn) {
} else {
throw "No method fn";
}
Of course, I understand that not all scenarios needs this.
However, sometimes it is better to make a closure to hide some variables
and implementations that is not available on the outside. The questions
is when is is really needed?
Example from MyLibrary:
var elementUniqueId = (function () {
var it = 0;
return function (el) {
return el.uniqueID || (el.uniqueID = '_api' + it++);
};
})();
Why it can not be as a:
var elementUniqueId, it = 0;
elementUniqueId = function (el) {
return el.uniqueID || (el.uniqueID = '_api' + it++);
})();
The closure here is probably because there is a risk of overwrite
variable "it", right? But disadvantage of this is that closure needs
extra memory and as I suppose it is not efficient. Correct me if I am wrong.
--
Cezary Tomczyk
http://www.ctomczyk.pl/
[toc] | [prev] | [next] | [standalone]
| From | David Mark <dmark.cinsoft@gmail.com> |
|---|---|
| Date | 2013-01-06 12:56 -0800 |
| Message-ID | <7598b8a8-0d44-43a6-9b8e-f1657068a484@w8g2000yqm.googlegroups.com> |
| In reply to | #17980 |
On Jan 6, 5:09 am, Cezary Tomczyk <cezary.tomc...@gmail.com> wrote:
> W dniu 2013-01-05 18:13, David Mark pisze:
> [...]
>
> > var fn;
> > var el = ...
>
> > if (el) {
> > fn = ...
> > }
>
> > Now, before you start another bit of that *requires* the "fn"
> > function, make sure it exists:
>
> > if (fn) {
> > ...
> > }
>
> Yes, this is a "well-known style" that I know from My Library which I
> mostly use. :-)
I think everybody should be using it at this point. Doesn't take long
to figure out it is the only simple way to keep things straight in a
cross-browser script (as well as any plug-ins) of any real depth.
Otherwise, even basic tasks like enabling command buttons at the
outset (once the required API functions for each are detected) becomes
a nightmare. And, of course, presenting a toolbar with buttons that
call empty functions (or that break as a result of calling empty
functions) is not going to please anyone.
>
> As for above code: maybe it is better to catch exception like this
> (example):
>
> if (fn) {} else {
>
> throw "No method fn";
>
> }
You could for debugging purposes, but then the exception thrown by the
browser will be similar. I've taken to calling such bonus code
"scaffolding" and the Jessie builder removes it for production (by
which time you should have encountered and corrected such oversights).
>
> Of course, I understand that not all scenarios needs this.
> However, sometimes it is better to make a closure to hide some variables
> and implementations that is not available on the outside. The questions
> is when is is really needed?
One API function should not be able to change "members" of another.
>
> Example from MyLibrary:
>
> var elementUniqueId = (function () {
> var it = 0;
> return function (el) {
> return el.uniqueID || (el.uniqueID = '_api' + it++);
> };
>
> })();
>
> Why it can not be as a:
>
> var elementUniqueId, it = 0;
>
> elementUniqueId = function (el) {
> return el.uniqueID || (el.uniqueID = '_api' + it++);
>
> })();
Other than the typo at the end, that's fine. However, other functions
could change the "it" variable, which would foul up this function.
That's why you use the module pattern in this case.
>
> The closure here is probably because there is a risk of overwrite
> variable "it", right?
Exactly.
> But disadvantage of this is that closure needs
> extra memory and as I suppose it is not efficient. Correct me if I am wrong.
It will use extra memory and in My Library there are cases where this
is done for no good reason. There are also cases where functions could
potentially foul up the works of others. Libraries churned out by the
Jessie builder do not have either of these issues as I defined strict
authoring rules (not to be confused with "use strict" of course) from
the outset.
[toc] | [prev] | [next] | [standalone]
| From | Cezary Tomczyk <cezary.tomczyk@gmail.com> |
|---|---|
| Date | 2013-01-07 22:53 +0100 |
| Message-ID | <kcfg47$31q$1@speranza.aioe.org> |
| In reply to | #17988 |
W dniu 2013-01-06 21:56, David Mark pisze:
> On Jan 6, 5:09 am, Cezary Tomczyk <cezary.tomc...@gmail.com> wrote:
>> W dniu 2013-01-05 18:13, David Mark pisze:
>> [...]
>>
>>> var fn;
>>> var el = ...
>>
>>> if (el) {
>>> fn = ...
>>> }
>>
>>> Now, before you start another bit of that *requires* the "fn"
>>> function, make sure it exists:
>>
>>> if (fn) {
>>> ...
>>> }
>>
>> Yes, this is a "well-known style" that I know from My Library which I
>> mostly use. :-)
>
> I think everybody should be using it at this point. Doesn't take long
> to figure out it is the only simple way to keep things straight in a
> cross-browser script (as well as any plug-ins) of any real depth.
> Otherwise, even basic tasks like enabling command buttons at the
> outset (once the required API functions for each are detected) becomes
> a nightmare. And, of course, presenting a toolbar with buttons that
> call empty functions (or that break as a result of calling empty
> functions) is not going to please anyone.
I didn't thought really about empty function as an alternative in case
if some test of feature is not passed :-) That was just an example, but
I need to be more strictly in the future. Posting just code and thinking
that readers have a "crystal ball" to guess what I mean is not a good
idea :-)
>> As for above code: maybe it is better to catch exception like this
>> (example):
>>
>> if (fn) {} else {
>>
>> throw "No method fn";
>>
>> }
>
> You could for debugging purposes, but then the exception thrown by the
> browser will be similar. I've taken to calling such bonus code
> "scaffolding" and the Jessie builder removes it for production (by
> which time you should have encountered and corrected such oversights).
Maybe in some cases "throw" can send some "event" to tracking system
about that. So, then errors can be easy tracked by any system like
Google Analytics or Adobe Omniture or something similar.
>> Of course, I understand that not all scenarios needs this.
>> However, sometimes it is better to make a closure to hide some variables
>> and implementations that is not available on the outside. The questions
>> is when is is really needed?
>
> One API function should not be able to change "members" of another.
Generally, I agree.
>>
>> Example from MyLibrary:
>>
>> var elementUniqueId = (function () {
>> var it = 0;
>> return function (el) {
>> return el.uniqueID || (el.uniqueID = '_api' + it++);
>> };
>>
>> })();
>>
>> Why it can not be as a:
>>
>> var elementUniqueId, it = 0;
>>
>> elementUniqueId = function (el) {
>> return el.uniqueID || (el.uniqueID = '_api' + it++);
>>
>> })();
>
> Other than the typo at the end, that's fine. However, other functions
> could change the "it" variable, which would foul up this function.
> That's why you use the module pattern in this case.
Ok
>> The closure here is probably because there is a risk of overwrite
>> variable "it", right?
>
> Exactly.
:-)
>> But disadvantage of this is that closure needs
>> extra memory and as I suppose it is not efficient. Correct me if I am wrong.
>
> It will use extra memory and in My Library there are cases where this
> is done for no good reason. There are also cases where functions could
> potentially foul up the works of others. Libraries churned out by the
> Jessie builder do not have either of these issues as I defined strict
> authoring rules (not to be confused with "use strict" of course) from
> the outset.
I am watching Jessie, also :-)
--
Cezary Tomczyk
http://www.ctomczyk.pl/
[toc] | [prev] | [next] | [standalone]
| From | Luc Yen <luc@goal.tw> |
|---|---|
| Date | 2013-01-05 12:54 -0800 |
| Message-ID | <c1a21806-0357-4550-9ae3-7db2de8dd5d5@googlegroups.com> |
| In reply to | #17925 |
Cezary Tomczyk於 2013年1月4日星期五UTC+8上午5時58分48秒寫道:
> I have a two versions of code. They are just only examples and contains
>
> simple operations, but I want to understand more deeply some general things.
>
[...]
>
> a) Version 1 has an advantage over Version 2, because Version 2 is
>
> slower (?) and consumes more memory (?).
>
> b) Version 2 has a closure and inside fn everything is not available
>
> outside (except what return "return").
>
>
>
> Anything else what can be said about advantages or differences between them?
>
>
>
> --
>
> Cezary Tomczyk
>
> http://www.ctomczyk.pl/
The usage is quite different, for version 1:
var test = fn(); // return the current 'el' value or something else
Since 'el' can be changed anytime in its execute context, the result is unpredictable.
For version 2, you must first create a variable to hold the returned function if 'el' is defined.
var fnGetTestEl = fn(); // (1)
At this point, the 'el' is fixed and can't be accessed outside it's context. Later, you use:
var elTest = fnGetTestEl();
Every time you invoke this function, the result is predictable. (if that id="test" element is still there)
The difference is version 2 must eventually return a *callable* expression in that fallback part.
It could be:
if (el) {
return function() { return el; };
} else {
// fallback process
return function() { return null; }; // simply state that we can't find el at first place
}
Or something like:
if (el) {
return function() { return el; };
} else {
// el = document.createElement('div');
// el.id = 'test';
// maybe inject el into the document here
return function() { return el; }; // now el is properly defined
}
[toc] | [prev] | [next] | [standalone]
| From | Cezary Tomczyk <cezary.tomczyk@gmail.com> |
|---|---|
| Date | 2013-01-06 21:38 +0100 |
| Message-ID | <kccnb8$c47$1@speranza.aioe.org> |
| In reply to | #17964 |
W dniu 2013-01-05 21:54, Luc Yen pisze:
[...]
> The usage is quite different, for version 1:
> var test = fn(); // return the current 'el' value or something else
> Since 'el' can be changed anytime in its execute context, the result is unpredictable.
We can also assuming that el will never be changed.
> For version 2, you must first create a variable to hold the returned function if 'el' is defined.
> var fnGetTestEl = fn(); // (1)
> At this point, the 'el' is fixed and can't be accessed outside it's context. Later, you use:
> var elTest = fnGetTestEl();
> Every time you invoke this function, the result is predictable. (if that id="test" element is still there)
That's true.
> The difference is version 2 must eventually return a *callable* expression in that fallback part.
> It could be:
>
> if (el) {
> return function() { return el; };
> } else {
> // fallback process
> return function() { return null; }; // simply state that we can't find el at first place
> }
>
> Or something like:
>
> if (el) {
> return function() { return el; };
> } else {
> // el = document.createElement('div');
> // el.id = 'test';
> // maybe inject el into the document here
> return function() { return el; }; // now el is properly defined
> }
This is true according to fallback, but I was thinking about memory
management and efficient. After study more closely
http://jibbering.com/faq/notes/closures/ seems that:
var fn = (function(){
var t = 'test';
return function(){
return t;
};
}());
closure is executed only once and return reference to anonymous
function, but, as I understand, closure can not be dispose by garbage
collector due to stored reference of t inside returned anonymous
function. If I understand it correctly.
--
Cezary Tomczyk
http://www.ctomczyk.pl/
[toc] | [prev] | [standalone]
Page 2 of 2 — ← Prev page 1 [2]
Back to top | Article view | comp.lang.javascript
csiph-web