The biggest improvement of this version introduces a powerful debugging mechanism. If a framework is loaded with modules, debugging is the biggest problem. Because of the modularization, you do not need to worry about the volume. Therefore, the JS file is skyrocketing and the number of APIS is soaring, just like jquery, some of the APIs are not completely remembered, let alone Ext, Yui, and dojo. We can check whether this method is in module A or Module B during the call. However, when an error occurs, it may not be in module A or Module B, module A may also depend on Module C and Module D, and Module D may also depend on it. In this way, it is difficult for us to trace back to the source of the error. In particular, if this JS file is dynamically loaded and deleted, you cannot even find firebug! Therefore, it is imperative to strengthen the debugging mechanism, which is also the biggest highlight of the current version!
Other improvements in this version:
- Upgrade the uuid system to share a counter when multiple versions coexist on the page.
- The _ checkfail method is simplified. If a dead link occurs, print the module name directly, and no longer put it into the error stack.
- Deferred queues are simplified to ensure unified first-in-first-out.
- The $. Mix method is improved to allow only one parameter to be added directly to the $ namespace.
- The internal method assemble is renamed as setup, and the debugging mechanism is enhanced. Each time a new module is added,
All the methods in the namespace and prototype will be traversed, overwritten, And the try catch logic will be added.
Now let's go back to the topic of enhancing the debugging mechanism.
In the require method of the mass framework seed moduleCode:
If (DN = cn) {// If (token &&! (Token in transfer) {mapper [token]. state = 2 // If the merge method is used, the module runs into this branch (only once) Return transfer [token] = setup (callback, argS, token );} else if (! Token) {// a normal callback can execute countless return setup (callback, argS, token );}}
If a JS file does not have a dead link, the corresponding module will definitely enter the setup method. The setup method has three parameters: the first module name and a string. The second is its dependency list, a string array. The last one is the function, which can be the module itself or the user's callback. The situation is exactly the same as the $. Define method. The difference is that this module may have been modified and the folder name is added.
// Collect the returned values of the corresponding modules in the dependency list. input the values of function setup (name, deps, FN) {for (VAR I = 0, argv = [], D; D = deps [I ++];) {argv. push (Transfer [d]);} var ret = fn. apply (global, argv); if ($ ["@ debug"]) {// If you enable the debugging mechanism for (I in $) {debug ($, I, name) ;}for (I in $. FN) {debug ($. FN, I, name, 1) ;}} return ret ;}
The usage of setup has been clearly stated in the comment. Execute the module itself to add new methods or attributes for the namespace and mass prototype. For example, the Lang module is not dependent on itself (especially in a standard browser, the lang_fix module is added to IE). After the module function is executed, the $ namespace will have more isplainobject, isnative, isemptyobject, isarraylike, format, Tag, quote, dump, parsejs, parsejson, parsexml, each, MAP, isfunction, isarray, and Lang. The $. Lang method is returned. It is added to the internal transfer object and the key name is the corresponding module. Therefore, you can see that the setup method has a statement such as transfer [D.
If you have enabled the debugging mechanism (enabled by default), it will rewrite the method that is added to the module, which is completed by another internal method.
VaR rdebug =/^ (init | constructor | Lang | query) $ | ^ is/function debug (OBJ, name, module, p) {var fn = OBJ [name]; if (typeof fn = "function "&&! FN ["@ debug"]) {If (rdebug. test (name) {fn ["@ debug"] = Name;} else {VaR method = OBJ [name] = function () {try {return method ["@ debug"]. apply (this, arguments)} catch (e) {$. log ("[[" + module + ":" + (P? "$. FN. ":" $. ") + name +"] Gone Wrong "); $. log (E); throw e ;}for (var I In Fn) {method [I] = FN [I] ;}method ["@ debug"] = FN; method. tostring = function () {return fn. tostring ()} method. valueof = function () {return fn. valueof ();}}}}
The purpose of this method is to override the original method, but to save performance, instead of using curry, it is to put the original method on an attribute named "@ debug" of the new method, use try catch to call it with caution. If an error occurs, print the prepared debugging message. To prevent this method from manually adding various custom attributes, We need to forward these private attributes for in to the new method. However, for in has a bug in ie678, so you need to handle the valueof and tostring methods separately. In addition, some core methods and methods with abnormal calls will not be overwritten, such as isxxx series, init constructor, query selector, Lang language chain ...... Basically, they all have powerful enough code defense, so you don't need to do it any more!
After talking about so many theories, let's look at the actual results. For example, if we want to call the format method of the Lang module, there are two parameter passing methods, But no matter which one is, the first parameter is always a string!
$. Require ("Ready, Lang", function () {var A = $. format ("result is # {0}, # {1}",); alert (a); // "result is "})
However, if you mistakenly upload an array, an error will be reported immediately and the following will be displayed in each browser (this is the case where debugging is not enabled)
$. Require ("Ready, Lang", function () {$. Format ([]);})
In addition to opera, debugging messages of other browsers are useless. Now there is only one line of code. Of course we guess there is a problem with the format. If there are a few more lines, it will be miserable.
Let's take a look at the debugging mechanism, which is more useful than the original one.
@ Lang indicates the module where it is located. According to the file name of the mass framework and the module name, it is difficult to know that it is Lang. JS file error. If it is @ more/AAA, It is AAA under the more directory. JS file error. $. Format is the name of the method with which the error occurred. This is found immediately by using ide. Then, the cause should be quickly found based on the original browser message and method source code.
// Load the mass framework module, create elements, insert elements, and bind events $. require ("Ready, event", function () {$ ("body "). append ("<div> new node </div> "). on ("click", "Div", function () {alert (this. innerhtml )})})
Basically, the source code is put on GitHub. You are welcome to try it out.