Javascript: how much more efficient is forked function declaration?

I just read this article about the named functional expressions and their incompatibility with IE <= 8.

I am interested in, in particular, one statement:

A common pattern in web development is to define fork functions based on some kind of function test that provides the best performance.

Example taken from his page:

var contains = (function() { var docEl = document.documentElement; if (typeof docEl.compareDocumentPosition != 'undefined') { return function(el, b) { return (el.compareDocumentPosition(b) & 16) !== 0; }; } else if (typeof docEl.contains != 'undefined') { return function(el, b) { return el !== b && el.contains(b); }; } return function(el, b) { if (el === b) return false; while (el != b && (b = b.parentNode) != null); return el === b; }; })(); 

When I see this, my immediate reaction is that it would be terrible to maintain. Code written this way cannot really be easily understood.

In this case, instead of conditionally defining a function inside another function, which is then called immediately after the declaration of an external function, you can write a function nested if s. That would be longer, but, in my opinion, easier to understand (although I come from C / C ++ / Java).

I would prefer answers that include some test numbers or explanations of how these functions will differ at runtime.

+4
source share
4 answers

Javascript: how much more efficient is forked function declaration?

Disabling any magic optimization performed using JIT / run-time is "worth it" in the same way as to call any function. Functions are simply objects that are often stored in variables (or properties).

How "effective" the version that returns a specialized object-object depends on factors, including (but not limited to):

  • the number of times the resulting function is executed (1x = no gain) and
  • the "cost" of the branch compared to another code (depends) and
  • the "cost" of making the specified closure (very cheap)

For a cheap branch or a small number of executions, the amount of "efficiency" is reduced. If there is a specific precedent, then check this and you will have an β€œanswer”.

When I see this, my immediate reaction is that it would be terrible to maintain. Code written this way cannot really be easily understood.

This example does not necessarily do it fairly, IMOHO and is useless for other reasons. I think that providing an anonymous external function with an explicit name - this can be done even for expression functions - could help, for example, clarify an intention. Write the code first to be clean. Then run benchmark analysis and correct if necessary. The likelihood of "slow parts" will not be what was originally expected.

Some of them are "not easy to understand" - it is simply ignorance of this construction (without implying anything negative here), on the other hand, every language that I know about has functions that are abused in cases where there are cleaner solutions.

In this case, instead of conditionally defining the function inside another function, which is then called immediately after the declaration of the external function, you can write a function of nested ifs. That would be longer, but, in my opinion, easier to understand (although I come from C / C ++ / Java).

Again, the exact case seems messy, IMOHO. However, JavaScript is not C / C ++ / Java, and function-like-first-class values ​​and closures do not exist in C / C ++ / Java (this is a little white lie, closures can be emulated in Java, and newer C ++ supports some AFAIK closure form - but I do not use C ++).

Thus, this construct is not considered in these other languages ​​because other languages ​​do not support it easily (or in general) - it does not say anything about the viability of the approach (in JavaScript or elsewhere) in general.

I would prefer answers that include some test numbers or explanations of how these functions will differ at runtime.

See above.


Deploy the highlighted bold portion at the top:

A function is "just an object" that is "applied" (read: called) with an operator (...) .

 function x () { alert("hi") } x() // alerts window.x() // alerts -- just a property (assumes global scope above) a = {hello: x} a.hello() // alerts (still property) b = a.hello b() // alerts (still just a value that can be invoked) 

Happy coding.

+2
source

It is very effective. Pay attention to (); in the end. This executes and assigns the result of the external contains function immediately. This is much more efficient than doing basic logic every time the contains function is used.

Instead of checking every time that contains() is called that compareDocumentPosition exists, this is done once the first time the code is executed. The fact that compareDocumentPosition exists or does not exist will not change, so only checking it will be ideal.

+3
source

The main advantage, as mentioned, is speed. The presence of one function with a nested if means that the condition must be re-read each time the function is called. However, we know that the results of the conditions will never change.

If you are concerned about readability, a similar effect can be achieved in a more readable way:

 var contains = (function () { var docEl = document.documentElement; if (typeof docEl.compareDocumentPosition != 'undefined') { return contains_version1; } else if (typeof docEl.contains != 'undefined') { return contains_version2; } else { return contains_version3; } function contains_version1() { ... } function contains_version2() { ... } function contains_version3() { ... } })(); 

Or:

 (function () { var docEl = document.documentElement; var contains = typeof docEl.compareDocumentPosition != 'undefined' ? contains_version1 : typeof docEl.contains != 'undefined' ? contains_version2 : contains_version3; function contains_version1() { ... } function contains_version2() { ... } function contains_version3() { ... } })(); 
+1
source

This is a relatively strange construct if you come from a pure C-background, but should be easily matched with well-known concepts for a C ++ / Java person. This specific example is essentially a base implementation class with an abstract function with 3 derived classes that implement it differently for different browsers. Using "if" or "switch" for this case is not the best approach in both C ++ and Java.

Most likely, the set of such functions will be packaged into a β€œclass”, in which case it will be closely tied to the base class with virtual functions and several implementations for each browser ...

0
source

Source: https://habr.com/ru/post/1346133/


All Articles