Check if Function Exists

S

shapper

Hello,

I am calling a Javascript function as follows:

tinyMCE.init({
editor_selector: "TinyMce-Extended",
...

In some pages I am not loading the tinyMCE .js file.

Is it possible to run tinyMCE.init file only if tinyMCE exists so I
don't get an error on my page Javascript?

Thanks,
Miguel
 
M

Martin Honnen

shapper said:
I am calling a Javascript function as follows:

tinyMCE.init({
editor_selector: "TinyMce-Extended",
...

In some pages I am not loading the tinyMCE .js file.

Is it possible to run tinyMCE.init file only if tinyMCE exists so I
don't get an error on my page Javascript?

if (typeof tinyMCE != 'undefined' && typeof tinyMCE.init == 'function')
{
tinyMCE.init(...);
}
 
L

Logos

Martin said:
if (typeof tinyMCE != 'undefined' && typeof tinyMCE.init == 'function')
{
tinyMCE.init(...);
}

Martin's code is robust, but if memory serves typeof is a very
expensive in terms of processing cycles. I would just test for the
existence of the namespace object, then pop the function call into a
try/catch block:

if(top.tinyMCE) { try { tinyMCE.init(); } catch(e) { alert
(e.message); } }

If you don't like top, you can always use document instead (or so my
admittedly faulty memory tells me).
 
L

Lasse Reichstein Nielsen

Logos said:
Martin's code is robust, but if memory serves typeof is a very
expensive in terms of processing cycles.

Depends on implementation, but it doesn't have to be much more
expensive than just reading the property.
I would just test for the
existence of the namespace object, then pop the function call into a
try/catch block:

Try/catch are *much* more likely to be expensive than the typeof
operator.
if(top.tinyMCE) { try { tinyMCE.init(); } catch(e) { alert
(e.message); } }

If you don't like top, you can always use document instead (or so my
admittedly faulty memory tells me).

Neither "top" nor "document" are any good, if it's a top-level declared
value. Use either "window" or, if also at top level, "this", or get a
reference to the global object using (funcion(){return this;})().

/L
 
G

Garrett Smith

Lasse said:
Depends on implementation, but it doesn't have to be much more
expensive than just reading the property.


I am unaware of an implementation where typeof is more expensive than
[[Get]] plus [[ToBoolean]].
Try/catch are *much* more likely to be expensive than the typeof
operator.

Yes, if the error is thrown and caught in the catch block that would be
more expensive.

However, if the catch block is not entered (when no error is thrown in
the try), the cost should not be much greater.

For functions that use try/catch, an implementation could perform a
lexical scan to determine if the identifier in the catch block has been
accessed by normal means, when eval is not used directly. In the case of
an empty catch block, an implementation would seem to want to optimize
that. Don't you think?

I should probably provide some sort of example.

There is no way for a program to determine if the |ex| variable and
augmented scope chain "as if by the expression new Object" in a catch
block like:-

try {
throw 0;
} catch(ex){}

This goes back to the "if a tree falls in the forest" argument from
prior "arguments.callee" discussions.

Garrett
 
T

Thomas 'PointedEars' Lahn

Garrett said:
Lasse said:
Depends on implementation, but it doesn't have to be much more
expensive than just reading the property.

I am unaware of an implementation where typeof is more expensive than
[[Get]] plus [[ToBoolean]].

Add me.
Yes, if the error is thrown and caught in the catch block that would be
more expensive.

However, if the catch block is not entered (when no error is thrown in
the try), the cost should not be much greater.

You are ignoring the fact that for each executed statement entering of an
additional exception state must be considered in any case.
For functions that use try/catch, an implementation could perform a
lexical scan to determine if the identifier in the catch block has been
accessed by normal means, when eval is not used directly. In the case of
an empty catch block, an implementation would seem to want to optimize
that. Don't you think?

No, I don't think so.
I should probably provide some sort of example.

There is no way for a program to determine if the |ex| variable and
augmented scope chain "as if by the expression new Object" in a catch
block like:-

Parse error. However, there is no way for an implementation to determine if
a block would throw an exception without executing this block to begin with.
It boils down to the halting problem, which AFAIK remains unsolved.
try {
throw 0;
} catch(ex){}

This goes back to the "if a tree falls in the forest" argument from
prior "arguments.callee" discussions.

Not really. Even if the `catch' block is empty, potential exceptions must
be considered because a different control flow would have to be followed then.


PointedEars
 
L

Logos

Lasse said:
Depends on implementation, but it doesn't have to be much more
expensive than just reading the property.

That's true of any part of javascript. I'm only really familiar with
IE 5&6 and FF 2& 3's engines, which are slow on typeof AFAIK. Which
engine(s) are you referring to?
Try/catch are *much* more likely to be expensive than the typeof
operator.

Only if you trigger the catch more often than you would evaluate
typeof. From what we wrote, I assumed that tinyMCE.init would be
present more often than not.
Neither "top" nor "document" are any good, if it's a top-level declared
value. Use either "window" or, if also at top level, "this", or get a
reference to the global object using (funcion(){return this;})().

Ummm...by definition, "top" is in fact the top level document.
They're synonymous. You can most definitely access any variables
declared at the top level using top. I use this syntax when I have a
code library that might be in an iframe, or might be in the top level
page.
 
L

Logos

Garrett said:
I am unaware of an implementation where typeof is more expensive than
[[Get]] plus [[ToBoolean]].

I have to say I have no clue what this means...could I get a fuller
explanation?
 
T

Thomas 'PointedEars' Lahn

Logos said:
That's true of any part of javascript. I'm only really familiar with
IE 5&6 and FF 2& 3's engines, which are slow on typeof AFAIK.

Wishful thinking. As if the Specification would not tell already, the
following test shows a `typeof' test to be roughly 200 times faster in
Firefox 3.0.0.10/Linux than a `try...catch' where the `try' block would
throw an exception (Worst Case); that is, where the `catch' block is empty
(Best Case):

var d = new Date();
for (var i = 10000; i--;) try { x } catch (e) {}
var t = new Date() - d;

var d2 = new Date();
for (var i = 10000; i--;) typeof x == "undefined"
var t2 = new Date() - d2;

console.log(
"A (try...catch): ", t, " ms\n",
"B (typeof): ", t2, " ms\n",
"Ratio A/B: ", t / t2);
Which engine(s) are you referring to?

SpiderMonkey (JavaScript) 1.8.
Only if you trigger the catch more often than you would evaluate
typeof.

The following benchmark test tells me that `typeof' it is 4 to 10 times
faster in Firefox 3.0.0.10/Linux in the best case, too:

var benchmark = [];

for (var j = 100; j--;)
{
if (typeof benchmark[0] == "undefined") benchmark[0] = [];

var d = new Date();
for (var i = 1000; i--;) try { d } catch (e) {}
benchmark[0].push(new Date() - d);

if (typeof benchmark[1] == "undefined") benchmark[1] = [];

var d2 = new Date();
for (var i = 100; i--;) typeof d2 == "undefined"
benchmark[1].push(new Date() - d2);
}

Array.prototype.avg = function() {
var sum = 0;

if (typeof this.forEach == "function")
{
this.forEach(function(v, i, a) { sum += v; });
}
else
{
for (var i = this.length; i--;) sum += this;
}

return sum / this.length;
};

var avg = [benchmark[0].avg(), benchmark[1].avg()];

console.log(
"A (try...catch): ", avg[0], "ms\n",
"B (typeof): ", avg[1], "ms\n",
"Ratio A/B: ", avg[0] / avg[1]);
From what we wrote, I assumed that tinyMCE.init would be
present more often than not.

Apparently irrelevant.
Ummm...by definition, "top" is in fact the top level document.
They're synonymous.

Nonsense. `top' is a property of proprietary Window objects to refer to the
topmost frameset, a Window object. `document' is a property of proprietary
Window objects or a host-defined property of the Global Object to refer to a
Document (usually HTMLDocument) object.
You can most definitely access any variables declared at the top level
using top.

That is, provided `window' is in the scope chain and the DOM of the UA works
that way.
I use this syntax when I have a code library that might be in an iframe,
or might be in the top level page.

You don't know really what you are talking about. "top level page"?


PointedEars
 
L

Lasse Reichstein Nielsen

Logos said:
That's true of any part of javascript. I'm only really familiar with
IE 5&6 and FF 2& 3's engines, which are slow on typeof AFAIK. Which
engine(s) are you referring to?

Any, pretty much.
A quick test of the relative speeds of "x in o", "Boolean(o.x)" and
"typeof x.x != 'undefined'" would be:
---
var x = { x: 42, y : 42 };
var t0 = new Date();
for (var i = 0; i < 1000000; i++) {
var u = "x" in x;
}
var t1 = new Date();
for (var i = 0; i < 1000000; i++) {
var u = Boolean(x.x);
}
var t2 = new Date();
for (var i = 0; i < 1000000; i++) {
var u = (typeof x.x != "undefined");
}
var t3 = new Date();
var result = [t1-t0,t2-t1,t3-t2]
---

It shows the following:
FF 3.0.10: 391,1071,444
Chrome 2.0.180: 737,1023,663
Opera 9.64: 250,359,266
IE 7: 500,1000,564 (estimated)
Safari 4 beta: 161,219,277

I.e., almost exactly the same pattern for all browsers: using "in" is
faster than "typeof", which is (much) faster than checking the actual
value (the exception begin Chrome that is fastest on typeof).
Ummm...by definition, "top" is in fact the top level document.
They're synonymous.

No, it's the top level window.
You can most definitely access any variables
declared at the top level using top.

The top level frame's global variables, yes (unless prohibited by XSS
security).
I use this syntax when I have a code library that might be in an
iframe, or might be in the top level page.

If the library is in the iframe, then you won't access it like this.
If it's in the top level page, you can access it from the iframe.

/L
 
G

Garrett Smith

Thomas said:
You are ignoring the fact that for each executed statement entering of an
additional exception state must be considered in any case.

I am not ignoring that. I am proposing that the entering the execution
of the catch clause could be optimized.
No, I don't think so.


Parse error. However, there is no way for an implementation to determine if
a block would throw an exception without executing this block to begin with.
It boils down to the halting problem, which AFAIK remains unsolved.


Not really. Even if the `catch' block is empty, potential exceptions must
be considered because a different control flow would have to be followed then.

In ES3, when a catch block is entered, the scope chain is augmented "as
if by the expression new Object". The catch block's identifier is then
bound to that new object.

What I was trying to convey in one of my bungled sentences was that if
the catch block is empty, the implementation should not have to create
that new object ("as if by the expression") and augmenting the scope
chain should be unnecessary. No program could possibly observe such
optimization. Because such optimization would be unobservable, it could
not be shown to be non-complian. Therefore, the optimization could be
considered compliant (even though not following ECMA-262 specification
to the letter)).

It would also be possible to make similar optimizations for catch blocks
that do not reference the caught exception and do not make direct use of
eval.

This could be optimized:-

try {
throw atom;
} catch(cat) {
alert(12);
}

The program would not be able to observe if catch block had augmented
the scope chain with a new object, adding identifier "cat" to it.

This could not be optimized:-

try {
throw atom;
} catch(cat) {
eval("ca" + another);
}

because eval might possibly be doing something with that identifier.

And this:-

try {
throw atom;
} catch(cat) {
g("ca" + another);
}

- might be an indirect access to eval which a lexical scan would not be
able to determine.

Of course, the first one, the "alert" call could be an indirect use of
eval, and so could something like: window["eval"](cat);

Garrett
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top