1. Naming conflicts

Start with a simple habit.

As I have been doing JavaEE development before, I have been used to abstract out some general functions in the project and form independent functions one by one in JavaScript development to facilitate code reuse, such as:

Function CSS (Element, attr) {// Get the CSS property of the element attr

// …

}

Function offset(element) {// Get the position coordinates of the element in the document

// …

}

And put these wrapped functions in a unified tools.js file.

If the page function implementation needs to use these functions, they can be introduced directly with <script SRC =”tools.js”></script>.

At the beginning, everything felt good, and everyone felt it was very convenient to write such a tool file for development, until the use of more and more, more and more complex page functions, people to achieve more and more diverse requirements.


In tools.js, if you want to define a function that can set the value of CSS properties, you have to use another function name (setCss) instead of the CSS function name. Similarly, if you want to set the position of an element in the entire document, You can no longer use the function name offset because that would conflict with the function name defined in the tools.js file.

Now that the problem has arisen, it needs to be solved.


A very useful technique in Java, package, organizes logically related code together for management using “packages,” the equivalent of folders in a file system. In a file system, a folder is a relatively independent space. There is no need to worry about file name conflicts between one folder and another folder. The same goes for “packages”, where file naming conflicts can be resolved. If you want to reuse the resources inside the package outside the package, you can import the relevant package directly through import. Concepts such as packages are also called namespaces in other languages such as C#.

There is no native package or namespace support in JavaScript, but other methods (objects, closures) can be used to achieve similar effects.


Taking a page from Java, I use objects in JavaScript to modify tools.js files simply:

var Util = {

css : function(element, attr) {

// …

},

offset : function(element) {

// …

}

};

Thus, when the tools.js file is imported, the CSS style or document coordinates of the element are retrieved using methods like util.css ()/ util.offset (). CSS and offset are scoped under the Util object. CSS properties defined globally or in new objects are not affected.

Util the name Util is also universal and is usually used for auxiliary tool definition. For uniqueness of this name, we can continue to refer to the naming convention of package in Java (domain name inversion) :

var com = {};

com.github = {};

com.github.itrainhub = {};

com.github.itrainhub.Util = {

css : function(element, attr) {

// …

},

offset : function(element) {

// …

}

};

To get the CSS style value, can use com. Making. Itrainhub. Util. CSS () method. But such writing method increases the difficulty of memorizing, YUI has a better solution to this point, first press the table.

Naming conflicts can be resolved using the way the object is written, but it also exposes all the members of the object, allowing the internal state of the object to be overwritten outside the object. For example, there is a counter inside an object:

var Util = {

_count : 0

}

Outside the object you can call Util._count = 18; It is not safe to modify the value of this counter.

A variable such as a counter, which may normally exist as a private member of an object and do not want to continue modifying its value outside the object, can be designed using IIFE (execute functions now) :

var Util = (function(){

var _count = 0;

function _css(element, attr) {

// …

}

function _offset(element) {

// …

}

return {

css : _css,

offset : _offset

}

}) ();

Thus, the value of _count can no longer be changed directly externally.

We can breathe a sigh of relief that namespaces do solve the problem of naming conflicts.


2. File dependency

Tools.js continued development.

Based on Tools.js, you can develop common COMPONENTS at the UI level, such as magnifying glasses and carousels, so that you don’t have to reinvent the wheel to use these features in various projects.

Normally, each UI component is stored in a separate JS file, such as a magnifying glass, which can be placed in a zoom.js file. When using the magnifying glass component, use <script SRC =”zoom.js”></script> to import it.

<script src=”tools.js”></script>

<script src=”zoom.js”></script>

<script>

ZoomIn (/* Passing in configuration information for the magnifying glass effect */);

</script>

But many times, if you forget to introduce tools.js before using zoom.js, you will get an error when using zoom.js, and you can’t guarantee its normal execution.

The normal execution of zoom.js depends on the use of tools.js, and the above problems are relatively easy to solve. However, as the team grows larger and business requirements become more and more complex, the dependency between components in the project will become more and more complicated. Such as:

One day, I expanded the zoom.js component, but in addition to tools.js, I also used another tools.js component: helper.js. If THERE are N places in the project that used the zoom.js component before, I have to search globally for every reference to zoom.js, plus references to helper.js.

Think again, as the project progresses, we’ll continue to modify tools.js, adding more components component_1.js, Component_2.js… Some components use only tools.js, some use only helper.js, and some components use both tools.js and helper.js. So about the maintenance of dependencies between components, the workload can be imagined, if the human way to ensure the maintenance of dependencies, it is about to collapse.

The reason why maintaining dependencies between components is so hard is because JavaScript inherently lacks the syntax to import other JS files. In Java, dependency components can be imported through import, and CSS has the @import command to import other CSS files. Js does not manage dependencies automatically.

In addition to the dependent relationships between file maintenance inconvenience, if the component is very much, introduced in the page, we have to ensure that the path of the reference component and the order can’t go wrong, once the error, and it takes time to find the mistake, it is conceivable that it is very significant work, plus component is introduced, and synchronously load components, browser may also lead to the phenomenon of suspended animation.

To address these issues, modular development is valuable.


3. Modular development

3.1 modular

The so-called modularization, is to put a relatively independent function, separate form a file, can input specified dependence, output specified function, for the outside world to call, other internal hidden implementation details. This makes it easy for different projects to reuse without causing additional impact on the project.

The main functions of using modular front-end load transmitter are:

• Load JS asynchronously to avoid browser death

• Manage dependencies between modules for easy maintenance

Modules make it easier to use other people’s code and load whatever functionality you want.

But to use the premise of the module, it is necessary to form a development specification that can be followed, so that developers and users have the data to find, otherwise you have your writing method, I have my writing method, we can not be unified, it can not be very good mutual use.

The current common specification is that the server uses the CommonJS specification and the client uses the AMD/CMD specification.


3.2 CommonJS

Node.js is the implementation of the CommonJS specification, which emerged in 2009. The CommonJS specification loads modules like this:

var gulp = require(“gulp”);

Gulp. Task (task / * * /);

Module loading is synchronous, this writing method is suitable for the server side, because the modules read in the server are in the local disk, the loading speed is very fast, can be synchronized to complete loading. However, in the client browser, because modules are placed on the server side, module loading depends on the network environment. Loading modules in a synchronous manner may cause “false death”.

Today I’m going to focus on programming for the browser, not node.js, so I won’t go into the CommonJS specification here, except that require() is used to load modules.


3.3 AMD

Because in the browser side, the module using synchronous loading mode may appear false death, so we use asynchronous loading mode to achieve module loading, which is the birth of AMD specifications.

AMD is an Asynchronous Module Definition. AMD specification: https://github.com/amdjs/amdjs-api/wiki/AMD.

AMD uses asynchronous mode to load the module, the module load does not affect its subsequent statement run. All statements that depend on the loaded module are defined in a callback function that is not executed until the module is loaded.

AMD also uses require() to load modules.

require([module], callback);

Module is an array parameter that represents the name of the loaded module; Callback is a callback function parameter that is executed after all modules are loaded. Such as:

require([“jquery”], function($){

$(“#box”).text(“test”);

});


3.4 CMD

CMD stands for Common Module Definition. CMD specification: https://github.com/cmdjs/specification/blob/master/draft/module.md.

CMD specification defines the basic writing format and basic interaction rules of modules, which is developed in China and standardized by Yubo in the process of promoting SeaJS.

SeaJS implements the CMD specification. SeaJS addresses the same problems as RequireJS, but differs in how modules are defined and when modules are loaded (run, parsed).


3.5 Differences between AMD and CMD

AMD is the canonical output of RequireJS’s module definition in its promotion process.

CMD is the normalized output of SeaJS module definitions during the roll-out process.



The main differences are as follows:

1. For dependent modules, AMD executes in advance and CMD executes late.

2.CMD advocates relying on nearby, AMD advocates relying on front.

3.AMD API default is a when multiple use, CMD API strictly differentiated, advocating a single responsibility.


Of course, there are some other details, depending on the definition of the specification.


You can also refer to https://www.zhihu.com/question/20351507/answer/14859415 or https://www.zhihu.com/question/20342350 to see jade “for AMD and CMD Different insights.