Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Code inside block is wrapped inside parens. Why?

Tags:

javascript

I came across this code and don't understand why the code within the block is wrapped in the parens like an auto-executing function.

function foo(a,b) {
  var b = b || window,
    a = a.replace(/^\s*<!(?:\[CDATA\[|\-\-)/, "/*$0*/"); 
  if (a && /\S/.test(a)) {
    (b.execScript || function (a) {
      b["eval"].call(b, a)
    })(a);
  }
}

The first parameter is the text from a script tag. The only part I don't get is why the script eval is wrapped in parens.

like image 564
gholmes Avatar asked Sep 18 '26 05:09

gholmes


2 Answers

I assume you are talking about this part:

(b.execScript || function (a) {
    b["eval"].call(b, a)
})(a);

This is short form of writing:

if (b.execScript) {
    b.execScript(a);
}
else {
    b["eval"].call(b, a);
}

I.e. execute b.execScript if it is defined, otherwise call b["eval"].call(b, a).

The purpose of the grouping operator is to evaluate ... || ... before the function call, i.e. whatever the result of the grouping operator is, it is treated as function and called by passing a to it.

It looks like the code could be simplified to

(b.execScript || b["eval"])(a);

Though if explicitly setting this to b is necessary, then the function expression is necessary as well, to have two functions that only accept one argument, a.

like image 154
Felix Kling Avatar answered Sep 19 '26 19:09

Felix Kling


(b.execScript || function (a) {
      b["eval"].call(b, a)
    })(a)

This is wrapped in parens because the || statement needs to be evaluated to determine what function to run before being passed an argument.

This code calls b.execScript with argument a if b.execScript exists and is truthy. Otherwise it defines a new function and passes a as an argument to that.

The parens wrap is to make sure that the || statement is evaluated before the function is executed. Without it the logic would go basically, if b.exec doesn't exist, evaluate to the value of the custom function, if it does, evaluate to b.exec.

So with the parens the logic is equivalent to:

if(b.execScript){
   b.execScript(a)
}
else{
  function (a) {
    b["eval"].call(b, a)
  })(a)

}

without it, its equivalent to

if(!b.execScript){ function (a) { b["eval"].call(b, a) })(a) }

like image 30
Ben McCormick Avatar answered Sep 19 '26 19:09

Ben McCormick



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!