Path: csiph.com!aioe.org!news.mb-net.net!open-news-network.org!.POSTED!not-for-mail From: Thomas 'PointedEars' Lahn Newsgroups: comp.lang.javascript Subject: Re: Adding data to a function Date: Tue, 03 May 2016 19:08:27 +0200 Organization: PointedEars Software (PES) Lines: 103 Message-ID: <6849379.UDgNqft9K3@PointedEars.de> References: Reply-To: Thomas 'PointedEars' Lahn NNTP-Posting-Host: 90.228.197.178.dynamic.wless.zhbmb00p-cgnat.res.cust.swisscom.ch Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8Bit X-Trace: gwaiyur.mb-net.net 1462295309 1776 178.197.228.90 (3 May 2016 17:08:29 GMT) X-Complaints-To: abuse@open-news-network.org NNTP-Posting-Date: Tue, 3 May 2016 17:08:29 +0000 (UTC) User-Agent: KNode/4.14.2 Xref: csiph.com comp.lang.javascript:30387 Stefan Ram wrote: > The following function always would recompute > »window.document.getElementById( "info" )«. > > "use strict"; > > function f() > { window.document.getElementById( "info" ).innerHTML > = 'The function "f" was called.'; } > > Is it good style to attach this data to f as a property of f, > so that it does not have to be recomputed each time f is > being called, i.e.: > > "use strict"; > > function f() > { f.info.innerHTML > = 'The function "f" was called.'; } > f.info = document.getElementById( "info" ); > > ? You should avoid "use strict" in the global execution context because it affects all subsequent code – even code that has not been written to run in strict mode (you cannot undo "use strict" in local execution contexts). JSHint warns you about that by default: “W097: Use the function form of "use strict".”) See p. for details. That aside, whether the answer to your question should be “yes” depends on the use-case. By default, functions are extensible objects in ECMAScript implementations, so there is, in theory, nothing wrong with extending them. However, one should take care to avoid name collisions as they are objects that already have and inherit properties. [To that end, my JSX provides jsx.object.findNewProperty().] Also, there is no possibility for a race condition only if the property value is never written twice. And you have to consider the possibility that the element was not in the document tree when the code was first executed, or that the element had been removed or replaced afterwards. A document.getElementById("…") call always works on the *current* document tree. An alternative approach that is still rather efficient, with which name collisions are minimized and race conditions avoided, is the module pattern: var foo = (function (doc) { "use strict"; /* * The value assigned could also be one of a property * of the object to which a reference is returned */ var info = doc.getElementById("info"); return { bar: function (s) { info.innerHTML = s; } }; }(document)); /* executed much later: */ foo.bar("baz"); A variant of this that tends to be more efficient is to initialize a variable or property on first use: var foo = (function (doc) { "use strict"; /* * The value assigned could also be one of a property * of the object to which a reference is returned */ var info = null; return { bar: function (s) { if (info === null) info = doc.getElementById("info"); if (info) info.innerHTML = s; } }; }(document)); Whether the assignment should only take place only if the base object can be resolved depends on the use-case and is a matter for debate; the code runs more smoothly with the test it, but as it is, without error handling, it hides regressions. You would tend to test before assignment if you did not know the markup well that you are working on; for example, you would certainly test, and handle errors explicitly, in a browser extension, and in a bookmarklet that is available to the general public. -- PointedEars FAQ: | SVN: Twitter: @PointedEars2 | ES Matrix: Please do not cc me. / Bitte keine Kopien per E-Mail.