這篇文章帶給大家的內容是關於javascrip中UMD規範的詳細介紹(附程式碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
網址:https://github.com/umdjs/umd
UMD規範,就是所有規範裡長得最醜的那個,沒有之一! ! !它是為了讓模組同時相容於AMD和CommonJs規範而出現的,多被一些需要同時支援瀏覽器端和服務端引用的第三方函式庫所使用。 UMD是一個時代的產物,當各種環境最終實現ES harmony的統一的規範後,它也將退出歷史舞台。
UMD規範的結構乍看之下非常複雜,主要是因為想要看懂這段範式需要一些javascript基礎知識,它的基本結構是這樣的:
(function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD define(['jquery', 'underscore'], factory); } else if (typeof exports === 'object') { // Node, CommonJS之类的 module.exports = factory(require('jquery'), require('underscore')); } else { // 浏览器全局变量(root 即 window) root.returnExports = factory(root.jQuery, root._); } }(this, function ($, _) { // 方法 function a(){}; // 私有方法,因为它没被返回 (见下面) function b(){}; // 公共方法,因为被返回了 function c(){}; // 公共方法,因为被返回了 // 暴露公共方法 return { b: b, c: c } }));
先來看最外層的結構:
(function (){}());
很簡單,就是一個自執行函數。既然它是一個模組化的標準,也意味著這個自執行函數最終可以導出一個模組,那麼從程式碼的角度來講其實有兩種常見的實作方式:
return回傳一個模組;
實參傳入一個對象,把函數內部產生好的需要導出的東西掛在這個物件的屬性上;
可以看到上面的函數體內部是沒有return語句的,那麼可以猜測UMD在實作時是採用了第二種方式。既然UMD是一種模組化的規範,那麼它的功能就是根據使用要求生產模組,也就是說它的職責定位叫做模組工廠,我們可以定義一個factory方法,每當執行該方法時,就回返回一個模組,所以它的基本結構就變成瞭如下的樣子:
(function (factory){ //假设没有使用任何模块化方案,那么将工厂函数执行后返回的内容直接挂载到全局 window.Some_Attr = factory(); }(function(){ //自定义模块主体的内容 /* var a,b,c function a1(){} function b1(){} function c1(){} return { a:a1, b:b1 } */ }))
#也就是說我們自訂一個匿名函數,然後把它當做實參傳給了自執行函數,然後在自執行函數內部透過形參來存取這個工廠方法(或者你會更熟悉回呼函數或callback這樣的叫法),把它簡單地掛在到全域物件上,這樣就完成了基本的模組導出。
有的時候我們也希望可以將模組掛載到非全局的環境,將掛載物件動態傳入可以讓程式碼變得更靈活,這裡涉及到一個基礎知識,就是瀏覽器環境中的全域物件擁有parent,top,self三個屬性來追蹤頁面中嵌入d5ba1642137c3f32f4f4493ae923989c後引入的新的Window物件的,單頁面Window.self是指向自己的,程式碼中常透過是否包含self屬性來鑑別全域對象,所以此處的寫法可以改進為相容:
(function(root,factory){ root.Some_Attr = factory(); }(self !== undefined ? self : this, function(){ }));
接著我們先來加入AMD的規範的適配,規範位址:AMD規範github位址:
/* * AMD规范的模块定义格式是define(id?, dependencies?, factory),factory就是实际的模块内容 */ (function (factory){ //判断全局环境是否支持AMD标准 if(typeof define === 'function' && define.amd){ //定义一个AMD模块 define([/*denpendencies*/],factory); } }(function(/*formal parameters*/){ //自定义模块主体的内容 /* var a,b,c function a1(){} function b1(){} function c1(){} return { a:a1, b:b1 } */ }))
接著我們先來加入CommonJs
的規範的適配:
/* * CommonJs规范使用require('moduleName')的格式来引用模块,使用module.exports对象输出模块,所以只要把模块的输出内容挂载到module.exports上就完成了模块定义。 */ (function (factory){ //判断全局环境是否支持CommonJs标准 if(typeof exports === 'object' && typeof define !== 'function'){ module.exports = factory(/*require(moduleA), require(moduleB)*/); } }(function(/*formal parameters*/){ //自定义模块主体的内容 /* var a,b,c function a1(){} function b1(){} function c1(){} return { a:a1, b:b1 } */ }))
加入對CommonJs
的適配後,函數主體中return的內容(一般是一個物件)就被掛載到了module.exports
上,如果你寫過node.js
程式碼,對此一定不會陌生。
把上面的片段揉到一塊,你也就看懂UMD
的樣子了。
UMD在其github主頁上提供了更具針對性的範式,適用於不同的場景,感興趣的讀者可以自行查看(地址在第一節已經給出)。
在此貼一個可能對大多數開發者比較有用的jqueryPlugin的開發範式,如果看懂了上面的分析,那麼下面的程式碼應該不難看懂:
// Uses CommonJS, AMD or browser globals to create a jQuery plugin. (function (factory) { if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['jquery'], factory); } else if (typeof module === 'object' && module.exports) { // Node/CommonJS module.exports = function( root, jQuery ) { if ( jQuery === undefined ) { // require('jQuery') returns a factory that requires window to // build a jQuery instance, we normalize how we use modules // that require this pattern but the window provided is a noop // if it's defined (how jquery works) if ( typeof window !== 'undefined' ) { jQuery = require('jquery'); } else { jQuery = require('jquery')(root); } } factory(jQuery); return jQuery; }; } else { // Browser globals factory(jQuery); } }(function ($) { $.fn.jqueryPlugin = function () { return true; }; }));
前端模組化本身是一個稍微混亂的話題,筆者自己最初也是require( )和require.js傻傻分不清楚,但模組化是前端開發中非常重要的課題,如果你不想一輩子只是在一個頁面內寫代碼,這一關是一定要過的,有興趣的讀者可以按照下面的基本類別劃分分塊進行學習。
以上是javascrip中UMD規範的詳細介紹(附程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!