Home  >  Article  >  Web Front-end  >  JavaScript design pattern singleton pattern example_javascript skills

JavaScript design pattern singleton pattern example_javascript skills

WBOY
WBOYOriginal
2016-05-16 16:35:391033browse

Peter Seibel, author of "Practical Common Lisp" once said, if you need a pattern, something is wrong. The problem he refers to is that because of the inherent flaws of language, he has to find and summarize a universal solution.

Whether it is weakly typed or strongly typed, static or dynamic language, imperative or declarative language, every language has its inherent advantages and disadvantages. A Jamaican athlete has some advantages in sprinting and even boxing, but lacks in practicing yoga.

Warlock and Shadow Priest can easily become an excellent support, but an enemy Mage flying around the map with Macon on his back will be slightly awkward. Switching to a program, it may take a lot of effort to implement decorators in static languages, but since js can throw methods on objects at any time, the decorator pattern has become useless in js.

There are relatively few books that talk about JavaScript design patterns. "Pro javaScript Design Patterns" is a classic one, but the examples in it are quite verbose, so I combined them with the codes I have written at work. Understand and summarize. If there is any deviation in my understanding, please feel free to correct me.

1. Singleton mode

The definition of singleton pattern is to produce a unique instance of a class, but js itself is a "classless" language. Many articles that talk about js design patterns use {} as a singleton, which barely makes sense. Because there are many ways to generate objects in js, let's take a look at another more meaningful singleton.

There is such a common requirement. When a button is clicked, a mask layer needs to pop up on the page. For example, when you click to log in on web.qq.com.

This code to generate a gray background mask layer is very easy to write.

Copy code The code is as follows:

var createMask = function(){
return document,body.appendChild( document.createElement(div) );
}
$( ‘button’ ).click( function(){
Var mask = createMask();
mask.show();
})

The problem is that this mask layer is globally unique, so every time createMask is called, a new div will be created. Although you can remove it when hiding the mask layer, this is obviously unreasonable.

Let’s look at the second option. Create this div at the beginning of the page. Then use a variable to reference it.

Copy code The code is as follows:

var mask = document.body.appendChild( document.createElement( ”div' ) );
$( ”button' ).click( function(){
mask.show();
} )

In this way, only one mask layer div will be created on the page, but another problem will follow. Maybe we will never need this mask layer, which will waste another div, and any operation on the DOM node will Should be very stingy.

What if you can use a variable to determine whether the div has been created?

Copy code The code is as follows:

var mask;
var createMask = function(){
if (mask) return mask;
else{
mask = document,body.appendChild( document.createElement(div) );
return mask;
}
}

It looks good. Here we have indeed completed a function that generates a single column object. Let’s take a closer look at what’s wrong with this code.

First of all, this function has certain side effects. The reference to the external variable mask is changed within the function body. In a multi-person collaboration project, createMask is an unsafe function. On the other hand, the global variable mask is not absolutely necessary. . Let’s improve it again.

Copy code The code is as follows:

var createMask = function(){
var mask;
return function(){
return mask || ( mask = document.body.appendChild( document.createElement('div') ) )
}
}()

A simple closure is used to wrap the variable mask, at least for the createMask function, it is closed.

You may see this and feel that the singleton pattern is too simple. Indeed, some design patterns are very simple. Even if you have never paid attention to the concept of design patterns, you still use some of them unknowingly in your daily code. Design pattern. Just like many years ago when I understood what the old man’s stroller was, I also thought about it. It turns out that this is the old man’s stroller.

The 23 design patterns in GOF are also patterns that have long existed and been used repeatedly in software development. If the programmer does not clearly realize that he has used certain patterns, then he may miss a more suitable design next time (This passage comes from "Yukihiro Matsumoto's Programming World").

Back to the topic, the previous singleton still has shortcomings. It can only be used to create mask layers. What if I need to write a function to create a unique xhr object? Can I find a universal singleton? Wrapper.

Functions in js are of the first type, which means that functions can also be passed as parameters. Take a look at the final code.

Copy code The code is as follows:

var singleton = function( fn ){
var result;
return function(){
return result || ( result = fn .apply( this, arguments ) );
}
}
var createMask = singleton( function(){
return document.body.appendChild( document.createElement('div') );
})

Use a variable to save the first return value. If it has already been assigned, the variable will be returned first in subsequent calls. The code that actually creates the mask layer is passed to the singleton through the callback function. In the wrapper. This method is actually called bridge mode. Regarding bridge mode, I will talk about it a little later.

However, the singleton function is not perfect. It still needs a variable result to store the reference of the div. Unfortunately, the functional characteristics of js are not enough to completely eliminate declarations and statements.

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn