Xiao A is a front-end engineer of a certain entrepreneurial team, responsible for writing project Javascript programs.
Global variable conflict
According to his own experience, Xiao A first extracted some commonly used functions and wrote them into functions and put them in a public file base.js:
The code copy is as follows:
var _ = {
$: function(id) { return document.getElementById(id); },
getCookie: function(key) { ... },
setCookie: function(key, value) { ... }
};
Xiao A puts these functions in the _ object to prevent too many global variables from causing conflicts. He told the rest of the team that if anyone wants to use these functions, just introduce base.js.
Xiao C is Xiao A's colleague. He told Xiao A: his page has introduced a class library called underscore.js, and this class library will also occupy this global variable, which will conflict with the "base.js". Xiao A thought to himself that underscore.js is a third-party library and it is probably difficult to modify, but base.js has been spread out on many pages and it is impossible to modify it. In the end, Xiao A had no choice but to change the global variable occupied by underscore.js.
At this time, Xiao A found that putting functions in a namespace can reduce the probability of global variable conflicts, but it does not solve the problem of global variable conflicts.
rely
With the development of the business, Xiao A has written a series of function libraries and UI components, such as tag switching component tabs.js, which requires calling functions in base.js and util.js.
One day, the new colleague Xiao D and Xiao A reported that he had quoted tabs.js on the page, but the function was not normal. Xiao A found the problem at a glance. It turned out that Xiao D didn't know that tabs.js relied on base.js and util.js, so he did not add references to these two files. So he immediately made changes:
The code copy is as follows:
<script src="tabs.js"></script>
<script src="base.js"></script>
<script src="util.js"></script>
However, the function is still abnormal. At this time, Xiao A taught Xiao D a lesson: "Everyone said it is a dependency, so the dependent party must be placed before the dependent party." It turns out that Xiao D put base.js and util.js after tabs.js.
Xiao A thought to himself that he is the author and naturally knows the dependence of components, but it is hard for others to say, especially newcomers.
After a while, Xiao A added functions to the tag switching component. In order to implement this function, tabs.js also needs to call functions in ui.js. At this time, Xiao A discovered a serious problem. He needed to add ui.js references to all pages that called tabs.js! ! !
After a while, Xiao A optimized tabs.js, and this component no longer relies on util.js, so he removed the references to util.js from all pages that use tabs.js to improve performance. Something big happened to him when he made the modification. The MM in the test team told him that some pages were abnormal. When Xiao A saw it, he suddenly realized that other functions of some pages used functions in util.js. He removed the reference to this file and caused an error. In order to ensure the function is normal, he restored the code again.
Xiao A thought again, is there a way to modify the dependencies without modifying the page one by one, and does not affect other functions?
Modular
When Xiao A was shopping in the Internet, he accidentally discovered a novel modular encoding method that can solve all the problems it encountered before.
In modular programming, each file is a module. Each module is created by a function called define. For example, after transforming base.js into a module, the code will become like this:
The code copy is as follows:
define(function(require, exports, module) {
exports.$ = function(id) { return document.getElementById(id); };
exports.getCookie = function(key) { ... };
exports.setCookie = function(key, value) { ... };
});
All interfaces provided by base.js are added to the exports object. exports is a local variable, and the code of the entire module does not occupy half of the global variable.
So how do you call the interface provided by a certain module? Take tabs.js as an example, it depends on base.js and util.js:
The code copy is as follows:
define(function(require, exports, module) {
var _ = require('base.js'), util = require('util.js');
var div_tabs = _.$('tabs');
// .... Other codes
});
A module can obtain the interfaces of other modules through the local function require. At this time, the variables _ and util are both local variables, and the variable name is completely controlled by the developer. If you don't like _, you can also use base:
The code copy is as follows:
define(function(require, exports, module) {
var base = require('base.js'), util = require('util.js');
var div_tabs = base.$('tabs');
// .... Other codes
});
Once you want to remove util.js and add ui.js, just modify tabs.js:
The code copy is as follows:
define(function(require, exports, module) {
var base = require('base.js'), ui = require('ui.js');
var div_tabs = base.$('tabs');
// .... Other codes
});
Loader
Due to the lack of native browser support, if we want to encode in a modular way, we must rely on something called a loader.
Currently, there are many implementations of loaders, such as require.js and seajs. The JRaiser class library also has its own loader.