Difference between revisions of "JavaScript"

From Organic Design wiki
m (Closures)
m (Closures)
Line 59: Line 59:
  
  
To pass globals into your closure such as jQuery as $, use the syntax shown below. Notice in this example some other common globals are also passed without changing their names - this is commonly seen nowadays and is done for three reasons:
+
To pass globals into your closure such as jQuery as $, use the syntax shown below. This example doesn't assign the final closure to a variable, since often the code inside will perform everything it needs to do directly onto the environment, such as modifying the page or adding extensions to jQuery etc rather than offering a public API in its return value. Notice in this example some other common globals are also passed without changing their names - this is commonly seen nowadays and is done for three reasons:
 
*The interpreter doesn't need to walk the scope tree to find the value
 
*The interpreter doesn't need to walk the scope tree to find the value
 
*The names can be compressed along with other normal variables when the code is minimised
 
*The names can be compressed along with other normal variables when the code is minimised
 
*The code can be sure that the names haven't been hijacked or modified by some other badly written code
 
*The code can be sure that the names haven't been hijacked or modified by some other badly written code
 
For the third reason, you'll often see nowadays the ''undefined'' variable being added to the inner argument list but not the outer - this ensure that ''undefined'' has not been set to something else and really is ''undefined'' by not having an equivalent value assigned to it from the outer function's argument list.
 
For the third reason, you'll often see nowadays the ''undefined'' variable being added to the inner argument list but not the outer - this ensure that ''undefined'' has not been set to something else and really is ''undefined'' by not having an equivalent value assigned to it from the outer function's argument list.
{{code|<js>var closure = ( function($, document, window, undefined) {
+
{{code|<js>( function($, document, window, undefined) {
  
 
     ...
 
     ...

Revision as of 14:16, 26 March 2015

JavaScript is most commonly used as the scripting language in the browser, but is increasingly being seen on the server-side mainly in the form of Node.js, and on the desktop such as in GNOME's desktop extension system.

Technically JavaScript is classified as a prototype-based scripting language with dynamic typing and first-class functions. This mix of features makes it a multi-paradigm language, supporting object-oriented, imperative, and functional programming styles. JavaScript has been standardised in the ECMAScript language specification.

Despite some naming, syntactic, and standard library similarities, JavaScript and Java are unrelated and have very different semantics. The syntax of JavaScript is actually derived from C, while the semantics and design are influenced by the Self and Scheme programming languages.\

Scope

One of the main sources of confusion with scoping in JavaScript is that most programmers are used to the way scoping works in C-like languages such as PHP or Java. These language use block-based scoping, where every new block automatically forms a new scope in which new variables can be defined locally, and functions form a kind of scope-bubble where only the locally defined names are available (usually access is allowed to the global scope via the global keyword). JavaScript on the other hand, uses function-based scoping which is unaffected by blocks such as for-loops or if-statements and is purely determined by the currently executing function.

Another important thing to remember is that items defined by the var keyword or by function declarations are brought into the scope at the beginning of execution of that scope regardless of their position within that scope (the actual assignment takes place at the location of the definition for variables, or at the beginning for function declarations). For this reason it has become a common practice to include only one var statement at the beginning of each function which declares all variables that are used throughout it, this avoids confusion and ensures that the code reflects the reality of what's happening.

These are the most important points, but for more subtle details see this excellent short article about it, Scoping and hoisting by Ben Cherry.

Prototypes

JavaScript is a prototype-based which means that there is no explicit support for classes, it's only how instances are used within a program that determines which objects are treated as classes and which as instances.

Inheritance is not supported directly in the language either and is left up to the programmer to implement this functionality if they need it. There are many ways of achieving inheritance, and even some libraries such as klass and selfish.js] have been written specifically to address this need, but most JavaScript gurus tend to think that using inheritance in a JavaScript application's architecture is the wrong approach, and instead the programmer should learn the instance-based approach more deeply as discussed by David Walsh here and in Chapter 8 of Eloquent JavaScript.

The most flexible way of creating re-usable objects in JavaScript is with a special type of function syntax called a closure which results in a structure that has private scope available only to its own methods, and can also return a public API.

Closures

A closure is like a bubble in JavaScript in that it acts like a separate self-contained global scope, and can contain variables, functions, and even entire JavaScript frameworks like jQuery. The Module Pattern is a closely related concept which is the most common form that closures take, it's become the generally accepted method of creating JavaScript code designed to be imported without any assumptions as to the target environment.

Closures can have both a private and public aspect, they're in the form of a function rather than an object, and are brought into existence by calling them, what's returned is the public interface. The content of the scope within the closures definition is private and exists for as long as the returned public interface exists.

The following example illustrates a simple closure. The variable foo is private and can only be accessed by functions in the same private scope, or by the functions returned in the public interface. An instance of the closure is created in the variable closure by being assigned the value returned by anonymously executing the declared function.

{{{1}}}


In the example above, the public function baz can access the private foo variable from it's local scope. The public interface also includes a variable bar which can be accessed publicly or via this from within the executing public interface functions. All of the items in both the private and the public scopes of the closure exist for the lifetime of the closure object.

In this next example, a single private variable is defined, and there are two public functions which are called one after the other. The first stores a secret message in the private variable which the second displays. This shows that the private local scope of the functions remains intact after the function exits and is available to all the functions. It is not available outside the scope of the functions thought, any data which needs to be available outside the private scope of the closure needs to be prefixed with this. Note that if the private variable were not defined in the private scope, then the function that writes to it would create the variable in the global public scope because it's not using the var keyword.

{{{1}}}


To pass globals into your closure such as jQuery as $, use the syntax shown below. This example doesn't assign the final closure to a variable, since often the code inside will perform everything it needs to do directly onto the environment, such as modifying the page or adding extensions to jQuery etc rather than offering a public API in its return value. Notice in this example some other common globals are also passed without changing their names - this is commonly seen nowadays and is done for three reasons:

  • The interpreter doesn't need to walk the scope tree to find the value
  • The names can be compressed along with other normal variables when the code is minimised
  • The code can be sure that the names haven't been hijacked or modified by some other badly written code

For the third reason, you'll often see nowadays the undefined variable being added to the inner argument list but not the outer - this ensure that undefined has not been set to something else and really is undefined by not having an equivalent value assigned to it from the outer function's argument list.

<js>( function($, document, window, undefined) {
   ...

}(jQuery, document, window) );</js>


For more in-depth information about closures, see Understanding closures, The Module pattern in-depth and Snook.ca Why I don't love the JavaScript module pattern.

Single-page applications

A single-page application (SPA), also known as single-page interface (SPI), is a web application that fits on a single web page. In an SPA, either all necessary code – HTML, JavaScript, and CSS – is retrieved with a single page load, or partial changes are performed loading new code on demand from web servers, usually driven by user actions.

The page does not automatically reload during user interaction with the application, nor does control transfer to another page. Necessary updates to the page display may or may not involve interaction with a server. The term single-page application was coined by Steve Yen in 2005, though the concept was discussed at least as early as 2003.

Hash fragments

A central concept making single-page applications possible is the idea of "hash fragments" which is the part of the URL appearing after the first hash character. Everything after the hash represents addressing within the document, whereas everything before the hash is outside the page and requires a server to fetch the document. This allows applications to have their current state fully reflected within the URL so it can be bookmarked - this is one of the foundation principles of the web, that any state the application is in, for example a report or query result, can be bookmarked or sent to others as a URL. So the Single Page Application model is the best of both worlds - it has the dynamic feel of a desktop application having instant responsiveness without page reloads, but also has the important URL reflection quality of the web.

The most natural way of mapping application interface elements to functionality in the system model is to make the URL portion after the hash continue on in the form of path elements separated by slashes - hence the name "hash fragments".

For example:

http://localhost/#/path/into/unified/ontology/

This could also start with a normal domain name if the peer instance is running on a server connected to the web, in that case an optional exclamation mark could also be included which indicates that the paths should be crawlable by search engines, for example:

http://foobar.com/#!/path/into/unified/ontology/

pushState

pushState is an HTML5 API that offers a different way to change the current URL, and thereby insert new back/forward history entries, without triggering a page load. This differs from hash-based navigation in that you're not limited to updating the hash fragment — you can update the entire URL. Most modern framemworks that offer Single Page Application support can determine if the browser supports pushState and use it, but fall back to hash fragment URL format otherwise.

Existing SPAs

JavaScript frameworks

Graphics libraries

Tools

See also