Skip to content

Instantly share code, notes, and snippets.

@muhammadghazali
Last active August 29, 2015 14:01
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 muhammadghazali/c7ab0ff528b1c48ee3de to your computer and use it in GitHub Desktop.
Save muhammadghazali/c7ab0ff528b1c48ee3de to your computer and use it in GitHub Desktop.
My reading progress on JavaScript Patterns (http://shop.oreilly.com/product/9780596806767.do)

Book Contents

  • Chapter 1: Introduction
    • Patterns
    • JavaScript concepts
    • ECMAScript 5
    • JSLint
    • The Console
  • Chapter 2: Essentials
    • Writing Maintainable Code
    • Minimizing Globals
    • for Loops
    • for-in Loops
    • (Not) Augmenting Built-in Prototypes
    • switch Pattern
    • Avoiding Implied Typecasting
    • Avoiding eval()
    • Number Conversions with parseInt()
    • Coding Conventions
    • Naming Conventions
    • Writing Comments
    • Writing API Docs
    • Writing to Be Read
    • Peer Reviews
    • Minify...In Production
    • Run JSLint
    • Summary
  • Chapter 3: Literals and Constructors
    • Object Literal
    • Custom Constructor Funtions
    • Patterns for Enforcing new
    • Array Literal
    • JSON
    • Regular Expression Literal
    • Primitive Wrappers
    • Error Objects
    • Summary
  • Chapter 4: Functions
    • Background
    • Callback pattern
    • Returning functions
    • Self-Defining functions
    • Immediate functions
    • Immediate Object initialization
    • Init-Time Branching
    • Function Properties - A Memoization Pattern
    • Configuration Objects
    • Curry
    • Summary
  • Chapter 5: Object Creation Patterns
    • Namespace Pattern
    • Declaring Dependencies
    • Private Properties and Methods
    • Module Pattern
    • Sandbox Pattern
    • Static Members
    • Object Constants
    • Chaining Pattern
    • method() Method
    • Summary
@muhammadghazali
Copy link
Author

Maintainable code means code that:

  • Is readable
  • Is consistent
  • Is predictable
  • Looks as if it was written by the same person
  • Is documented

@muhammadghazali
Copy link
Author

I just know if chain assignments is an anti pattern in JavaScript:

// antipattern, do not use
function foo() {
var a = b = 0;
// ...
}
``

@muhammadghazali
Copy link
Author

When augmenting built-in prototypes:

  • it can seriously hurt maintainability, because it will make your code less predictable
  • it can create confusion, because other developers using your code will probably expect the built-in JavaScript methods to work consistently and will not expect your additions.

@muhammadghazali
Copy link
Author

Therefore it’s best if you don’t augment built-in prototypes. You can make an exception of the rule only when all these conditions are met:

  1. It’s expected that future ECMAScript versions or JavaScript implementations will implement this functionality as a built-in method consistently. For example, you can add methods described in ECMAScript 5 while waiting for the browsers to catch up. In this case you’re just defining the useful methods ahead of time.
  2. You check if your custom property or method doesn’t exist already—maybe already implemented somewhere else in the code or already part of the JavaScript engine of one of the browsers you support.
  3. You clearly document and communicate the change with the team.

@muhammadghazali
Copy link
Author

To avoid inconsistency and unexpected results, always specify the radix parameter when converting number with parseInt()

For example:

var month = "06";

month = parseInt(month, 10);

@muhammadghazali
Copy link
Author

Technically, if you have only one statement in an if or a for, curly braces are not required, but you should always use them anyway. It makes the code more consistent and easier to update.

@muhammadghazali
Copy link
Author

always use curly braces and always put the opening one on the same line as the previous statement:

function func() {
   return {
      name: "Batman"
   };
}

@muhammadghazali
Copy link
Author

peer reviews help you write clearer code, simply because you know someone else will need to read and understand what you’re doing.

Peer reviews are a good practice not only because the resulting code is better, but also because both reviewer and creator share and exchange knowledge and learn from each other’s experience and individual approaches.

@muhammadghazali
Copy link
Author

The code you write will be read (by humans), so make it easy for the maintainer to understand it quickly and let the minifier (the machine) take care of reducing the file sizes.

@muhammadghazali
Copy link
Author

Literal notation patterns available in JavaScript enable more concise, more expressive, and less error-prone object definitions.

@muhammadghazali
Copy link
Author

The custom objects you create in JavaScript (in other words, the user-defined native objects) are mutable at any time. Many of the properties of the built-in native objects are also mutable.

@muhammadghazali
Copy link
Author

There are no classes in JavaScript and this allows for great flexibility, because you don’t have to know anything about your object in advance; you don’t need a class “blueprint.” But JavaScript also has constructor functions, which use syntax similar to the class-based object creation in Java or other languages.

An obvious benefit of the literal notation is:

  • that it’s shorter to type
  • emphasizes that objects are simply mutable hashes and not something that needs to be baked from a “recipe” (from a class)

@muhammadghazali
Copy link
Author

This behavior of the Object() constructor can lead to unexpected results when the value you pass to it is dynamic and not known until runtime.

@muhammadghazali
Copy link
Author

remember that reusable members, such as methods, should go to the prototype.

The inefficient way to add method:

var Person = function (name) {
  this.name = name;
  this.say = function () {
  return "I am " + this.name;
  };
};

the say() method was added tothis . The result is that
any time you call new Person() a new function is created in memory.

The efficient way to add method:

Person.prototype.say = function () {
  return "I am " + this.name;
};

@muhammadghazali
Copy link
Author

As mentioned already, constructors are still just functions but invoked with new . What happens if you forget new when you invoke a constructor? This is not going to cause syntax or runtime errors but might lead to logical errors and unexpected behavior. That’s because when you forget new , this inside the constructor will point to the global object. (In browsers this will point to window .)

@muhammadghazali
Copy link
Author

Arrays in JavaScript, as most other things in the language, are objects. They can be created with the built-in constructor function Array() , but they also have a literal notation and, just like the object literal, the array literal notation is simpler and preferred.

@muhammadghazali
Copy link
Author

It’s only a combination of the array and the object literal notation.

In JSON strings you cannot use functions or regular expression literals.

In object literals the quotes are required only when the property names are not valid identifiers, for example, they have spaces {"first name": "Dave"}.

Use JSON.parse() method to parse JSON string. Use JSON.stringify() method to serializes into a JSON string.

@muhammadghazali
Copy link
Author

There is two options to create regular expressions in JavaScript:

  • Using the new RegExp() constructor
  • Using the regular expression literal
// regular expression literal
var re = /\\/gm;
// constructor
var re = new RegExp("\\\\", "gm");

The good thing about the regular expression literal is makes the regular expression pattern shorter and doesn't force you to think in terms of class-like constructors. Therefore it's preferable to use the literal.

When using the RegExp() constructor, we also need to escape quotes and often you need to double-escape backslashes, as shown in the preceding snippet, where we need four backslashes to match a single one. This makes your regular expression patterns longer and harder to read and modify.

So, it's best to stick with the literal notation when creating regular expression.

Calling RegExp() without new (as function, not as constructor) behaves the same as with new.

@muhammadghazali
Copy link
Author

JavaScript has five primitive value types: number, string, boolean, null, and undefined.

With the exception of null and undefined, the other three have the so-called primitive wrapper objects. The wrapper objects can be created using the built-in constructors Number, String, and Boolean.

To illustrate the difference between a primitive number and a number object, consider the following example:

// a primitive number
var n = 100;
console.log(typeof n); // "number"
// a Number object
var nobj = new Number(100);
console.log(typeof nobj); // "object"

The wrapper objects have some useful properties and methods—for example, number objects have methods such as toFixed() and toExponential() . String objects have substring() , charAt() , and toLowerCase() methods (among others) and a length property. These methods are convenient and can be a good reason to decide to create an object, as opposed to using a primitive. But the methods work on primitives, too—as soon as you invoke a method, the primitive is temporarily converted to an object behind the scenes and behaves as if it were an object.

One reason to use the wrapper objects is when you want to augment the value and persist state. Because primitives are not objects, they cannot be augmented with properties.

When used without new , wrapper constructors convert the argument passed to them to a primitive value:

typeof
typeof
typeof
typeof
typeof
Number(1); // "number"
Number("1"); // "number"
Number(new Number()); // "number"
String(1); // "string"
Boolean(1); // "boolean"

@muhammadghazali
Copy link
Author

Chapter 4. Functions

Mastering functions is an essential skill for the the JavaScript programmer because the language has many uses for them.

There are two main features of the functions in JavaScript that make them special, the first is that functions are first-class objects and the second is that they provide scope.

Functions are objects that:

  • Can be created dynamically at runtime, during the execution of the program
  • Can be assigned to variables, can have their references copied to other variables, can be augmented, and except for a few special cases, can be deleted.
  • Can be passed as arguments to other functions and can also be returned by other functions
  • Can have their own properties and methods

Using the Function() constructor is not a good idea though (it's as bad as eval()) because code is passed around as a string and evaluated.

The second important feature is that functions provide scope. In JavaScript there's no curly braces local scope; in other words, blocks don't create scope. There's only function scope.

Example of named function expression:

var add = function add(a, b) {
  return a + b;
};

Example of unnamed function expression aka anonymous function:

var add = function (a, b) {
  return a + b;
};

Example of function declarations:

function foo() {
  // function body goes here
}

@muhammadghazali
Copy link
Author

JavaScript is especially suited for event-driven programming, because of the callback pattern, which enables your programs to work asynchronously, in other words, out of order.

@muhammadghazali
Copy link
Author

The callback is a simple and powerful pattern, which can come in handy when you’re designing a library. The code that goes into a software library should be as generic and reusable as possible, and the callbacks can help with this generalization. You don’t need to predict and implement every feature you can think of, because it will bloat the library, and most of the users will never need a big chunk of those features. Instead, you focus on core functionality and provide “hooks” in the form of callbacks, which will allow the library methods to be easily built upon, extended, and customized.

@muhammadghazali
Copy link
Author

The great things about returning functions in JavaScript is we can have a function returning another more specialized function, or it can create another function on-demand, depending on some inputs.

@muhammadghazali
Copy link
Author

Chapter 4: Immediate Functions

The immediate function pattern is a syntax that enables you to execute a function as it is defined.
Keep in mind, that the term immediate function is not defined in the ECMAScript standard.

Here is the step-by-steps to create immediate function:
define a function using a function expression

function() {
  // TODO write enough code
}

add a set of parentheses at the end

function() {
  // TODO write enough code
}()

wrap the whole function in parantheses

(function() {
  // TODO write enough code
}());

The following alternative syntax is also common (note the placement of the closing parentheses):

(function () {
  alert('watch out!');
})();

Parameters of an immediate function

How to pass an arguments to immediate functions:

(function(parameter1, parameter2){
  // TODO write enough code
}("Argument of parameter 1", "Argument of parameter 2"));

Note that in general you shouldn't pass too many parameters to an immediate function, because it could quickly become a burden to constantly scroll to the top and top the bottom of the function to understand how it works.

Returned values from immediate functions

An immediate function can return values and these return values can be assigned to variables:

var result = (function() {
  return 2 + 2;  
}());

Benefits and usage

  • it helps you wrap an amount of work you want to do without leaving any global variables behind.
  • enables you to wrap individual features into self-contained modules.

Others

  • Other names for the immediate function pattern include self-invoking or self-executing function, because the function executes itself as soon as it's defined.

@muhammadghazali
Copy link
Author

Chapter 4: Configuration objects

Use configuration object pattern to provide cleaner APIs.

An example of function without configuration objects pattern:

function addPerson(first, last) { ... }

An example of function with configuration objects pattern:

// declaration
function addPerson(conf) { ... }

// usage
addPerson({
  username: 'ghanoz',
  age: 26
});

The pros of the configuration objects pattern are:

  • No need to remember the parameters and their order
  • You can safely skip optional parameters
  • Easier to read and maintain
  • Easier to add and remove parameters

The cons of the configuration objects are:

  • You need to remember the names of the parameters
  • Property names cannot always be safely minified, especially by simpler minifiers

@muhammadghazali
Copy link
Author

Chapter 4: Summary

Useful patterns in JavaScript function:

  1. API patterns
  2. Initialization patterns
  3. Performance patterns

API patterns

These pattern help you provide better and cleaner interfaces to your functions. These patterns include:

  • Callback patterns. Pass a function as an argument
  • Configuration objects. Help keep the number of arguments to a function under control
  • Returning functions. When the return value of one function is another function
  • Currying. When new functions are created based on existing ones plus a partial list of arguments

Initialization patterns

These pattern help you perform initialization and setup tasks (very common to web pages and applications) in a clearer, structured way without polluting the global namespace with temporary variables. These patterns include:

  • Immediate functions. Execute as soon as they are defined
  • Immediate object initialization. Initialization tasks structured in an anonymous object that provides a method to be called immediately.
  • Init-time branching. Helps branch code only once during initial code execution, as opposed to many times later during the life of the application.

Performance patterns

These patterns help speed up the code. These include:

  • Memoization. Using function properties so that computed values are not computed again.
  • Self-defining functions. Overwrite themselves with new bodies to do less work from the second invocation and after.

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