Skip to content

Instantly share code, notes, and snippets.

@matthewstokeley
Last active November 17, 2019 19:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matthewstokeley/d30868b5e677a8555716087f45409b57 to your computer and use it in GitHub Desktop.
Save matthewstokeley/d30868b5e677a8555716087f45409b57 to your computer and use it in GitHub Desktop.

Lexical scope

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.

Example

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 )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment