inherit
96289
0
May 17, 2020 9:37:00 GMT -8
elli
1,822
January 2007
ebbymac
|
Post by elli on Jun 18, 2019 10:49:34 GMT -8
I've been working on a plugin that I plan to release. (I've built other, more simple plugins in the past, but kept them for personal use.) I followed Peter's ebook, referenced a few other plugins, and it's working as intended. Cool. But now I'm wondering: what is the "best" way to write JavaScript for ProBoards plugins? Are there benefits to one style over another? Peter, Brian, Jordan, and others use (what I understand to be called) object methods, which seems fine and good, but the context of this is really confusing and doesn't work as I'd expect it to. Also, I can't figure out how to work with global variables (such as a button across multiple functions) without having to declare them under each function. var plugin = (function() {
return {
images: {}, settings: {},
init: function() {
this.setup();
},
setup: function() {
// Down here I set up `bool` to use // I won't be able to use this again in another function // It seems that it has to be redeclared each time?
var bool = false;
}
}
})();
$(function() { plugin.init(); }); Then there's the way that I'm used to writing functions, whatever this would be called: $(function() {
(function() {
var $button = $('#button-id'), $body = $('body');
function addButton() {
$body.append($button);
}
addButton();
})();
}); I find it more straightforward to work with global variables this way. I can use them anywhere within the scope of that immediately invoked function expression. With object methods, to use global variables and make this easier to work with, I ended up doing: var plugin = (function() {
var $button, $body;
var self = {
init: function() {
self.images = {}; self.settings = {};
self.setup();
},
setup: function() {
// Now I can set $button and $body // And use them in other functions
$button = $('#button-id'); $body = $('body');
}
}
return self;
})();
$(function() { plugin.init(); }); idk if that's "correct". It works, but seems so extra when I could just use the pattern from my second example. What am I missing? Is it an individual preference, or is there a benefit to object methods?
|
|
#eb7100
33409
0
1
Nov 24, 2024 4:27:37 GMT -8
Brian
48,130
November 2004
smashmaster3
|
Post by Brian on Jun 18, 2019 18:15:48 GMT -8
Variables declared within functions exist only within the scope of that function and cannot be referenced outside of it which is why you can't access the bool variable in the first example once you've exited the function. this will typically return the object that the function that called it is a property of.
However, if you create a function using bind() or run one using apply() or call() you can change what this represents. If I were to write a plugin today it would look pretty different from what I have on the library based on what I've learned over the past several months. To prove so, I have, uh... written a plugin... today. Example Counter.pbp (1.91 KB) I assign everything I need to repeatedly access from outside of the plugin to an object stored in a single global variable. This way there's only one variable that can possibly be overwritten to break the plugin unless you're explicitly trying to break it. If anything within the plugin has a one-time use it doesn't get assigned to the global variable. Ideally I should also move the anonymous functions inside of _bindCounterButtonEvents() into their own public functions so that elements other than the counter can call them without having to do their own calculations to update the HTML themselves but it's just a self-contained example, so meh! Some helpful things I've been instructed to do that end up tying into this are: - Name variables and functions as specifically as possible so that I can tell what they represent or what action they perform based on just the name. Rename them until I'm satisfied with the name, no matter how many times it takes.
- Keep functions as small as possible by ensuring they only perform the action advertised in their name. If a function is super long it's probably doing more than one thing and a good chunk of it can probably be moved into a new function.
- Keep things in the order they're introduced. If a function doesn't get called until way later in the code there's not much justification for it being way near the top of the file next to a bunch of other functions that don't use it.
The code ends up a lot more readable because the names tell me exactly what everything is and does. And it's much easier to maintain when most of the functions only do what they advertise, so I can just go and find the exact thing I need to edit without needing an abundance of comments to lead the way or having to scroll through a 100+ line function. Edit: Here's a cleaned up version of the source code with no comments that adheres as closely to these guidelines as possible.
|
|
inherit
Official Code Helper
65613
0
1
Oct 22, 2024 1:56:19 GMT -8
Chris
"'Oops' is the sound we make when we improve"
9,018
December 2005
horace
RedBassett's Mini-Profile
|
Post by Chris on Jun 18, 2019 18:39:29 GMT -8
Proboards has also posted best practices guidelines for Javascript as well as HTML and CSS that I personally have yet to incorporate into my own coding
|
|
inherit
2671
0
May 14, 2013 14:40:03 GMT -8
Peter
🐺
10,615
February 2002
peter3
|
Post by Peter on Jun 19, 2019 14:51:45 GMT -8
But now I'm wondering: what is the "best" way to write JavaScript for ProBoards plugins? Are there benefits to one style over another? There really is no "best" way. As long as your code is readable and performant, then it really comes down to personal preference at the end of the day. You can look over best practices / style guides and adopt a few of the styles, but they are just recommendations, it's not something you have to do yourself. Take a look at the link posted by Chris and there may be a few you like and want to adopt. You may already be doing a lot of them. In regards to how I write plugins. It has changed quite a bit over the years, and the last couple of years I relaxed my practices a little (this will change again when v6 is available to us). I did use IIFE's (Immediately Invoked Function Expression) for a long time, as it was a way to prevent global pollution and conflicts with other plugins. The problem with IIFE's is debugging. Unless you create a global namespace (i.e a property of window), then things become hard to debug when looking at peoples forums, as browser debugger tools wasn't the easiest to get along with back then. Here's an example of how I use to write my code when using an IIFE. (function(){
// Maybe you want something out side the object; let welcome_msg = "Hello World!"; return { init(){ console.log(welcome_msg); console.log("Hello from init"); this.setup(); $(this.ready.bind(this)); }, setup(){ console.log("Hello from setup"); }, ready(){ console.log("Hello from ready, your dom is available"); this.fetch_elements(); this.create_elements(); this.add_button(); }, create_elements(){ this.$button = $("<button>Hello World</button>"); }, fetch_elements(){ this.$body = $("body"); }, add_button(){ this.$body.append(this.$button); } }; })().init(); I like splitting my code up into methods, makes things much easier to read and find later on. It's pretty flexible, because as you know, you have your own private scope, so adding variables to the top is absolutely fine. There are so many ways you can do it. Just find one you are happy with Edit: Wrote this pretty late last night and forgot to comment on the example code by Brian . If you aren't keen on an object approach, I definitely recommend the way Brian has done his. What stands out the most is setting a global namespace based on the plugin ID, so there should really be no conflicts (create a good plugin id), and it's a doorway into the plugin when it comes to debugging.
|
|
inherit
96289
0
May 17, 2020 9:37:00 GMT -8
elli
1,822
January 2007
ebbymac
|
Post by elli on Jun 26, 2019 8:55:39 GMT -8
Thank you for the helpful replies, guys. I had to think about this for a little while, for some reason it didn't occur to me that I can just put my global variables outside of the return. var plugin = (function() {
var $button = $('#button'), $body = $('body');
return {
images: {}, settings: {},
init: function() {
this.setup();
},
setup: function() {
$button.append($body);
}
}
})();
$(function() { plugin.init(); });
Jeez. That's, uh, one lesson learned. Methods are nice and tidy, but the context of this is still confusing, so I'll need to keep working on that one. In the meantime, I think I'll maintain the style from Bryan's example plugin, which is more familiar to me. Thank you for that example. At my job, we also use a modified version of AirBnB's style guide, so I've been using most of those rules for about two years now. I picked up BEM for CSS around the same time (combined with Idiomatic CSS and alphabetical property ordering). I'm happy that ProBoards has adopted these, as well. 🙂 QQ: will v6 have Babel built in for the code editor?
|
|
inherit
217348
0
Jul 27, 2022 7:26:44 GMT -8
Lynx
5,849
January 2015
msg
|
Post by Lynx on Jun 27, 2019 8:58:56 GMT -8
Just to note, elli - if any of my plugins are open build, I'd advise against using any of them as a reference. The code is sloppy - and are most likely closely resembling spaghetti code, which is a type of coding that is typically frowned upon.
|
|
inherit
96289
0
May 17, 2020 9:37:00 GMT -8
elli
1,822
January 2007
ebbymac
|
Post by elli on Jun 27, 2019 9:32:18 GMT -8
Lynx Hey, at least you released them!
|
|