Недавно изучал cmd и amd и увидел в интернете хорошую статью, посмотрю.
На ранней стадии разработки JavaScript нужно было просто реализовать простую логику взаимодействия со страницей, всего несколько слов; сейчас производительность ЦП и браузера значительно улучшена, и многие логики страницы были перенесены на клиент (проверка форм и т. д.). .), с развитием веб 2.0 С наступлением эпохи технология Ajax получила широкое распространение, интерфейсные библиотеки, такие как jQuery, появляются одна за другой, а интерфейсный код расширяется день ото дня.
В это время положение JavaScript как встроенного языка сценариев было поколеблено, но JavaScript не предоставлял никакой очевидной помощи для организации кода, даже концепции классов, не говоря уже о модулях. Чрезвычайно простой спецификации организации кода JavaScript недостаточно для управления кодом эта величина
модуль
Так как JavaScript не может справиться с таким масштабным кодом, мы можем узнать, как другие языки справляются с крупномасштабным программированием.В Java есть важное понятие - пакет.Логически связанный код организован в один и тот же пакет.Внутренний является относительно независимое королевство, так что не беспокойтесь о конфликтах имен, ну и что, если используется external? Просто импортируйте соответствующий пакет напрямую
import java.util.ArrayList;
Жаль, что JavaScript создан из соображений позиционирования и не предоставляет подобных функций.Разработчикам необходимо имитировать подобные функции, чтобы изолировать и организовать сложный код JavaScript, что мы называем модуляризацией.
Модуль — это файл, который реализует определенную функцию.С модулем мы можем более легко использовать код других людей и загружать любой модуль, который мы хотим, для любой функции, которую мы хотим. Разработка модуля должна следовать определенным спецификациям, и все идет наперекосяк.
Процесс формирования стандарта болезненный.Пионеры фронтенда начинали на этапе подсечно-огневого выращивания и питья крови, и развились до настоящего времени.Давайте вкратце рассмотрим этот неординарный процесс.
инкапсуляция функций
Когда мы говорили о функциях, мы упомянули, что функция функции состоит в том, чтобы упаковать группу операторов, которые реализуют определенную логику, а область видимости JavaScript основана на функциях, поэтому естественно использовать функции в качестве первого шага в модуляризации. Написание нескольких связанных функций в файле — это первый модуль.
function fn1(){
statement
}
function fn2(){
statement
}1234567
Таким образом, после того, как вам это понадобится, вы можете вложить его в файл, где находится функция, и вызвать функцию.
Недостаток этого подхода очевиден: он загрязняет глобальные переменные, нет гарантии отсутствия конфликтов имен переменных с другими модулями и нет связи между членами модуля.
объект
Для решения вышеуказанных проблем появился метод записи объектов, и все члены модуля могут быть инкапсулированы в объект.
var myModule = {
var1: 1,
var2: 2,
fn1: function(){
},
fn2: function(){
}
}12345678910111213
Таким образом, мы обращаемся к соответствующему файлу, когда хотим вызвать модуль, а затем
myModule.fn2();
Это позволяет избежать загрязнения переменных, если имя модуля уникально, а элементы в одном модуле также связаны между собой.
Вроде неплохое решение, но и у него есть недостатки, внешние элементы можно модифицировать по желанию
myModel.var1 = 100;
Это создает неожиданные проблемы с безопасностью
выполнить функцию немедленно
Цель сокрытия деталей может быть достигнута путем немедленного выполнения функции.
var myModule = (function(){
var var1 = 1;
var var2 = 2;
function fn1(){
}
function fn2(){
}
return {
fn1: fn1,
fn2: fn2
};
})();1234567891011121314151617
Таким образом, переменные и функции, которые мы не представили, не могут быть изменены вне модуля.
Вышеприведенный подход является основой нашей модульности.В настоящее время существует две общие спецификации модулей JavaScript: CommonJS и AMD.
CommonJS
Начнем с CommonJS, потому что модульного программирования на веб-стороне нет, а логика страничного JavaScript сложная, но она все еще может работать, но на стороне сервера должны быть модули, поэтому, хотя JavaScript разработан на веб-стороне для Столько лет первая популярная модульная спецификация JavaScript представлена серверным приложением JavaScript, а спецификация CommonJS перенесена NodeJS, что означает, что модульное программирование JavaScript официально вступило в стадию.
1. Определите модуль
Согласно спецификации CommonJS, один файл является модулем. Каждый модуль представляет собой отдельную область, то есть переменные, определенные в модуле, не могут быть прочитаны другими модулями, если они не определены как свойства глобального объекта.
2. Выход модуля:
Модуль имеет только один экспорт, объект module.exports, нам нужно поместить контент, который модуль хочет вывести в этот объект
3. Загрузите модуль:
Загрузка модуля использует метод require, который считывает файл и выполняет его, возвращая объект module.exports внутри файла.
посмотреть пример
//模块定义 myModel.js
var name = 'Byron';
function printName(){
console.log(name);
}
function printFullName(firstName){
console.log(firstName + name);
}
module.exports = {
printName: printName,
printFullName: printFullName
}
//加载模块
var nameModule = require('./myModel.js');
nameModule.printName();12345678910111213141516171819202122
В разных реализациях разные требования к пути require.В общем, расширение js можно не указывать, можно использовать относительный или абсолютный путь, а имя модуля можно использовать даже без пути (при условии, что модуль является встроенный модуль системы)
неудобный браузер
Если вы внимательно посмотрите на приведенный выше код, вы обнаружите, что требование является синхронным. Система модулей должна синхронно считывать содержимое файла модуля, а также компилировать и выполнять его, чтобы получить интерфейс модуля.
Это просто и естественно реализовать на стороне сервера, однако на стороне браузера возникает много проблем.
Со стороны браузера лучший и самый простой способ загрузить JavaScript — вставить в документ тег скрипта. Однако теги script по своей природе асинхронны, и традиционные модули CommonJS не могут быть правильно загружены в среде браузера.
Одно из решений — разработать компонент на стороне сервера, выполнить статический анализ кода модуля и вернуть модуль в браузер со списком зависимостей. Это прекрасно работает, но требует установки на сервер дополнительных компонентов и, следовательно, ряда корректировок базовой архитектуры.
Другим решением является использование набора стандартных шаблонов для инкапсуляции определения модуля, но существуют различия в том, как следует определять и загружать модуль:
AMD
AMD означает определение асинхронного модуля, а китайское название означает определение асинхронного модуля. Это спецификация для модульной разработки на стороне браузера.
Поскольку он изначально не поддерживается JavaScript, использование спецификации AMD для разработки страниц требует использования соответствующей библиотечной функции, которая является хорошо известной RequireJS, Фактически, AMD является стандартизированным выходом RequireJS в процессе продвижения определений модулей. .
requireJS в основном решает две проблемы
1. Несколько файлов js могут иметь зависимости, и зависимые файлы должны быть загружены в браузер раньше, чем файлы, которые зависят от него.
2. При загрузке js браузер останавливает отрисовку страницы, чем больше загружено файлов, тем дольше страница теряет время отклика.
См. пример использования requireJS
// 定义模块 myModule.js
define(['dependency'], function(){
var name = 'Byron';
function printName(){
console.log(name);
}
return {
printName: printName
};
});
// 加载模块
require(['myModule'], function (my){
my.printName();
});12345678910111213141516
грамматика
requireJS определяет функцию define, которая представляет собой глобальную переменную, используемую для определения модулей.
define(id?, dependencies?, factory);
- id: необязательный параметр, используемый для определения идентификатора модуля, если этот параметр не указан, имя файла скрипта (убрать расширение)
- зависимости: это массив имен модулей, от которых зависит текущий модуль.
- factory: фабричный метод, модуль инициализирует функцию или объект для выполнения. Если это функция, она должна выполняться только один раз. Если объект, этот объект должен быть выходным значением модуля
Загрузите модуль, используя функцию require на странице
require([dependencies], function(){});
Функция require() принимает два параметра
- Первый параметр — это массив, представляющий модули, от которых он зависит.
- Второй параметр — это функция обратного вызова, которая будет вызываться после успешной загрузки указанных выше модулей. Загруженные модули будут переданы функции в качестве параметров, чтобы их можно было использовать внутри функции обратного вызова.
Функция require() загружается асинхронно при загрузке зависимых функций, поэтому браузер не потеряет ответ.Указанная ею функция обратного вызова запустится только после успешной загрузки предыдущих модулей, что решает проблему зависимостей.
CMD
CMD — это общее определение модуля. есть различия во времени загрузки (так сказать, запуска, парсинга)
грамматика
Sea.js использует один модуль и один файл и следует единому методу написания.
define(id?, deps?, factory)
Потому что CMD уважает
- Один файл — это один модуль, поэтому имя файла часто используется в качестве идентификатора модуля.
- CMD соблюдает близость зависимостей, поэтому вообще пишите зависимости не в параметрах define, а в фабрике
factory - это функция с тремя параметрами: function(require, exports, module)
- require — это метод, который принимает идентификатор модуля в качестве единственного параметра для получения интерфейса, предоставляемого другими модулями: require(id)
- exports — это объект, используемый для предоставления интерфейсов модуля внешнему миру.
- модуль — это объект, в котором хранятся некоторые свойства и методы, связанные с текущим модулем.
См. пример:
// 定义模块 myModule.js
define(function(require, exports, module) {
var $ = require('jquery.js')
$('div').addClass('active');
});
// 加载模块
seajs.use(['myModule.js'], function(my){
});12345678910
Разница между AMD и CMD
В Интернете можно найти кучу статей о разнице между ними, кратко резюмируя
Наиболее очевидная разница заключается в том, что зависимости обрабатываются по-разному во время определения модуля.
1. AMD учитывает предварительную зависимость и объявляет модули, от которых она зависит, при определении модулей.
2. CMD учитывает ближайшие зависимости и требует только при использовании модуля.
Это различие имеет свои преимущества и недостатки, но это всего лишь грамматический пробел, и оба языка, requireJS и SeaJS, поддерживают написание друг друга.
Самая большая разница между AMD и CMD заключается в том, что время выполнения зависимых модулей отличается.Обратите внимание, что это не время или метод загрузки.
Многие говорят, что requireJS — это модуль асинхронной загрузки, а SeaJS — модуль синхронной загрузки.Это понимание на самом деле неточное.На самом деле модули загрузки асинхронные, но AMD полагается на фронт.js может легко узнать, кто является зависимым модулем. и загрузите его немедленно. И CMD близок к зависимости, вам нужно использовать модуль для преобразования модуля в строку, чтобы проанализировать его, чтобы узнать, какие модули зависимы.Это также момент, за который многие люди критикуют CMD, жертвуя производительностью чтобы обеспечить удобство разработки, на самом деле требуется короткое время для анализа модуля, который будет проигнорирован
Почему мы говорим, что разница между ними заключается в том, что время выполнения зависимых модулей различно, и почему многие люди думают, что ADM является асинхронным, а CMD — синхронным (за исключением названия...)
Модули также загружаются асинхронно. AMD выполнит модуль изменения после завершения загрузки модуля. После того, как все модули будут загружены и выполнены, они войдут в функцию обратного вызова, требующую выполнения основной логики. Этот эффект заключается в том, что порядок выполнения и порядок записи зависимых модулей разный, он должен быть последовательным, в зависимости от скорости сети, какой из них загружается первым, а какой выполняется первым, но основная логика должна выполняться после загрузки всех зависимостей.
После того, как CMD загружает зависимый модуль, он не выполняет его, а просто загружает.После того, как все зависимые модули загружены, он входит в основную логику и выполняет соответствующий модуль только тогда, когда встречает запрос, так что порядок выполнения модулей точно такой же, как и порядок записи.
Это также причина, по которой многие люди говорят, что у AMD хороший пользовательский интерфейс, потому что нет задержки, зависимые модули выполняются заранее, а производительность CMD хорошая, потому что она выполняется только тогда, когда это нужно пользователю.