1

I presume it is possible to create a JavaScript function that disables it self after it is done running.

Is possible? How can this effect be achieved?

Basilevs
  • 22,440
  • 15
  • 57
  • 102
Mister Verleg
  • 4,053
  • 5
  • 43
  • 68

6 Answers6

4

Wrap arbitrary runnable in following manner:

function once(subject) {
   var first = true;
   return function() {
     if (first) {
        first = false;
        return subject();
     } else {
        return null;
     }
   };
}

var wrapper = once(function() {alert("No more!");});

wrapper(); // alerts
wrapper(); // noop

Runnable will only be executed on first invocation of wrapper.

You can convert a function of arbitrary arguments to an argumentless runnable.

Community
  • 1
  • 1
Basilevs
  • 22,440
  • 15
  • 57
  • 102
2

something like this?

function a(){ alert(1); a = null;}

invoke a() once, second time it will say

Uncaught TypeError: a is not a function

if the function is anonymous, then make it IIFE

(function(){ alert(1);})();
Community
  • 1
  • 1
gurvinder372
  • 66,980
  • 10
  • 72
  • 94
  • 1
    **Never give up**! :) – void Jan 08 '16 at 08:02
  • 2
    Will only work if function is stored in a field of original name. `var b = a; b(); b(); b();` will always alert. – Basilevs Jan 08 '16 at 08:05
  • 1
    @Basilevs agree, I guess if OP wants to execute it only once he/she wouldn't want to store its reference in another variable, but good catch! – gurvinder372 Jan 08 '16 at 08:11
  • @gurvinder372 we can even have named function as IIFEs. They will not be accessible but will add readability to code. – Rajesh Jan 08 '16 at 08:19
  • @Rajesh `we can even have named function as IIFEs` agree. but `add readability to code` debatable, not totally sure about that. – gurvinder372 Jan 08 '16 at 08:25
  • If you have multiple `IIFE`s then someone will have to read entire function just to get gist of function. In such cases, name would help. Yes we can add comments, but still I prefer having named IIFEs, even if its just one. – Rajesh Jan 08 '16 at 08:32
  • @Rajesh agree with readability part. But if one whole file is a function (check jquery source) then it doesn't make sense to name it, right? – gurvinder372 Jan 08 '16 at 08:34
  • @gurvinder372 Thats true. My point with single function was, if you have an initialize function, you can have a named IIFE there. But if it is used to encapsulate then it will not make much sense. – Rajesh Jan 08 '16 at 08:39
  • Why do you write `this.a = null` instead of `a = null`? – Barmar Jan 08 '16 at 09:17
  • @Barmar then it will check variable `a` inside `function a()` and it won't set the function reference to `null`. You can try the same in console. – gurvinder372 Jan 08 '16 at 09:18
  • If you want to assign to a global variable, it should be `window.a = null;` – Barmar Jan 08 '16 at 09:19
  • @Barmar true, but what if it is not a global variable? – gurvinder372 Jan 08 '16 at 09:24
  • Then `this.a` won't work, either, since `this` is `window` unless you're in an object context. – Barmar Jan 08 '16 at 09:31
  • I just tried `function a() { a = null; }`, `a()` in the console, and after this `a` was null. There's no local binding of the function name inside itself. – Barmar Jan 08 '16 at 09:33
  • @Barmar you are right. I don't know why `function a(){ alert(1); a = null;}` was alerting earlier multiple times. I have edited my answer. Thanks. – gurvinder372 Jan 08 '16 at 12:50
2

If you want the functionality to be happen only once you can use the following function

function once(fn, context) { 
    var result;

    return function() { 
        if(fn) {
            result = fn.apply(context || this, arguments);
            fn = null;
        }

        return result;
    };
}

// Usage
var canOnlyFireOnce = once(function() {
    console.log('Fired!');
});

canOnlyFireOnce(); // "Fired!"
canOnlyFireOnce(); // nada

Courtesy: https://davidwalsh.name/essential-javascript-functions

Narendra CM
  • 1,416
  • 3
  • 13
  • 23
1
var _flag = true; // Have a flag variable.

function oneTimer(){

     // Check flag is set to true or not
     if(!_flag) return;
     _flag = false;

     // Your function definition here.


}
void
  • 36,090
  • 8
  • 62
  • 107
  • You are using a variable declared in the outer scope of the function, The accepted `once` functional decorator is a much better solution as everything is enclosed within it so there can be no issues with the 'pure' function. Also this would not be reusable, `once` can be used on any function, but if you wanted to do the same thing to another function you would have to do something like `_flag_2` which could get messy quickly. – synthet1c Jan 08 '16 at 11:02
1

As commented, if you want to execute a function only once, you should try IIFE. These functions are invoked immediately and cannot be called afterwards.

Following is a sample code.

(function test() {
  console.log("test");

  (function innerFunc() {
    console.log("Inner Function");
  })();

  try {
    innerFunc();
  } catch (ex) {
    console.log(ex)
  }
})();

try {
  test();
} catch (ex) {
  console.log(ex)
}
Rajesh
  • 24,354
  • 5
  • 48
  • 79
1

Pretty easy, just assign an empty function to the function:

function once() {
    alert('once');
    once = function () { };
}

once();
once();
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392