Is there a difference between arrow functions and regular functions for middleware functions in Express app? [duplicate] - node.js

Arrow functions in ES2015 provide a more concise syntax.
Can I replace all my function declarations / expressions with arrow functions now?
What do I have to look out for?
Examples:
Constructor function
function User(name) {
this.name = name;
}
// vs
const User = name => {
this.name = name;
};
Prototype methods
User.prototype.getName = function() {
return this.name;
};
// vs
User.prototype.getName = () => this.name;
Object (literal) methods
const obj = {
getName: function() {
// ...
}
};
// vs
const obj = {
getName: () => {
// ...
}
};
Callbacks
setTimeout(function() {
// ...
}, 500);
// vs
setTimeout(() => {
// ...
}, 500);
Variadic functions
function sum() {
let args = [].slice.call(arguments);
// ...
}
// vs
const sum = (...args) => {
// ...
};

tl;dr: No! Arrow functions and function declarations / expressions are not equivalent and cannot be replaced blindly.
If the function you want to replace does not use this, arguments and is not called with new, then yes.
As so often: it depends. Arrow functions have different behavior than function declarations / expressions, so let's have a look at the differences first:
1. Lexical this and arguments
Arrow functions don't have their own this or arguments binding. Instead, those identifiers are resolved in the lexical scope like any other variable. That means that inside an arrow function, this and arguments refer to the values of this and arguments in the environment the arrow function is defined in (i.e. "outside" the arrow function):
// Example using a function expression
function createObject() {
console.log('Inside `createObject`:', this.foo);
return {
foo: 42,
bar: function() {
console.log('Inside `bar`:', this.foo);
},
};
}
createObject.call({foo: 21}).bar(); // override `this` inside createObject
// Example using a arrow function
function createObject() {
console.log('Inside `createObject`:', this.foo);
return {
foo: 42,
bar: () => console.log('Inside `bar`:', this.foo),
};
}
createObject.call({foo: 21}).bar(); // override `this` inside createObject
In the function expression case, this refers to the object that was created inside the createObject. In the arrow function case, this refers to this of createObject itself.
This makes arrow functions useful if you need to access the this of the current environment:
// currently common pattern
var that = this;
getData(function(data) {
that.data = data;
});
// better alternative with arrow functions
getData(data => {
this.data = data;
});
Note that this also means that is not possible to set an arrow function's this with .bind or .call.
If you are not very familiar with this, consider reading
MDN - this
YDKJS - this & Object prototypes
2. Arrow functions cannot be called with new
ES2015 distinguishes between functions that are callable and functions that are constructable. If a function is constructable, it can be called with new, i.e. new User(). If a function is callable, it can be called without new (i.e. normal function call).
Functions created through function declarations / expressions are both constructable and callable.
Arrow functions (and methods) are only callable.
class constructors are only constructable.
If you are trying to call a non-callable function or to construct a non-constructable function, you will get a runtime error.
Knowing this, we can state the following.
Replaceable:
Functions that don't use this or arguments.
Functions that are used with .bind(this)
Not replaceable:
Constructor functions
Function / methods added to a prototype (because they usually use this)
Variadic functions (if they use arguments (see below))
Generator functions, which require the function* notation
Lets have a closer look at this using your examples:
Constructor function
This won't work because arrow functions cannot be called with new. Keep using a function declaration / expression or use class.
Prototype methods
Most likely not, because prototype methods usually use this to access the instance. If they don't use this, then you can replace it. However, if you primarily care for concise syntax, use class with its concise method syntax:
class User {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
Object methods
Similarly for methods in an object literal. If the method wants to reference the object itself via this, keep using function expressions, or use the new method syntax:
const obj = {
getName() {
// ...
},
};
Callbacks
It depends. You should definitely replace it if you are aliasing the outer this or are using .bind(this):
// old
setTimeout(function() {
// ...
}.bind(this), 500);
// new
setTimeout(() => {
// ...
}, 500);
But: If the code which calls the callback explicitly sets this to a specific value, as is often the case with event handlers, especially with jQuery, and the callback uses this (or arguments), you cannot use an arrow function!
Variadic functions
Since arrow functions don't have their own arguments, you cannot simply replace them with an arrow function. However, ES2015 introduces an alternative to using arguments: the rest parameter.
// old
function sum() {
let args = [].slice.call(arguments);
// ...
}
// new
const sum = (...args) => {
// ...
};
Related question:
When should I use arrow functions in ECMAScript 6?
Do ES6 arrow functions have their own arguments or not?
What are the differences (if any) between ES6 arrow functions and functions bound with Function.prototype.bind?
How to use arrow functions (public class fields) as class methods?
Further resources:
MDN - Arrow functions
YDKJS - Arrow functions

Arrow functions => best ES6 feature so far. They are a tremendously
powerful addition to ES6, that I use constantly.
Wait, you can't use arrow function everywhere in your code, its not going to work in all cases like this where arrow functions are not usable. Without a doubt, the arrow function is a great addition it brings code simplicity.
But you can’t use an arrow function when a dynamic context is required: defining methods, create objects with constructors, get the target from this when handling events.
Arrow functions should NOT be used because:
They do not have this
It uses “lexical scoping” to figure out what the value of “this”
should be. In simple word lexical scoping it uses “this” from the
inside the function’s body.
They do not have arguments
Arrow functions don’t have an arguments object. But the same
functionality can be achieved using rest parameters.
let sum = (...args) => args.reduce((x, y) => x + y, 0);
sum(3, 3, 1) // output: 7
They cannot be used with new
Arrow functions can't be constructors because they do not have a prototype property.
When to use arrow function and when not:
Don't use to add function as a property in object literal because we
can not access this.
Function expressions are best for object methods. Arrow functions
are best for callbacks or methods like map, reduce, or forEach.
Use function declarations for functions you’d call by name (because
they’re hoisted).
Use arrow functions for callbacks (because they tend to be terser).

To use arrow functions with function.prototype.call, I made a helper function on the object prototype:
// Using
// #func = function() {use this here} or This => {use This here}
using(func) {
return func.call(this, this);
}
usage
var obj = {f:3, a:2}
.using(This => This.f + This.a) // 5
Edit
You don't NEED a helper. You could do:
var obj = {f:3, a:2}
(This => This.f + This.a).call(undefined, obj); // 5

They are not always equivalent. Here's a case where you cannot simply use arrow functions instead of regular functions.
Arrow functions CANNOT be used as constructors
TLDR:
This is because of how Arrow Functions use the this keyword. JS will simply throw an error if it sees an arrow function being invoked as a "constructor". Use regular functions to fix the error.
Longer explanation:
This is because objects "constructors" rely on the this keyword to be able to be modified.
Generally, the this keyword always references the global object. (In the browser it is the window object).
BUT, when you do something like:
function personCreator(name) {
this.name = name;
}
const person1 = new personCreator('John');
The new keyword do some of its magic and makes the this keyword that is inside of personCreator to be initially an empty object instead of referencing the global object. After that, a new property called name is created inside that empty this object, and its value will be 'John'. At the end, the this object is returned.
As we see, the new keyword changed the value of this from referencing the global object to now be an empty object {}.
Arrow functions do not allow their this object to be modified. Their this object is always the one from the scope where they were statically created. This is called Static Lexical Scope. That is why you cannot do operations like bind, apply, or call with arrow functions. Simply, their this is locked to the value of the this of the scope were they were created. This is by design.
And because of this :D, arrow functions cannot be used as "constructors".
Side Note:
A lexical scope is just the area where a function is created. For example:
function personCreator(name) {
this.name = name;
const foo = () => {
const bar = () => {
console.log(this); // Output: { name: 'John' }
}
console.log(this); // Output: { name: 'John' }
bar();
}
foo();
}
const person1 = new personCreator('John');
The lexical scope of bar is everything that is within foo. So, the this value of bar is the one that foo has, which is the one of personCreator.

Related

nodejs function syntax in module.export

consider the following:
let y = doSomething(){ //doesn't work
console.log('sdf')
}
let y = function doSomething(){ //works
console.log('sdf')
}
module.exports = {
getAll(){
}
}
I had never seen this sort of function(inside the module.exports) is it a call or definition?
It differs in that it doesn't have a keyword function, yet it's exported. What is it called? Does it have a specific name, most importantly, what are we actually doing in here? Please leave me a link to finding out more on this sort of definition if possible.
let y = function doSomething() {} called Function expressions
a name can be provided with a function expression. Providing a name allows the function to refer to itself, and also makes it easier to identify the function in a debugger's stack traces:
module.exports = {
getAll(){}
}
It exports an anonymous object which has a getAll() method. It's called Method definitions

'this' in regular function vs fat arrow function in ES6, illustrated with an example of Mongoose

In router/user.js for routing:
router.post('/register', auth.optional, (req, res, next) => {
const {
body: { user }
} = req
// validation code skipped for brevity
const finalUser = new User(user)
finalUser.setPassword(user.password)
// to save the user in Mongo DB
return finalUser.save().then(() => res.json({ user: finalUser.toAuthJSON() }))
})
Post request sent with a body of:
{
"user":{
"email":"leon#idiot.com",
"password": "123abc"
}
}
In model/User.js for database schema:
const UserSchema = new Schema({
email: String,
hash: String,
salt: String
})
// Please note: this is a regular/normal function definition
UserSchema.methods.setPassword = function (password) {
// this references the UserSchema created
this.salt = crypto.randomBytes(16).toString('hex')
console.log(`salt: ${this.salt}`)
this.hash = crypto
.pbkdf2Sync(password, this.salt, 10000, 512, 'sha512')
.toString('hex')
console.log(`hash: ${this.hash}`)
}
Everything works fine now. The log output as:
salt: e7e3151de63fc8a90e3621de4db0f72e
hash: 19dd9fdbc78d0baf20513b3086976208ab0f9eee6d68f3c71c72cd123a06459653c24c11148db03772606c40ba4846e2f9c6d4f1014d329f01d22805fc988f6164fc13d4157394b118d921b9cbd742ab510e4d2fd4ed214a0d523262ae2b2f80f6344fbd948e8c858f95ed9706952db90d415312156a994c65c42921afc8c3e5b1b24a923219445eec8ed62de313ab3d78dc93b715689a552b6449870c5bfcc3bec80c4438b1895cab41f92ef681344ac8578de476a82aa798730cf3a6ef86973a4364a8712c6b3d53ce67ffffd7569b9ade5db09ad95490354c6f7194fdd9d8f8a1cb7ccddf59e701198a1beee59a2dd6afb90ae50e26ea480e9a6d607e4b37857a02016ee4d692d468dd9a67499547eb03fc6cfa676686f7990c2251c9516459288c55584138aed56a5df6c4692f7ef6925e8f3d6f6a0c780c4d80580447f2b1258bea799a8c7eb9da878ab70a94c4227ec03d18d56b2722c315d0e2b2681d81d78d4213288f7305cbbfa377c3b2eb75e0f0b093e6067b14adce4a01f0a7bde8515350a1c987739c12574ec4c49008510e2e7e5534f9b76d15b1af68e43ef54e6b8a1bea859aafd23d6b6bc61d5b1965004cd6dd933545cf755f3e6dfc8f230f37a79a8bc006b9b14465b1b08d60cb45ef3b6a1b73f5afac90bdc58d5ec15c7596dc7e8d503f8dfbd6a3289cf997da2031389c7f3d165e34b29178f3daf76d
3
But it does not work with such a definition:
UserSchema.methods.setPassword = password => {
// what this reference is undefined, so are ones below
this.salt = crypto.randomBytes(16).toString('hex')
console.log(`salt: ${this.salt}`)
this.hash = crypto
.pbkdf2Sync(password, this.salt, 10000, 512, 'sha512')
.toString('hex')
console.log(`hash: ${this.hash}`)
}
The error is:
{
"errors": {
"message": "Cannot set property 'salt' of undefined",
"error": {}
}
}
which means what this referenced is undefined.
What I find online is that fat arrow functions explicitly prevent binding of this, and it's a problem of scopes, that this in fat arrow functions has a scope of its immediate object. But I cannot say that I understand it very well.
1. In this case, what is the scope of this in fat arrow functions?
2. What is the scope, of this, in normal function definitions?
3. How to access the object, in this case: UserSchema, properties (forgive me for less proper words) in fat arrow functions as one does in normal function definitions?
These posts are quite helpful:
Are 'Arrow Functions' and 'Functions' equivalent / exchangeable?
How does the “this” keyword work?
But I am still expecting answers to my specific questions in particular cases, before figuring them out.
The core of your misunderstanding is this:
that this in fat arrow functions has a scope of immediate object
Wrong. It's context is resolved in the scope of the currently executing function/environment.
Examples:
// global scope outside of any function:
let foo = {};
// Define a method in global scope (outside of any function)
foo.a = () => {
console.log(this); // undefined
}
// Return a function from scope of a method:
foo.b = function () {
// remember, "this" in here is "foo"
return () => {
console.log(this); // foo - because we are in scope foo.c()
}
}
foo.a(); // undefined
foo.b()(); // foo
For arrow functions, it is not what object the function belongs to that matters but where it is defined. In the second example, the function can completely not belong to foo but will still print foo regardless:
bar = {};
bar.b = foo.b();
bar.b(); // will log "foo" instead of "bar"
This is the opposite of regular functions which depend on how you call them instead on where you define them:
// Defined in global scope:
function c () {
console.log(this);
}
bar.c = c;
bar.c(); // will log "bar" instead of undefined because of how you call it
Note
Note that there are two very different concepts here that are intermingled - context (what value "this" has) and scope (what variables are visible inside a function). Arrow function uses scope to resolve context. Regular functions do not use scope but instead depend on how you call them.
Questions
Now to answer some of your questions:
In this case, what is the scope of this in fat arrow functions?
As I said. Scope and this are two unrelated concepts. The concept behind this is object/instance context - that is, when a method is called what object is the method acting on. The concept of scope is as simple as what are global variables and what variables exist only inside a specific function and it can evolve to more complicated concepts like closures.
So, since scope is always the same, the only difference is in arrow functions, its context (its this) is defined by the scope. That is, when the function is being declared, where is it declared? At the root of the file? Then it has global scope and this equals "undefined". Inside another function? Then it depends on how that function is called. If it was called as a method of an object such as UserSchema.methods for example if UserSchema.methods.generatePasswordSetter() returns an arrow function, then that function (let's call it setPassword()) will have it's this point to the correct object.
What is the scope, of this, in normal function definitions?
Based on my explanation above I can only sat that scope is not involved with the value of this in normal functions. For a more detailed explanation of how this works see my answer to this other question: How does the "this" keyword in Javascript act within an object literal?
How to access the object, in this case: UserSchema, properties (forgive me for less proper words) in fat arrow functions as one does in normal function definitions?
The way it's defined it is not possible. You need to define it from a regular function that has it's this pointing to UserSchema:
UserSchema.methods.generatePasswordSetter = function () {
return (password) => { /* implementation... */}
}
But this is probably not what you want. To do what you want you only need to stop using arrow functions in this case. Regular functions still exist for use-cases such as this.

Javascript coding format between hash and class [duplicate]

I'm curious what the difference is between the following OOP javascript techniques. They seem to end up doing the same thing but is one considered better than the other?
function Book(title) {
this.title = title;
}
Book.prototype.getTitle = function () {
return this.title;
};
var myBook = new Book('War and Peace');
alert(myBook.getTitle())
vs
function Book(title) {
var book = {
title: title
};
book.getTitle = function () {
return this.title;
};
return book;
}
var myBook = Book('War and Peace');
alert(myBook.getTitle())
The second one doesn't really create an instance, it simply returns an object. That means you can't take advantage of operators like instanceof. Eg. with the first case you can do if (myBook instanceof Book) to check if the variable is a type of Book, while with the second example this would fail.
If you want to specify your object methods in the constructor, this is the proper way to do it:
function Book(title) {
this.title = title;
this.getTitle = function () {
return this.title;
};
}
var myBook = new Book('War and Peace');
alert(myBook.getTitle())
While in this example the both behave the exact same way, there are differences. With closure-based implementation you can have private variables and methods (just don't expose them in the this object). So you can do something such as:
function Book(title) {
var title_;
this.getTitle = function() {
return title_;
};
this.setTitle = function(title) {
title_ = title;
};
// should use the setter in case it does something else than just assign
this.setTitle(title);
}
Code outside of the Book function can not access the member variable directly, they have to use the accessors.
Other big difference is performance; Prototype based classing is usually much faster, due to some overhead included in using closures. You can read about the performance differences in this article: http://blogs.msdn.com/b/kristoffer/archive/2007/02/13/javascript-prototype-versus-closure-execution-speed.aspx
Which is better can sometimes be defined by the context of their usage.
Three constraints of how I choose between Prototype and Closure methods of coding (I actively use both):
Performance/Resources
Compression requirements
Project Management
1. Performance/Resources
For a single instance of the object, either method is fine. Any speed advantages would most likely be negligible.
If I am instantiating 100,000 of these, like building a book library, then the Prototype Method would be preferred. All the .prototype. functions would only be created once, instead of these functions being created 100,000 times if using the Closure Method. Resources are not infinite.
2. Compression
Use the Closure Method if compression efficiency is important (ex: most browser libraries/modules). See below for explanation:
Compression - Prototype Method
function Book(title) {
this.title = title;
}
Book.prototype.getTitle = function () {
return this.title;
};
Is YUI compressed to
function Book(a){this.title=a}Book.prototype.getTitle=function(){return this.title};
A savings of about 18% (all spaces/tabs/returns). This method requires variables/functions to be exposed (this.variable=value) so every prototype function can access them. As such, these variables/functions can't be optimized in compression.
Compression - Closure Method
function Book(title) {
var title = title; // use var instead of this.title to make this a local variable
this.getTitle = function () {
return title;
};
}
Is YUI compressed to
function Book(a){var a=a;this.getTitle=function(){return a}};
A savings of about 33%. Local variables can be optimized. In a large module, with many support functions, this can have significant savings in compression.
3. Project Management
In a project with multiple developers, who could be working on the same module, I prefer the Prototype Method for that module, if not constrained by performance or compression.
For browser development, I can override the producton.prototype.aFunction from "production.js" in my own "test.js" (read in afterwords) for the purpose of testing or development, without having to modify the "production.js", which may be in active development by a different developer.
I'm not a big fan of complex GIT repository checkout/branch/merge/conflict flow. I prefer simple.
Also, the ability to redefine or "hijack" a module's function by a testbench can be beneficial, but too complicated to address here...
The former method is how JavaScript was intended to be used. The latter is the more modern technique, popularised in part by Douglas Crockford. This technique is much more flexible.
You could also do:
function Book(title) {
return {
getTitle: function () {
return title;
}
}
}
The returned object would just have an accessor called getTitle, which would return the argument, held in closure.
Crockford has a good page on Private Members in JavaScript - definitely worth a read to see the different options.
It's also a little bit about re-usability under the hood. In the first example with the Function.prototype property usage all the instances of the Book function-object will share the same copy of the getTitle method. While the second snippet will make the Book function execution create and keep in the heap 'bookshelf' different copies of the local closurable book object.
function Book(title) {
var book = {
title: title
};
book.getTitle = function () {
return this.title += '#';
};
return book;
}
var myBook = Book('War and Peace');
var myAnotherBook = Book('Anna Karenina');
alert(myBook.getTitle()); // War and Peace#
alert(myBook.getTitle()); // War and Peace##
alert(myAnotherBook.getTitle()); // Anna Karenina#
alert(myBook.getTitle());// War and Peace###
The prototype members exist in the only copy for all the new instances of the object on the other hand. So this is one more subtle difference between them that is not very obvious from the first sigh due to the closure trick.
here is an article about this
in general Book inharets from Book.prototype. In first example you add function to getTitle Book.prototype

How to implement inheritance in Node.JS

How do we use 'inheritance' in Node.JS? I heard that prototype is similar to interfaces in java. But I have no idea how to use it!
Although there are various ways of performing inheritance and OO in javascript, in Node.js you would typically use the built in util.inherits function to create a constructor which inherits from another.
See http://book.mixu.net/ch6.html for a good discussion on this subject.
for example:
var util = require("util");
var events = require("events");
function MyOwnClass() {
// ... your code.
}
util.inherits(MyOwnClass, events.EventEmitter);
Creating an object constructor in pure JS:
They're just functions like any other JS function but invoked with the new keyword.
function Constructor(){ //constructors are typically capitalized
this.public = function(){ alert(private); }
var private = "Untouchable outside of this func scope.";
}
Constructor.static = function(){ alert('Callable as "Constructor.static()"'); }
var instance = new Constructor();
Inheritance:
function SubConstructor(){
this.anotherMethod(){ alert('nothing special'); }
}
function SubConstructor.prototype = new Constructor();
var instance = new SubConstructor();
instance.public(); //alerts that private string
The key difference is that prototypal inheritance comes from objects, rather than the things that build them.
One disadvantage is that there's no pretty way to write something that makes inheritance of instance vars like private possible.
The whopping gigantor mega-advantage, however, is that we can mess with the prototype without impacting the super constructor, changing a method or property for every object even after they've been built. This is rarely done in practice in higher-level code since it would make for an awfully confusing API but it can be handy for under-the-hood type stuff where you might want to share a changing value across a set of instances without just making it global.
The reason we get this post-instantiated behavior is because JS inheritance actually operates on a lookup process where any method call runs up the chain of instances and their constructor prototype properties until it finds the method called or quits. This can actually get slow if you go absolutely insane with cascading inheritance (which is widely regarded as an anti-pattern anyway).
I don't actually hit prototype specifically for inheritacne a lot myself, instead preferring to build up objects via a more composited approach but it's very handy when you need it and offers a lot of less obvious utility. For instance when you have an object that would be useful to you if only one property were different, but you don't want to touch the original.
var originInstance = {
originValue:'only on origin',
theOneProperty:'that would make this old object useful if it were different'
}
function Pseudoclone(){
this.theOneProperty = "which is now this value";
}
Pseudoclone.prototype = originInstance;
var newInstance = new Psuedoclone();
//accesses originInstance.originValue but its own theOneProperty
There are more modern convenience methods like Object.create but only function constructors give you the option to encapsulate private/instance vars so I tend to favor them since 9 times out of 10 anything not requiring encapsulation will just be an object literal anyway.
Overriding and Call Object Order:
( function Constructor(){
var private = "public referencing private";
this.myMethod = function(){ alert(private); }
} ).prototype = { myMethod:function(){ alert('prototype'); };
var instance = new Constructor();
instance.myMethod = function(){ alert(private); }
instance.myMethod();//"undefined"
Note: the parens around the constructor allow it to be defined and evaluated in one spot so I could treat it like an object on the same line.
myMethod is alerting "undefined" because an externally overwritten method is defined outside of the constructor's closure which is what effective makes internal vars private-like. So you can replace the method but you won't have access to what it did.
Now let's do some commenting.
( function Constructor(){
var private = "public referencing private";
this.myMethod = function(){ alert(private); }
} ).prototype = { myMethod:function(){ alert('prototype'); };
var instance = new Constructor();
//instance.myMethod = function(){ alert(private); }
instance.myMethod();//"public referencing private"
and...
( function Constructor(){
var private = "public referencing private";
//this.myMethod = function(){ alert(private); }
} ).prototype = { myMethod:function(){ alert('prototype'); };
var instance = new Constructor();
//instance.myMethod = function(){ alert(private); }
instance.myMethod();//"prototype"
Note that prototype methods also don't have access to that internal private var for the same reason. It's all about whether something was defined in the constructor itself. Note that params passed to the constructor will also effectively be private instance vars which can be handy for doing things like overriding a set of default options.
Couple More Details
It's actually not necessary to use parens when invoking with new unless you have required parameters but I tend to leave them in out of habit (it works to think of them as functions that fire and then leave an object representing the scope of that firing behind) and figured it would be less alien to a Java dev than new Constructor;
Also, with any constructor that requires params, I like to add default values internally with something like:
var param = param || '';
That way you can pass the constructor into convenience methods like Node's util.inherit without undefined values breaking things for you.
Params are also effectively private persistent instance vars just like any var defined in a constructor.
Oh and object literals (objects defined with { key:'value' }) are probably best thought of as roughly equivalent to this:
var instance = new Object();
instance.key = 'value';
With a little help from Coffeescript, we can achieve it much easier.
For e.g.: to extend a class:
class Animal
constructor: (#name) ->
alive: ->
false
class Parrot extends Animal
constructor: ->
super("Parrot")
dead: ->
not #alive()
Static property:
class Animal
#find: (name) ->
Animal.find("Parrot")
Instance property:
class Animal
price: 5
sell: (customer) ->
animal = new Animal
animal.sell(new Customer)
I just take the sample code Classes in CoffeeScript. You can learn more about CoffeeScript at its official site: http://coffeescript.org/

How can I break this code up into two RequireJs modules

I've created the code below to dynamically load 2 buttons into an element with an ID of masthead. Then a function called showMenus runs when each button is clicked, running some jQuery animations. Everything is wrapped inside of a RequireJS module.
The code works fine as is but I'm thinking it may be better to break it up into two separate RequireJS modules/files: one that loads the buttons on the page and another one that runs the showMenus function. I did refer to the RequireJS API docs but couldn't find an answer.
Any help is appreciated...thanks in advance!
require(['jquery'], function ($) {
var header = document.getElementById("masthead"),
$navMenu = $("#site-navigation-list"),
$searchBox = $("#searchform"),
menuButton = document.createElement("div"),
searchButton = document.createElement("div"),
showMenus;
$(menuButton).attr("id", "menu");
$(searchButton).attr("id", "search");
header.appendChild(searchButton);
header.appendChild(menuButton);
// break the code below into its on RequireJS module?
showMenus = function(btn,el) {
$(btn).click(function() {
if (el.is(":visible") ) {
el.slideUp({
complete:function(){
$(this).css("display","");
}
});
} else {
el.slideDown();
}
});
};
showMenus(menuButton, $navMenu);
showMenus(searchButton, $searchBox);
});
What follows is only my opinion, but you might find it useful.
It might help to think in terms of things that your app is made of, and then maybe they are candidates for modules. So in your example, a 'masthead' seems to be a thing that you are interested in.
So using RequireJS, we can create a new module representing a generic masthead:
// Masthead module
define(['jquery'], function ($) {
function showMenus (btn, el) {
function toggle (el) {
if (el.is(":visible")) {
el.slideUp({
complete:function(){
$(this).css("display","");
}
});
} else {
el.slideDown();
}
}
$(btn).click(function() {
toggle(el);
});
}
// A Masthead is an object that encapsulates a masthead DOM element.
// This is a constructor function.
function Masthead (mastheadElement) {
// 'this' is the masthead object that is created with the 'new'
// keyword in your application code.
// We save a reference to the jQuerified version of mastheadElement.
// So mastheadElement can be a DOM object or a CSS selector.
this.$mastheadElement = $(mastheadElement);
}
// Add a method to Masthead that creates a normal button
Masthead.prototype.addButton = function (id) {
var $btn = $("<div/>").attr("id", id);
this.$mastheadElement.append($btn);
return $btn;
};
// Add a method to Masthead that creates a 'toggling' button
Masthead.prototype.addTogglingButton = function (id, elementToToggle) {
// ensure we have a jQuerified version of element
elementToToggle = $(elementToToggle);
// Reuse the existing 'addButton' method of Masthead.
var $btn = this.addButton(id);
showMenus($btn, elementToToggle);
return $btn;
};
// return the Masthead constructor function as the module's return value.
return Masthead;
});
And then use this module in our actual application code:
// Application code using Masthead module
require(["Masthead"], function (Masthead) {
// We create a new Masthead around an existing DOM element
var masthead = new Masthead("#masthead");
// We add our buttons.
masthead.addTogglingButton("menu", "#site-navigation-list");
masthead.addTogglingButton("search", "#searchform");
});
The advantage of this approach is that no DOM ids are hard-coded into the module. So we can reuse the Masthead module in other applications that require this functionality, but which may be using different DOM ids.
It might be convenient to think of this as separating the what things are from the how we use them.
This is a simple example, but frameworks/libraries like Backbone and Dojo (and many, many more) take this further.

Resources