How important is IIFE in RMMV?

TheoAllen

Self-proclaimed jack of all trades
Veteran
Joined
Mar 16, 2012
Messages
5,573
Reaction score
6,499
First Language
Indonesian
Primarily Uses
RMVXA
About IIFE: https://developer.mozilla.org/en-US/docs/Glossary/IIFE

This morning, I had an interesting discussion from one of the discord chat (with @Aloe Guvner to give them some credit). Some brought up that it is not something to promote in MV plugin making. While I sort of understand, I didn't really voice my opinion on because I barely made anything in MV to understand that. However, that doesn't mean it isn't bothering my mind.

Generally, what I've seen is it is to avoid naming conflict. It encapsulated in a private block of function so your variable isn't accessible outside of it. But the question are
> How common is the name conflict?
> Can you just use your own name pattern like <yourname>_<scriptname>_<alias method name>? I don't believe if it will be too common to get conflict. Additionally, you can just use your own namespace (like how Yanfly did it)?
> Do you consider a plugin that doesn't do an IIFE is a kind of... heretic?
> So why even IIFE? Any other benefit that I don't know? Or other drawbacks (aside from the conflicting name)?
> Do you promote to some of the (potential) new plugin dev to use IIFE?
 

CaRa_CrAzY

Undefined Custom Title
Veteran
Joined
Jan 19, 2019
Messages
65
Reaction score
27
First Language
Portuguese
Primarily Uses
Other
> How common is the name conflict?
I am not an MV developer, but I have already made some little works using javascript and I ALWAYS use IIFE's.
That's because got kind of traumatized when working in teams both at college and in Educational Game Development. Naming conflicts were very common, but those were completely different environments.
> Can you just use your own name pattern like <yourname>_<scriptname>_<alias method name>? I don't believe if it will be too common to get conflict. Additionally, you can just use your own namespace (like how Yanfly did it)?
Defining your own naming conventions isn't a problem itself in my opinion, since the odds of names clashing, specially when using elaborate conventions, are extremely low, but at the bottom of my heart I feel like it is just a workaround. I would feel much more comfortable coding stuff that does not rely in any convention at all.
> Do you consider a plugin that doesn't do an IIFE is a kind of... heretic?
There isn't any other form to fully isolate your javascript code that I know other than using an IIFE. I have some prejudice upon plugins that do not encapsulate themselves using IIFEs, but again, it's just prejudice. And I must add that I just got here at RMW like... two months ago, so I don't have many parameters to say anything at all about MV.
> So why even IIFE? Any other benefit that I don't know? Or other drawbacks (aside from the conflicting name)?
I don't know. I always was "indoctrinated" to use IIFE's =/
> Do you promote to some of the (potential) new plugin dev to use IIFE?
Yes, but since you said someone is against promoting it, I would like to hear more.
 

Poryg

Dark Lord of the Castle of Javascreeps
Veteran
Joined
Mar 23, 2017
Messages
4,124
Reaction score
10,634
First Language
Czech
Primarily Uses
RMMV
How common is the name conflict?
If you create a reasonable namespace, it is not.
Do you consider a plugin that doesn't do an IIFE is a kind of... heretic?
Actually, I do. The biggest issue with IIFE is that it doesn't allow interplugin interaction, so to speak. In other words:
1. No ability to enhance your IIFE encapsulated custom scenes with additional plugins. You need to make edits directly in that plugin file.
2. No ability to test/read your IIFE encapsulated custom scenes in dev tools
3. A potential for crashes and bugs due to the funky variable handling IIFE brings

So why even IIFE? Any other benefit that I don't know? Or other drawbacks (aside from the conflicting name)?
It makes the code impossible to be called in dev tools, which is great for nwjs, because even if the user manages to open dev tools, they won't be able to analyze the code in dev console (as long as you compile your scripts).
 

TheoAllen

Self-proclaimed jack of all trades
Veteran
Joined
Mar 16, 2012
Messages
5,573
Reaction score
6,499
First Language
Indonesian
Primarily Uses
RMVXA
Yes, but since you said someone is against promoting it, I would like to hear more.
Actually, I'm leaning towards the against promoting it. But I'm not there yet, because I want to be educated. I mean, in Ace the chance of name conflict is almost abysmal (it did happen though, but not for making aliases). People usually use a long unique name so why not happen in MV?

Actually, I do. The biggest issue with IIFE is that it doesn't allow interplugin interaction, so to speak. In other words:
1. No ability to enhance your IIFE encapsulated custom scenes with additional plugins. You need to make edits directly in that plugin file.
2. No ability to test/read your IIFE encapsulated custom scenes in dev tools
3. A potential for crashes and bugs due to the funky variable handling IIFE brings
And how is that a good thing? If all your modification and variables are encapsulated in the IIFE block, means you (and some people) are unable to indirectly edit the plugin by making a plugin patch to change its behavior like, maybe making an addon?

It makes the code impossible to be called in dev tools, which is great for nwjs, because even if the user manages to open dev tools, they won't be able to analyze the code in dev console (as long as you compile your scripts).
Who is "the user" here? Is it related to security or something else?
 

caethyril

^_^
Veteran
Joined
Feb 21, 2018
Messages
1,955
Reaction score
1,402
First Language
EN
Primarily Uses
RMMZ
Unless you're using strict mode I think it's mostly a matter of style. Quoting a recent post of mine from another thread:
IIFEs can make using a single namespace easier to maintain, and can also be used, even in strict mode, for selective overrides. Example:
Code:
// import declarations for ease of compatibility checks
var Imported = Imported || {};
Imported.plugin = true;

// namespaces for organisation
var author = author || {};
author.plugin = author.plugin || {};

// define stuff on namespace via IIFE parameter
(function($) {
'use strict';  // IIFE confines strict-mode declaration
  $.foo = 123;  // shorter to type out
  $.bar = 'text';
})(author.plugin);  // easy to alter later if needed

console.log(author.plugin.foo);  // proof of scope/persistence

// sub-routines with early returns, e.g. compatibility patches
(function() { if (!Imported.YEP_CoreEngine) return;
  // do this only if using Yanfly's Core Engine
})();

console.log(author.plugin.bar);  // regardless of whether using YEP_CoreEngine
 

TheoAllen

Self-proclaimed jack of all trades
Veteran
Joined
Mar 16, 2012
Messages
5,573
Reaction score
6,499
First Language
Indonesian
Primarily Uses
RMVXA
@caethyril that was the merit mentioned in my morning chat, which currently the only reason I could say yes to IIFE.
 

Poryg

Dark Lord of the Castle of Javascreeps
Veteran
Joined
Mar 23, 2017
Messages
4,124
Reaction score
10,634
First Language
Czech
Primarily Uses
RMMV
And how is that a good thing? If all your modification and variables are encapsulated in the IIFE block, means you (and some people) are unable to indirectly edit the plugin by making a plugin patch to change its behavior like, maybe making an addon?
Actually, I did not say it was a good thing, quite the opposite.

Who is "the user" here? Is it related to security or something else?
Should have said "player". Would be clearer. But yes, encapsulation makes your code a bit more secure.
 

Aloe Guvner

Walrus
Veteran
Joined
Sep 28, 2017
Messages
1,628
Reaction score
1,110
First Language
English
Primarily Uses
RMMV
Actually, I do. The biggest issue with IIFE is that it doesn't allow interplugin interaction, so to speak.
I've personally experienced this trying to add functionality to a Scene_Something that another plugin writer defined in an IIFE. However, you should be careful in your wording, specifically that is for an anonymous IIFE / where a function argument is not passed (see caethryl's example)

There isn't any other form to fully isolate your javascript code that I know other than using an IIFE.
I don't know. I always was "indoctrinated" to use IIFE's =/
If you're talking Web dev / JS dev in general, then the standard now is to use modular code and imports/exports with a build process. I don't think the MV plugin ecosystem will switch to that anytime soon or ever though. The only attempt of that I'm aware of is LTN Game's Fenix Engine which I've been meaning to try.
 

Poryg

Dark Lord of the Castle of Javascreeps
Veteran
Joined
Mar 23, 2017
Messages
4,124
Reaction score
10,634
First Language
Czech
Primarily Uses
RMMV
MV plugin system won't do it anytime soon to ensure as much compatibility with older versions as possible. For the same reason we aren't going to see an upgrade of MV's core engine despite the fact that majority uses 1.6 subversions.
 

Tsukihime

Veteran
Veteran
Joined
Jun 30, 2012
Messages
8,564
Reaction score
3,839
First Language
English
I use IIFE so I can be lazy.

Code:
var TH_WindowActor_update = Window_Actor.prototype.update
var TH_WindowStatus_update = Window_Status.prototype.update
I don't need to pad that alias with extra namespaces like in Ace.

Code:
var TH_MYPLUGIN_WindowActor_update = Window_Actor.prototype.update
var TH_MYPLUGIN_WindowStatus_update = Window_Status.prototype.update
Too much work. Too annoying.
 

Solar_Flare

Veteran
Veteran
Joined
Jun 6, 2020
Messages
531
Reaction score
232
First Language
English
Primarily Uses
RMMV
I think it's a good idea to use an IIFE, but you can also go too far with that. The Kadokawa plugins (especially ItemBook and EnemyBook) go too far, making them non-extensible. So I'd recommend defining key things outside an IIFE and then putting the bulk of your code inside one. There are a few ways you could do this...

JavaScript:
// First way

function Scene_MyCustomScene() {}

(function() {
    // real code goes here
})();

// Second way

(function() {
    function Scene_MyCustomScene() {}
    
    // code here
    
    // Explicit exports
    window.Scene_MyCustomScene = Scene_MyCustomScene
    // could place them in window or in a custom namespace
    // don't need to use the same name for the export
})();
Using a personal namespace is pretty nice for extensibility, certainly. Of course, there could then be conflicts with the namespace itself... but at least that's less likely.
 

OcRam

Servant of the Universe
Veteran
Joined
Aug 2, 2016
Messages
601
Reaction score
715
First Language
Finnish
Primarily Uses
RMMZ
Like @Tsukihime said I am also a lazy coder.

And I like to bind this object to my current plugin.

Those are only reasons I use IIFE.
 

DoubleX

Just a nameless weakling
Veteran
Joined
Jan 2, 2014
Messages
1,750
Reaction score
913
First Language
Chinese
Primarily Uses
N/A
I generally use IIFE this way for existing classes:
Code:
(function(PLUGIN_CONTAINER) {

    "use strict";

    PLUGIN_CONTAINER.Klass = { orig: {}, new: {} };

    var $ = Klass.prototype, $$ = SuperKlass.prototype;
    var K = PLUGIN_CONTAINER.Klass.orig, _k = PLUGIN_CONTAINER.Klass.new;

    _k.PUBLIC_STATIC_FUNC = function(args) {};

    _k.PUBLIC_STATIC_CONST = CONST;

    _k.publicStaticVar = val;

    _k._PRIVATE_STATIC_FUNC = function(args) {};

    _k._PRIVATE_STATIC_CONST = CONST;

    _k._privateStaticVar = val;

    K.method = $.method;
    _k.method = $.method = function(args) {
        K.method.apply(this, arguments);
        _k._newPrivateMethod.call(this, args);
    };

    $.pluginNameNewPublicMethod = function(args) {};

    _k._newPrivateMethod = function(args) {};

})(DoubleX_RMMV.Plugin_Name);
And this way for new classes:
Code:
function NewClass() {
    "use strict";
    this.initialize.apply(this, arguments);
}

(function(PLUGIN_CONTAINER) {

    "use strict";

    var $$ = SuperClass.prototype;

    NewClass.prototype = Object.create($$);

    var $ = NewClass.prototype;

    $.constructor = NewClass;

    var _NC = PLUGIN_CONTAINER.NewClass = {};

    _NC.PUBLIC_STATIC_FUNC = function(args) {};

    _NC.PUBLIC_STATIC_CONST = CONST;

    _NC.publicStaticVar = val;

    _NC._PRIVATE_STATIC_FUNC = function(args) {};

    _NC._PRIVATE_STATIC_CONST = CONST;

    _NC._privateStaticVar = val;

    $.publicMethod = function(args) {};

    $._privateMethod = function(args) {};

})(DoubleX_RMMV.Plugin_Name);
To me. IIFE's just a style that keeps working for me :)
 

Tsukihime

Veteran
Veteran
Joined
Jun 30, 2012
Messages
8,564
Reaction score
3,839
First Language
English
I think it's a good idea to use an IIFE, but you can also go too far with that. The Kadokawa plugins (especially ItemBook and EnemyBook) go too far, making them non-extensible. So I'd recommend defining key things outside an IIFE and then putting the bulk of your code inside one. There are a few ways you could do this...

JavaScript:
// First way

function Scene_MyCustomScene() {}

(function() {
    // real code goes here
})();

// Second way

(function() {
    function Scene_MyCustomScene() {}
   
    // code here
   
    // Explicit exports
    window.Scene_MyCustomScene = Scene_MyCustomScene
    // could place them in window or in a custom namespace
    // don't need to use the same name for the export
})();
Using a personal namespace is pretty nice for extensibility, certainly. Of course, there could then be conflicts with the namespace itself... but at least that's less likely.
I also simply expose new classes in global space like in the first method.

But actually now that I know that window is the global space, I'm going to use the second method, just so I can keep all of my consts also encapsulated in that IIFE.
 

Aesica

undefined
Veteran
Joined
May 12, 2018
Messages
1,485
Reaction score
1,372
First Language
English
Primarily Uses
RMMV
I like IIFE. IIFE is LIFE I guess. :) Anyway, I find it better than just dumping everything out into the open, plus it lets me do the following things:

Code:
(function($$)
{
   // this shortcut...
   $$.doSomething = function(){};
   // is the same as typing out all this crap...
   Aesica.SomeUselessPlugin.doSomething = function(){};
   // ...and both of them are attached to my plugin's namespace
   // rather than being thrown out into the global stew with
   // everybody else's plugin code

   // these are private, so somebody else's crap can't interfere with them
   function butts(){};
   var hi = 12345;
})(Aesica.SomeUselessPlugin);
Edit:

1. I guess I'll go down the question list, but...
2. I just noticed this thread is...slightly necro'd. Oh well!

> How common is the name conflict?
Well without putting your stuff into an IIFE, any variables not in their respective functions, and any functions not specifically attached to a namespace are out in the global stew. If you have a "function butts()" and I make a "function butts()" as well, one of us is getting our function (unintentionally) overwritten.

> Can you just use your own name pattern like <yourname>_<scriptname>_<alias method name>? I don't believe if it will be too common to get conflict. Additionally, you can just use your own namespace (like how Yanfly did it)?
Yeah, I could name every function "Aesica_SomeCrapPlugin_someFunction" but seriously who wants to type all that crap out every time they want to invoke said function? Hard pass! Plus it still clutters the global namespace--don't do that.

> Do you consider a plugin that doesn't do an IIFE is a kind of... heretic?
in a word: Yes.

> So why even IIFE? Any other benefit that I don't know? Or other drawbacks (aside from the conflicting name)?
I covered above in my post, as well has many others. It's tidy and the only way anything can be globally accessible is if you specifically attach it to whatever namespace object you pass into it.

> Do you promote to some of the (potential) new plugin dev to use IIFE?
Also in a word: Yes.

(I need to get better at using the preview button)
 
Last edited:

Ossra

Formerly Exhydra
Veteran
Joined
Aug 21, 2013
Messages
1,076
Reaction score
848
First Language
English
Primarily Uses
RMMV
I probably went a bit over-board on mine, but here is the newest revision of what I have been using in my plugins :

Code:
// +===================================================|                      Namespace |
// | [Global] Namespace
// +====================================================================================+

var Imported   = Imported       || {};
Imported.Ossra = Imported.Ossra || {};

var Ossra      = Ossra          || {};
Ossra.Share    = Ossra.Share    || {};
Ossra.Plugin   = Ossra.Plugin   || {};



(function(pluginName, pluginVersion) {                                               // {



  'use strict';



  // +=================================================|                  Configuration |
  // | [Plugin] Configuration
  // +==================================================================================+

  // [Framework] Function(s)
  const setNamespace = Ossra.Share.setNamespace; // From Framework Plugin
  const createConfig = Ossra.Share.createConfig; // From Framework Plugin

  // [Namespace] Imported
  setNamespace(Imported.Ossra, pluginName, pluginVersion);
  // Imported.Ossra.PluginCategory.PluginName = pluginVersion

  // [Namespace] Plugin
  const ossPlugin    = setNamespace(Ossra.Plugin, pluginName);
  // Ossra.Plugin.PluginCategory.PluginName

  const ossCode      = setNamespace(ossPlugin, 'Code');
  const ossData      = setNamespace(ossPlugin, 'Data');
  // Ossra.Plugin.PluginCategory.PluginName.Code - Alias, Function, Command
  // Ossra.Plugin.PluginCategory.PluginName.Data - Default, Config, Variable, RegExp

  const ossDefault   = setNamespace(ossData, 'Default');
  const ossConfig    = setNamespace(ossData, 'Config');



  (function() {                                                                      // {

  // +=================================================|                  Configuration |
  // | [Setup] Configuration
  // +==================================================================================+

  // +----------------------------------------------------------------------------------+
  // | [Setup] Create Defaults
  // +----------------------------------------------------------------------------------+

    ossDefault.plugin = {

      // Default Plugin Configuration

    };

  // +----------------------------------------------------------------------------------+
  // | [Setup] Create Configuration
  // +----------------------------------------------------------------------------------+

    createConfig('UniquePluginID', ossDefault.plugin); // Deep Parse + Defaults Merge

  })();                                                                              // }



  (function(_) {                                                                     // {

  // +=================================================|                  RPGM_NewKlass |
  // | [Window] RPGM_NewKlass
  // +==================================================================================+

    _.RPGM_NewKlass = function () {
      this.initialize.apply(this, arguments);
    }

    _ = _.RPGM_NewKlass;

    _.prototype = Object.create(RPGM_Klass.prototype);
    _.prototype.constructor = _;

  // NEW -------------------------------------------------------------------------------+
  // | [Method] initialize
  // +----------------------------------------------------------------------------------+

    _.prototype.initialize = function() {

      // Function Code

    }; // RPGM_NewKlass ‹‹ initialize
    
  })(window);                                                                        // }



  (function(_) {                                                                     // {

  // +=================================================|                     RPGM_Klass |
  // | [Scene] RPGM_Klass
  // +==================================================================================+

    const _alias = setNamespace(ossCode, 'Alias.RPGM_Klass');
    const _funct = setNamespace(ossCode, 'Function.RPGM_Klass');
    // Ossra.Plugin.PluginCategory.PluginName.Code.Alias
    // Ossra.Plugin.PluginCategory.PluginName.Code.Function

  // ALIAS -----------------------------------------------------------------------------+
  // | [Method] aliasedFunct
  // +----------------------------------------------------------------------------------+

    _alias.aliasedFunct = _.prototype.aliasedFunct;

    _.prototype.aliasedFunct = function() {

      _alias.aliasedFunct.call(this);

    }; // RPGM_Klass ‹‹ aliasedFunct

  // NEW -------------------------------------------------------------------------------+
  // | [Method] newFunct (Prototype)
  // +----------------------------------------------------------------------------------+

    _.prototype.newFunct = function() {

      // Function Code

    }; // RPGM_Klass ‹‹ newFunct

  // NEW -------------------------------------------------------------------------------+
  // | [Method] newFunct (No Prototype) - Used to keep RPGM_Klass clean
  // +----------------------------------------------------------------------------------+

    _funct.newFunct = function() {

      // Function Code

    }; // RPGM_Klass ‹‹ newFunct

  })(RPGM_Klass);                                                                    // }



})('PluginCategory.PluginName', 1.00);                                               // }
 

TheoAllen

Self-proclaimed jack of all trades
Veteran
Joined
Mar 16, 2012
Messages
5,573
Reaction score
6,499
First Language
Indonesian
Primarily Uses
RMVXA
Well without putting your stuff into an IIFE, any variables not in their respective functions, and any functions not specifically attached to a namespace are out in the global stew. If you have a "function butts()" and I make a "function butts()" as well, one of us is getting our function (unintentionally) overwritten.
This does not explain how common is that to happen. While you could argue "IIFE is to eliminate all the possible risk", but still that wasn't the question. In my experience, RGSS3 barely even has name conflict because aliasing was done in a unique way most of the time. And the only thing when name clashing that actually happened was if you add a really common name for a method function that never existed in the first place.

This happened when my battle system had a compatibility issue with Luna Engine because we both added a method named "update_move" in a sprite class and we don't agree on how does that work and that was not even a global namespace. Just a new method attached to an existing class. Imagine if either of us willing to not use a commonly used name, like, if I would just "tsbs_update_move", that would save the time to debug the entire script. But no, the method name is too good to be missed and it is self-explanatory.

Yeah, I could name every function "Aesica_SomeCrapPlugin_someFunction" but seriously who wants to type all that crap out every time they want to invoke said function? Hard pass! Plus it still clutters the global namespace--don't do that.
I get what you're saying (I actually hate that I had to type "prototype" all times), but what is technically bad for cluttering the global namespace? Does it slow down the performance? Does it take a lot of memories? mind that it is in the context of RPG Maker, not web dev or stuff.
 

Aesica

undefined
Veteran
Joined
May 12, 2018
Messages
1,485
Reaction score
1,372
First Language
English
Primarily Uses
RMMV
This does not explain how common is that to happen. While you could argue "IIFE is to eliminate all the possible risk", but still that wasn't the question. In my experience, RGSS3 barely even has name conflict because aliasing was done in a unique way most of the time. And the only thing when name clashing that actually happened was if you add a really common name for a method function that never existed in the first place.
A nonzero chance is still a nonzero chance, no matter how slim. The real question is, "why not IIFE your code?"

I get what you're saying (I actually hate that I had to type "prototype" all times), but what is technically bad for cluttering the global namespace? Does it slow down the performance? Does it take a lot of memories? mind that it is in the context of RPG Maker, not web dev or stuff.
Mostly it's just seen as bad practice to clutter the global namespace because more can go wrong when you do, and because all of your functions and variables are out in the open. When you encapsulate your code, it becomes easier to debug and maintain. Everything inside the IIFE becomes private and specific to that IIFE unless you specifically indicate that it should behave otherwise--referencing a value that exists globally outside the IIFE, for example.

I mean, nothing's really stopping you from coding however you want as long as the plugin works, but if you want to risk as little going wrong as possible, it's best to wrap your code in an IIFE.[/QUOTE]

Edit: I suck at clicking preview~
 

TheoAllen

Self-proclaimed jack of all trades
Veteran
Joined
Mar 16, 2012
Messages
5,573
Reaction score
6,499
First Language
Indonesian
Primarily Uses
RMVXA
A nonzero chance is still a nonzero chance, no matter how slim. The real question is, "why not IIFE your code?"
If you still expose your function to the global namespace, then all is good (which what I've found a year ago when making this thread and honestly, that's good). But when you don't, it just encapsulates your code and you can not patch it. You know, when you do IIFE, you should no what you're doing which is good. But many who just started just use IIFE because many people do it and they had no idea what is the real purpose of it. They were afraid if their code suddenly doesn't work because they had been told to do it.

"Do it or your code suck" kind of thing.

No, you don't have to use IIFE to make your code works. The purpose of this topic I made in a year ago was questioning those people who do IIFE while don't do the practice that had been mentioned in this thread (exposing to global namespace afterward). And turned out, the conclusion mostly was.
  • Avoiding name conflict.
  • Polluting global namespace.
Which is not exactly essential to make the plugin works or any code at all. There was someone who made a tutorial and he used IIFE. And when I asked why, he had no idea. He just followed people. And his tutorial clearly didn't need you to use IIFE at all. And I call that misleading. This particular thread hopefully explains how and why you should use IIFE.
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts

Another day of mostly mapping in Make a Game in RPG Maker MZ: Episode 7 starting now! We're making a mansion! Come watch live and join in on the chat!
Game=Forest, Feature=Tree. There's little worth in looking at a tree except in its relation to how it affects the feel of the forest.
Been a while, guys. Despite being in college now, I'm working on Season's Promise as often as I can.
Helping my sister make her game
I hope i can get some freckles for the generator soon
Guys, if you are seeing this post, send me your RPG Games, I wanna test some to know about everyone! ^^

Forum statistics

Threads
104,575
Messages
1,007,279
Members
136,057
Latest member
simonbelmont88
Top