Javascript does not have a mechanism to preserve the global namespace, which can lead to namespace
collisions and other errors. Foundation
uses a one-line initialization script, var foundation = {}
, to create an object that can function
as a namespace. In Javascript, when an object is declared, an environment record
or scope is also created - functions and variables located within the same
environment record have access to each other. Objects and functions contain their own environment record. try catch
blocks and conditionals do not.
The IIFE
was a popular construct used in the development of jQuery
and documented in Addy Osmani's JS Design Patterns
as
the revealing module
pattern to help avoid namespace and scope collisions by wrapping a function with an immediately-invoked function -
the wrapper is invoked on runtime and functions and variables are declared within the IIFE's scope rather than the global scope.
Variables and functions located in the global namespace can be piped in as arguments.
twbs4 and other popular front-end frameworks have moved toward the es6 class construct.
Object declared in the global namespace
var _elements = {};
Construction of the IFFE
- a function wrapped in an immediately-invoked function
( function( ) { } )( )
- variables piped in from the global namespace
( function ( prop ) { } ) ( prop )
( function( _elements ) {
Declare variables within the IIFE's scope - this variable will not be available in the global namespace
var defaultOptions = {};
/**
* Wrapper for `document.createElement`
*
*
* @param {Array} options
* @return {Element}
*/
var createElement = function( options ) {
if ( typeof options !== 'object' ) {
If we clone the default options, we aren't preserving the reference to the defaultOptions object declared in the outer record.
options = clone(defaultOptions)
)
var element = document.createElement( options.element );
for ( var prop in options.properties ) {
if ( options.hasOwnProperty( prop ) ) {
elements[ prop ] = options.properties[ prop ];
}
}
return element;
};
Add the method to the global object.
_elements.addClass = addClass
Invoke the outer wrapper and pipe in a global variable.
})( _elements );
Other examples of lexical scoping in javascript and php
Classes
class ExampleClass
{
classProperty = ‘requiresPolyfill’
method() {
console.log( ‘accessible via `this` object ’ + this.classProperty )
}
}
<?php
class ExampleClass
{
classProperty = ‘native since 5.3’;
public function method() {
echo $this->classProperty;
}
}
var PrototypalJS = function() {
// a constructor
}
PrototypalJS.prototype.prop = ‘string property’;
PrototypalJS.prototype.method = function() {
console.log( this.prop );
}
// Explicit context handling in javascript
const context = {}
const arg = []
const method = () => {}
method.call( context, arg )
// Piping from the global context in php
$globalVar = ‘’
call_user_func( function() use ( $globalVar ) { }, $args )
// Implicit local scoping with a static method
$args = []
class StaticUtilities
{
public function static helperMethod() {
}
}
call_user_func( array( ’StaticUtilities’, ‘helperMethod ), $args )