I wanted to write a javascript code that will slide a div in specific direction, distance and in some given time. I wrote this small script. but doesn't work at all. Instead browser gets slow. No change in position is visible.
Can someone tell me how to achieve the result ? I know there are many ready made libraries that can do this easily. But I just wanted to give it a try.
<script type="text/javascript" language="javascript">
var element = '';
var slidePerMS = '';
function slideIt(ele, direction, distance, slideDuration){
element = ele;
var i=0;
slidePerMS = distance / (slideDuration*1000);
for(i=0; i<3000; i++){
setTimeout("changePosition()",1);
}
}
function changePosition(){
var currElement = document.getElementById(element);
currElement.style.left = "'"+slidePerMS+"px'";
}
</script>
SOO many things wrong with that code it's not even funny... Let's see...
You are trying to render a 1,000 FPS animation. This is simply impossible for a browser.
You are passing a string as parameter to setTimeout, which is as evil as eval.
You set slidePerMS once but never change it after, resulting in the div being moved to the exact same spot over and over.
You are setting the style with extra quotes inside - do you put quotes in a CSS file?
That's to name but a few. Try this instead:
<script type="text/javascript" language="javascript">
function slideIt(elem, direction, distance, slideDuration){
var elmt = document.getElementById(elem),
i=0, step = distance / (slideDuration*20),
stepper = setInterval(function() {
i = Math.min(distance,i+step);
elmt.style.left = i+'px';
if( i == distance) clearInterval(stepper);
},50);
}
</script>
You have many problems.
You are treating setTimeout as if it was sleep. Don't do that. It isn't like sleep at all, it runs a function after a given period of time, but doesn't pause the execution of anything else.
This means you just hammer the function repeatedly 3000 times, which is what is locking up the browser.
Instead of using a for loop, you should be using setInterval.
Don't pass a string to setInterval (or setTimeout), it gets evaled, which is slow and hard to debug, and it breaks scope. Pass a function instead.
Inside changePosition you are trying to use a variable called slidePerMS, which is undefined because it is defined in the scope of slideIt.
You are also trying to set left to "'123px'". You can't quote your values in CSS.
Get rid of both the 's.
This is why you can't see any change. Invalid values are ignored in CSS.
How do I make an infinite loop in JavaScript? I'm trying to make a slideshow, which I have working, but I can't get it to loop. I can't even get it to loop twice.
The code I'm using right now is
window.onload = function start() {
slide();
}
function slide() {
var num = 0;
for (num=0;num<=10;num++) {
setTimeout("document.getElementById('container').style.marginLeft='-600px'",3000);
setTimeout("document.getElementById('container').style.marginLeft='-1200px'",6000);
setTimeout("document.getElementById('container').style.marginLeft='-1800px'",9000);
setTimeout("document.getElementById('container').style.marginLeft='0px'",12000);
}
}
Without the for thing in there, it does go through once. When I put in a for, it either makes Firefox lock up, or just loops once. I'm sure this is a really simple thing to do, and even if it has to be loop 1,000,000 times or something instead of infinite, that'd work fine for me.
Also, I don't want to use jQuery or something that someone else created. I'm learning JavaScript, and this is partially to help me learn, and partially because I'm trying to make as many HTML5-based systems as I can.
EDIT: I think the reason it's freezing is because it executes the code all at once, and then just stores it in a cache or something. What I want it to do is go through this once, then start at the top again, which is what I've always thought loops where for. In "batch" (command prompt) scripting, this could be done with a "GOTO" command. I don't know if there's an equivalent in JS or not, but that's really my goal.
The correct approach is to use a single timer. Using setInterval, you can achieve what you want as follows:
window.onload = function start() {
slide();
}
function slide() {
var num = 0, style = document.getElementById('container').style;
window.setInterval(function () {
// increase by num 1, reset to 0 at 4
num = (num + 1) % 4;
// -600 * 1 = -600, -600 * 2 = -1200, etc
style.marginLeft = (-600 * num) + "px";
}, 3000); // repeat forever, polling every 3 seconds
}
You don't want while(true), that will lock up your system.
What you want instead is a timeout that sets a timeout on itself, something like this:
function start() {
// your code here
setTimeout(start, 3000);
}
// boot up the first call
start();
Here's a nice, tidy solution for you: (also see the live demo ->)
window.onload = function start() {
slide();
}
function slide() {
var currMarg = 0,
contStyle = document.getElementById('container').style;
setInterval(function() {
currMarg = currMarg == 1800 ? 0 : currMarg + 600;
contStyle.marginLeft = '-' + currMarg + 'px';
}, 3000);
}
Since you are trying to learn, allow me to explain how this works.
First we declare two variables: currMarg and contStyle. currMarg is an integer that we will use to track/update what left margin the container should have. We declare it outside the actual update function (in a closure), so that it can be continuously updated/access without losing its value. contStyle is simply a convenience variable that gives us access to the containers styles without having to locate the element on each interval.
Next, we will use setInterval to establish a function which should be called every 3 seconds, until we tell it to stop (there's your infinite loop, without freezing the browser). It works exactly like setTimeout, except it happens infinitely until cancelled, instead of just happening once.
We pass an anonymous function to setInterval, which will do our work for us. The first line is:
currMarg = currMarg == 1800 ? 0 : currMarg + 600;
This is a ternary operator. It will assign currMarg the value of 0 if currMarg is equal to 1800, otherwise it will increment currMarg by 600.
With the second line, we simply assign our chosen value to containers marginLeft, and we're done!
Note: For the demo, I changed the negative values to positive, so the effect would be visible.
Perhps this is what you are looking for.
var pos = 0;
window.onload = function start() {
setTimeout(slide, 3000);
}
function slide() {
pos -= 600;
if (pos === -2400)
pos = 0;
document.getElementById('container').style.marginLeft= pos + "px";
setTimeout(slide, 3000);
}
You are calling setTimeout() ten times in a row, so they all expire almost at the same time. What you actually want is this:
window.onload = function start() {
slide(10);
}
function slide(repeats) {
if (repeats > 0) {
document.getElementById('container').style.marginLeft='-600px';
document.getElementById('container').style.marginLeft='-1200px';
document.getElementById('container').style.marginLeft='-1800px';
document.getElementById('container').style.marginLeft='0px';
window.setTimeout(
function(){
slide(repeats - 1)
},
3000
);
}
}
This will call slide(10), which will then set the 3-second timeout to call slide(9), which will set timeout to call slide(8), etc. When slide(0) is called, no more timeouts will be set up.
You can infinitely loop easily enough via recursion.
function it_keeps_going_and_going_and_going() {
it_keeps_going_and_going_and_going();
}
it_keeps_going_and_going_and_going()
The key is not to schedule all pics at once, but to schedule a next pic each time you have a pic shown.
var current = 0;
var num_slides = 10;
function slide() {
// here display the current slide, then:
current = (current + 1) % num_slides;
setTimeout(slide, 3000);
}
The alternative is to use setInterval, which sets the function to repeat regularly (as opposed to setTimeout, which schedules the next appearance only.
Expanding on Ender's answer, let's explore our options with the improvements from ES2015.
First off, the problem in the asker's code is the fact that setTimeout is asynchronous while loops are synchronous. So the logical flaw is that they wrote multiple calls to an asynchronous function from a synchronous loop, expecting them to execute synchronously.
function slide() {
var num = 0;
for (num=0;num<=10;num++) {
setTimeout("document.getElementById('container').style.marginLeft='-600px'",3000);
setTimeout("document.getElementById('container').style.marginLeft='-1200px'",6000);
setTimeout("document.getElementById('container').style.marginLeft='-1800px'",9000);
setTimeout("document.getElementById('container').style.marginLeft='0px'",12000);
}
}
What happens in reality, though, is that...
The loop "simultaneously" creates 44 async timeouts set to execute 3, 6, 9 and 12 seconds in the future. Asker expected the 44 calls to execute one-after-the-other, but instead, they all execute simultaneously.
3 seconds after the loop finishes, container's marginLeft is set to "-600px" 11 times.
3 seconds after that, marginLeft is set to "-1200px" 11 times.
3 seconds later, "-1800px", 11 times.
And so on.
You could solve this by changing it to:
function setMargin(margin){
return function(){
document.querySelector("#container").style.marginLeft = margin;
};
}
function slide() {
for (let num = 0; num <= 10; ++num) {
setTimeout(setMargin("-600px"), + (3000 * (num + 1)));
setTimeout(setMargin("-1200px"), + (6000 * (num + 1)));
setTimeout(setMargin("-1800px"), + (9000 * (num + 1)));
setTimeout(setMargin("0px"), + (12000 * (num + 1)));
}
}
But that is just a lazy solution that doesn't address the other issues with this implementation. There's a lot of hardcoding and general sloppiness here that ought to be fixed.
Lessons learnt from a decade of experience
As mentioned at the top of this answer, Ender already proposed a solution, but I would like to add on to it, to factor in good practice and modern innovations in the ECMAScript specification.
function format(str, ...args){
return str.split(/(%)/).map(part => (part == "%") ? (args.shift()) : (part)).join("");
}
function slideLoop(margin, selector){
const multiplier = -600;
let contStyle = document.querySelector(selector).style;
return function(){
margin = ++margin % 4;
contStyle.marginLeft = format("%px", margin * multiplier);
}
}
function slide() {
return setInterval(slideLoop(0, "#container"), 3000);
}
Let's go over how this works for the total beginners (note that not all of this is directly related to the question):
format
function format
It's immensely useful to have a printf-like string formatter function in any language. I don't understand why JavaScript doesn't seem to have one.
format(str, ...args)
... is a snazzy feature added in ES6 that lets you do lots of stuff. I believe it's called the spread operator. Syntax: ...identifier or ...array. In a function header, you can use it to specify variable arguments, and it will take every argument at and past the position of said variable argument, and stuff them into an array. You can also call a function with an array like so: args = [1, 2, 3]; i_take_3_args(...args), or you can take an array-like object and transform it into an array: ...document.querySelectorAll("div.someclass").forEach(...). This would not be possible without the spread operator, because querySelectorAll returns an "element list", which isn't a true array.
str.split(/(%)/)
I'm not good at explaining how regex works. JavaScript has two syntaxes for regex. There's the OO way (new RegExp("regex", "gi")) and there's the literal way (/insert regex here/gi). I have a profound hatred for regex because the terse syntax it encourages often does more harm than good (and also because they're extremely non-portable), but there are some instances where regex is helpful, like this one. Normally, if you called split with "%" or /%/, the resulting array would exclude the "%" delimiters from the array. But for the algorithm used here, we need them included. /(%)/ was the first thing I tried and it worked. Lucky guess, I suppose.
.map(...)
map is a functional idiom. You use map to apply a function to a list. Syntax: array.map(function). Function: must return a value and take 1-2 arguments. The first argument will be used to hold each value in the array, while the second will be used to hold the current index in the array. Example: [1,2,3,4,5].map(x => x * x); // returns [1,4,9,16,25]. See also: filter, find, reduce, forEach.
part => ...
This is an alternative form of function. Syntax: argument-list => return-value, e.g. (x, y) => (y * width + x), which is equivalent to function(x, y){return (y * width + x);}.
(part == "%") ? (args.shift()) : (part)
The ?: operator pair is a 3-operand operator called the ternary conditional operator. Syntax: condition ? if-true : if-false, although most people call it the "ternary" operator, since in every language it appears in, it's the only 3-operand operator, every other operator is binary (+, &&, |, =) or unary (++, ..., &, *). Fun fact: some languages (and vendor extensions of languages, like GNU C) implement a two-operand version of the ?: operator with syntax value ?: fallback, which is equivalent to value ? value : fallback, and will use fallback if value evaluates to false. They call it the Elvis Operator.
I should also mention the difference between an expression and an expression-statement, as I realize this may not be intuitive to all programmers. An expression represents a value, and can be assigned to an l-value. An expression can be stuffed inside parentheses and not be considered a syntax error. An expression can itself be an l-value, although most statements are r-values, as the only l-value expressions are those formed from an identifier or (e.g. in C) from a reference/pointer. Functions can return l-values, but don't count on it. Expressions can also be compounded from other, smaller expressions. (1, 2, 3) is an expression formed from three r-value expressions joined by two comma operators. The value of the expression is 3. expression-statements, on the other hand, are statements formed from a single expression. ++somevar is an expression, as it can be used as the r-value in the assignment expression-statement newvar = ++somevar; (the value of the expression newvar = ++somevar, for example, is the value that gets assigned to newvar). ++somevar; is also an expression-statement.
If ternary operators confuse you at all, apply what I just said to the ternary operator: expression ? expression : expression. Ternary operator can form an expression or an expression-statement, so both of these things:
smallest = (a < b) ? (a) : (b);
(valueA < valueB) ? (backup_database()) : (nuke_atlantic_ocean());
are valid uses of the operator. Please don't do the latter, though. That's what if is for. There are cases for this sort of thing in e.g. C preprocessor macros, but we're talking about JavaScript here.
args.shift()
Array.prototype.shift. It's the mirror version of pop, ostensibly inherited from shell languages where you can call shift to move onto the next argument. shift "pops" the first argument out of the array and returns it, mutating the array in the process. The inverse is unshift. Full list:
array.shift()
[1,2,3] -> [2,3], returns 1
array.unshift(new-element)
[element, ...] -> [new-element, element, ...]
array.pop()
[1,2,3] -> [1,2], returns 3
array.push(new-element)
[..., element] -> [..., element, new-element]
See also: slice, splice
.join("")
Array.prototype.join(string). This function turns an array into a string. Example: [1,2,3].join(", ") -> "1, 2, 3"
slide
return setInterval(slideLoop(0, "#container"), 3000);
First off, we return setInterval's return value so that it may be used later in a call to clearInterval. This is important, because JavaScript won't clean that up by itself. I strongly advise against using setTimeout to make a loop. That is not what setTimeout is designed for, and by doing that, you're reverting to GOTO. Read Dijkstra's 1968 paper, Go To Statement Considered Harmful, to understand why GOTO loops are bad practice.
Second off, you'll notice I did some things differently. The repeating interval is the obvious one. This will run forever until the interval is cleared, and at a delay of 3000ms. The value for the callback is the return value of another function, which I have fed the arguments 0 and "#container". This creates a closure, and you will understand how this works shortly.
slideLoop
function slideLoop(margin, selector)
We take margin (0) and selector ("#container") as arguments. The margin is the initial margin value and the selector is the CSS selector used to find the element we're modifying. Pretty straightforward.
const multiplier = -600;
let contStyle = document.querySelector(selector).style;
I've moved some of the hard coded elements up. Since the margins are in multiples of -600, we have a clearly labeled constant multiplier with that base value.
I've also created a reference to the element's style property via the CSS selector. Since style is an object, this is safe to do, as it will be treated as a reference rather than a copy (read up on Pass By Sharing to understand these semantics).
return function(){
margin = ++margin % 4;
contStyle.marginLeft = format("%px", margin * multiplier);
}
Now that we have the scope defined, we return a function that uses said scope. This is called a closure. You should read up on those, too. Understanding JavaScript's admittedly bizarre scoping rules will make the language a lot less painful in the long run.
margin = ++margin % 4;
contStyle.marginLeft = format("%px", margin * multiplier);
Here, we simply increment margin and modulus it by 4. The sequence of values this will produce is 1->2->3->0->1->..., which mimics exactly the behavior from the question without any complicated or hard-coded logic.
Afterwards, we use the format function defined earlier to painlessly set the marginLeft CSS property of the container. It's set to the currnent margin value multiplied by the multiplier, which as you recall was set to -600. -600 -> -1200 -> -1800 -> 0 -> -600 -> ...
There are some important differences between my version and Ender's, which I mentioned in a comment on their answer. I'm gonna go over the reasoning now:
Use document.querySelector(css_selector) instead of document.getElementById(id)
querySelector was added in ES6, if I'm not mistaken. querySelector (returns first found element) and querySelectorAll (returns a list of all found elements) are part of the prototype chain of all DOM elements (not just document), and take a CSS selector, so there are other ways to find an element than just by its ID. You can search by ID (#idname), class (.classname), relationships (div.container div div span, p:nth-child(even)), and attributes (div[name], a[href=https://google.com]), among other things.
Always track setInterval(fn, interval)'s return value so it can later be closed with clearInterval(interval_id)
It's not good design to leave an interval running forever. It's also not good design to write a function that calls itself via setTimeout. That is no different from a GOTO loop. The return value of setInterval should be stored and used to clear the interval when it's no longer needed. Think of it as a form of memory management.
Put the interval's callback into its own formal function for readability and maintainability
Constructs like this
setInterval(function(){
...
}, 1000);
Can get clunky pretty easily, especially if you are storing the return value of setInterval. I strongly recommend putting the function outside of the call and giving it a name so that it's clear and self-documenting. This also makes it possible to call a function that returns an anonymous function, in case you're doing stuff with closures (a special type of object that contains the local state surrounding a function).
Array.prototype.forEach is fine.
If state is kept with the callback, the callback should be returned from another function (e.g. slideLoop) to form a closure
You don't want to mush state and callbacks together the way Ender did. This is mess-prone and can become hard to maintain. The state should be in the same function that the anonymous function comes from, so as to clearly separate it from the rest of the world. A better name for slideLoop could be makeSlideLoop, just to make it extra clear.
Use proper whitespace. Logical blocks that do different things should be separated by one empty line
This:
print(some_string);
if(foo && bar)
baz();
while((some_number = some_fn()) !== SOME_SENTINEL && ++counter < limit)
;
quux();
is much easier to read than this:
print(some_string);
if(foo&&bar)baz();
while((some_number=some_fn())!==SOME_SENTINEL&&++counter<limit);
quux();
A lot of beginners do this. Including little 14-year-old me from 2009, and I didn't unlearn that bad habit until probably 2013. Stop trying to crush your code down so small.
Avoid "string" + value + "string" + .... Make a format function or use String.prototype.replace(string/regex, new_string)
Again, this is a matter of readability. This:
format("Hello %! You've visited % times today. Your score is %/% (%%).",
name, visits, score, maxScore, score/maxScore * 100, "%"
);
is much easier to read than this horrific monstrosity:
"Hello " + name + "! You've visited " + visits + "% times today. " +
"Your score is " + score + "/" + maxScore + " (" + (score/maxScore * 100) +
"%).",
edit: I'm pleased to point out that I made in error in the above snippet, which in my opinion is a great demonstration of how error-prone this method of string building is.
visits + "% times today"
^ whoops
It's a good demonstration because the entire reason I made that error, and didn't notice it for as long as I did(n't), is because the code is bloody hard to read.
Always surround the arguments of your ternary expressions with parens. It aids readability and prevents bugs.
I borrow this rule from the best practices surrounding C preprocessor macros. But I don't really need to explain this one; see for yourself:
let myValue = someValue < maxValue ? someValue * 2 : 0;
let myValue = (someValue < maxValue) ? (someValue * 2) : (0);
I don't care how well you think you understand your language's syntax, the latter will ALWAYS be easier to read than the former, and readability is the the only argument that is necessary. You read thousands of times more code than you write. Don't be a jerk to your future self long-term just so you can pat yourself on the back for being clever in the short term.
Here:
window.onload = function start() {
slide();
}
function slide() {
var num = 0;
for (num=0;num==10;) {
setTimeout("document.getElementById('container').style.marginLeft='-600px'",3000);
setTimeout("document.getElementById('container').style.marginLeft='-1200px'",6000);
setTimeout("document.getElementById('container').style.marginLeft='-1800px'",9000);
setTimeout("document.getElementById('container').style.marginLeft='0px'",12000);
}
}
That makes it keep looping alright! That's why it isn't runnable here.
try this:
window.onload = function start() {
slide();
}
function slide() {
setInterval("document.getElementById('container').style.marginLeft='-600px'",3000);
setInterval("document.getElementById('container').style.marginLeft='-1200px'",6000);
setInterval("document.getElementById('container').style.marginLeft='-1800px'",9000);
setInterval("document.getElementById('container').style.marginLeft='0px'",12000);
}
setInterval is basically an 'infinite loop' and it wont black up the browser. it waits the required time, then goes again
you can use requestAnimationFrame() function like in the below,
function unlimited () {
requestAnimationFrame(unlimited);
console.log("arian")
}
unlimited();
I have a function e.g.
var test = function () {alert(1);}
How can I get the body of this function?
I assume that the only way is to parse the result of test.toString() method, but is there any other way? If parsing is the only way, what will be the regex to get to body? (help with the regex is extremly needed, because I am not familiar with them)
IF(!!!) you can get the toString(), then you can simply take the substring from the first indexOf("{") to the lastIndexOf("}"). So, something like this "works" (as seen on ideone.com):
var test = function () {alert(1);}
var entire = test.toString(); // this part may fail!
var body = entire.substring(entire.indexOf("{") + 1, entire.lastIndexOf("}"));
print(body); // "alert(1);"
2015 update
Upon revisiting the state of function decompilation, it can said that it's generally safe in certain well-considered use cases and enviroments (e.g: Node.js workers with user defined functions).
It should be put in the same bucket as eval, which is a powerful tool that has its place, but should only be used on rare occasions. Think twice, that's my only advice.
The conclusions from Kangax's new research:
It's still not standard
User-defined functions are generally looking sane
There are oddball engines (especially when it comes to source code
placement, whitespaces, comments, dead code)
There might be future oddball engines (particularly mobile or unusual
devices with conservative memory/power consumption)
Bound functions don't show their original source (but do preserve
identifier... sometimes)
You could run into non-standard extensions (like Mozilla's expression
closures)
ES6 is coming, and functions can now look very different than
they used to
Minifiers/preprocessors are not your friend
"function decompilation" — a process of getting
string representation of a Function object.
Function decompilation is generally
recommended against, as it is a
non-standard part of the language, and
as a result, leads to code being
non-interoperable and potentially
error-prone.
#kangax on comp.lang.javascript
Simplest Use-Case
If you just want to execute the body of the function (e.g. with eval or using the Worker API), you can simply add some code to circumvent all the pitfalls of extracting the body of the function (which, as mentioned by others, is a bad idea in general):
'(' + myFunction + ')()';
I am using this trick in this Worker-related JSFiddle.
Complete Function Serialization With Accurate Stacktrace
I also wrote a more complete library that can:
Serialize any kind of function to string
Be able to send that string representation anywhere else, execute it with any custom arguments, and be able to reproduce the original stacktrace
Check out my CodeBuilder code here.
Note that much of the code takes care of making sure that we get an accurate stacktrace, wherever we execute the serialized function at a later point in time.
This fiddle demonstrates a simplified version of that logic:
Use JSON.stringify to properly serialize the function (that comes in handy when, e.g., we want to make it part of a bigger serialization "data package").
We then wrap it in one eval to un-escape the "JSON-ish"-escaped string (JSON does not allow functions + code, so we must use eval), and then in another eval to get back the object we wanted.
We also use //# sourceMappingURL (or the old version //# sourceMappingURL) to show the right function name in the stacktrace.
You will find that the Stacktrace looks Ok, but it does not give you the correct row and column information relative to the file that we defined the serialized functions in, which is why my Codebuilder makes use of stacktracejs to fix that.
I use the CodeBuilder stuff in my (now slightly dated) RPC library where you can find some examples of how it is used:
serializeInlineFunction example
serializeFunction example
buildFunctionCall example
extending #polygenelubricants' answer:
using: .toString()
Testee:
var y = /* olo{lo} */
/* {alala} */function/* {ff} */ x/*{s}ls{
}ls*/(/*{*{*/)/* {ha-ha-ha} */
/*
it's a function
*/
{
return 'x';
// }
}
/*
*/
By indexOf and lastIndexOf:
function getFunctionBody(fn) {
function removeCommentsFromSource(str) {
return str.replace(/(?:\/\*(?:[\s\S]*?)\*\/)|(?:([\s;])+\/\/(?:.*)$)/gm, '$1');
}
var s = removeCommentsFromSource( fn.toString() );
return s.substring(s.indexOf('{')+1, s.lastIndexOf('}'));
};
getFunctionBody(y);
/*
"
return 'x'
"
*/
used: rm comments from js source
This code provides the body when using ES6 arrow functions like var testFn=(q)=>q+1;
function getFunctionBody(test){
var entire = test.toString(); // note: not safe-guarded; this part may fail like this!
return entire.substring((entire.indexOf("{")+1)||(entire.indexOf("=>")+2), entire.lastIndexOf("}")!==-1?entire.lastIndexOf("}"):entire.length);
}
//testing/showcase code
var tests = [
function () {alert(1);},
()=>{return 1;},
q=>q+1
];
for (var i=0;i<tests.length;i++){
console.log(tests[i],getFunctionBody(tests[i]));
}
I originally submitted this code as an edit to polygenelubricants accepted answer, but it was rejected as the changes were considered to be too drastic.
var fn1 = function() {};
var fn2 = function() { alert("lol!"); };
Function.prototype.empty = function() {
var x = this.toString().match(/\s*function\s*\w*\s*\(.*?\)\s*{\s*}\s*;?\s*/);
return x != null;
};
alert(fn1.empty()); // true
alert(fn2.empty()); // false
'
Solução proposta pelo Paulo Torres no grupo A.P.D.A. no facebook.
you can try this functiion:
function extractFunctionBody(fn) {
var reg = /function \((.*)\)[ ]?{(.*)}$/g;
var match = reg.exec(fn.toString().replace(/\n/g, ";"));
if (match){
return match[2];
} else {
return "";
}
}
Try this:
/\{(\s*?.*?)*?\}/g.exec(test.toString())[0]
test.toString() will hold your entire declaration.
/{(\s*?.?)?}/g will match everything between your braces