JavaScript Patterns 读书笔记(四)
4.Function Pattern
- Namespace Pattern
? ?Namespaces help reduce the number of globals required by our programs and at the?same time also help avoid naming collisions or excessive name prefixing.?JavaScript doesn’t have namespaces built into the language syntax, but this is a feature?that is quite easy to achieve. Instead of polluting the global scope with a lot of functions,?objects, and other variables, you can create one (and ideally only one) global object for?your application or library. Then you can add all the functionality to that object.?Consider the following example:
// BEFORE: 5 globals
// Warning: antipattern
// constructors
function Parent() {}
function Child() {}
// a variable
var some_var = 1;
// some objects
var module1 = {};
module1.data = {a: 1, b: 2};
var module2 = {};
??? You can refactor this type of code by creating a single global object for your application,?called, for example, MYAPP, and change all your functions and variables to become?properties of your global object:
// AFTER: 1 global
// global object
var MYAPP = {};
// constructors
MYAPP.Parent = function () {};
MYAPP.Child = function () {};
// a variable
MYAPP.some_var = 1;
// an object container
MYAPP.modules = {};
// nested objects
MYAPP.modules.module1 = {};
MYAPP.modules.module1.data = {a: 1, b: 2};
MYAPP.modules.module2 = {};
???For the name of the global namespace object, you can pick, for example, the name of your application or library, your domain name, or your company name. Often developers use the convention of making the global variable ALL CAPS, so it stands out to the readers of the code. (But keep in mind that all caps are also often used for constants.)
? This pattern is a good way to namespace your code and to avoid naming collisions in your own code, and collisions between your code and third-party code on the same page, such as JavaScript libraries or widgets. This pattern is highly recommended and perfectly applicable for many tasks, but it does have some drawbacks:
???? ?? A bit more to type; prefixing every variable and function does add up in the total
????amount of code that needs to be downloaded
??? ?? Only one global instance means that any part of the code can modify the global
????instance and the rest of the functionality gets the updated state
???? ? Long nested names mean longer (slower) property resolution lookups
The sandbox pattern discussed later in the chapter addresses these drawbacks.
- Declaring Dependencies
?? JavaScript libraries are often modular and namespaced, which enables you to include only the modules you require. For example, in YUI2 there’s a global variable YAHOO,?which serves as a namespace, and then modules that are properties of the global variable,?such as YAHOO.util.Dom (the DOM module) and YAHOO.util.Event (Events module).
?? It’s a good idea to declare the modules your code relies on at the top of your function?or module. The declaration involves creating only a local variable and pointing to the?desired module:
var myFunction = function () {
// dependencies
var event = YAHOO.util.Event,
dom = YAHOO.util.Dom;
// use event and dom variables
// for the rest of the function...
};
?This is an extremely simple pattern, but at the same time it has numerous benefits:
?? ?? Explicit declaration of dependencies signals to the users of your code the specific script files that they need to make sure are included in the page.
???? ? Upfront declaration at the top of the function makes it easy to find and resolve dependencies.
?? ? ? Working with a local variable (such as dom) is always faster than working with a global (such as YAHOO) and even faster than working with nested properties of a global variable (such as YAHOO.util.Dom),