В процессе разработки часто используется Node.js, который использует возможности V8 для расширения возможностей JS. В Node.js мы можем использовать модуль пути, которого нет в JS. Чтобы лучше познакомиться с приложением, давайте взглянем на него ~
Версия этой статьи для Node.js — 16.14.0. , а исходный код этой статьи взят отсюда Версия. Я надеюсь, что после прочтения этой статьи всем будет полезно прочитать исходный код.
используется для обработки путей к файлам и каталогам. Этот модуль предоставляет некоторые функции инструментов, которые удобно разрабатывать разработчикам, чтобы помочь нам в принятии сложных решений о пути и повышении эффективности разработки. Например:
Настройте псевдонимы в проекте. Конфигурация псевдонима облегчает нам обращение к файлам и позволяет избежать пошагового поиска вверх.
перелюбить: { псевдоним: { // __dirname путь к каталогу 'src', в котором находится текущий файл: path.resolve(__dirname, './src'), // текущий рабочий каталог процесса.cwd '@': path.join(process.cwd(), 'src'), }, }
В веб-пакете выходной путь файла также может быть сгенерирован в указанное место с помощью нашей собственной конфигурации.
модуль.экспорт = { запись: './path/to/my/entry/file.js', выход: { путь: path.resolve(__dirname, 'dist'), имя файла: 'my-first-webpack.bundle.js', }, }
Или для операций с папками
пусть fs = require("fs"); пусть путь = требуется («путь»); // Удалить папку let deleDir = (src) => { // Читаем папку let Children = fs.readdirSync(src); Children.forEach(item => { пусть childpath = path.join(src, item); // Проверяем, существует ли файл let file = fs.statSync(childpath).isFile(); если (файл) { // Удаляем файл, если он существует fs.unlinkSync(childpath) } еще { //Продолжаем обнаруживать папку deleDir(childpath) } }) // Удаляем пустую папку fs.rmdirSync(src) } deleDir("../floor")
кратко описывает сценарии использования пути. Далее мы изучим механизм его выполнения и то, как он реализуется на основе его использования.
Когда вводится модуль пути и вызывается инструментальная функция пути, будет введена логика обработки собственного модуля.
Используйте функцию _load
, чтобы использовать имя модуля, которое вы указали в качестве идентификатора, чтобы определить, что загружаемый модуль является собственным модулем JS. После этого функция loadNativeModule
будет использоваться для использования идентификатора для поиска соответствующего кода ASCII из _source
(. строка исходного кода, сохраняющая собственный модуль JS). Данные загружаются в собственный модуль JS.
Выполните файл lib/path.js и используйте процесс для определения операционной системы. В зависимости от операционной системы может быть дифференциальная обработка рабочих символов при обработке файла, но метод примерно тот же. После обработки он возвращается в исходное состояние. звонивший.
возвращает абсолютный путь текущего пути
.
разрешить (... аргументы) { пусть разрешеноDevice = ''; пусть разрешенный хвост = ''; пусть разрешено Абсолютное = ложь; // Обнаружение параметров справа налево for (let i = args.length - 1; i >= -1; i--) { ... } //Нормализованный путьsolvedTail =normalizeString(resolvedTail, !resolvedAbsolute, '\', isPathSeparator); вернуть решенное Абсолютно? `${resolvedDevice}\${resolvedTail}` : `${resolvedDevice}${resolvedTail}` || }
Получить путь по параметрам, пройтись по полученным параметрам, начать склейку, когда длина параметров больше или равна 0, выполнить нестроковую проверку по склеенному пути, если есть несовпадающие параметры , throw new ERR_INVALID_ARG_TYPE(name, 'string', value)
, если требования соблюдены, длина пути будет оценена. Если есть значение, для следующего шага будет использоваться += путь.
пусть путь; если (я >= 0) { путь = аргументы [я]; // внутренние/валидаторы validateString (путь, 'путь'); // Если длина пути равна 0, он выйдет непосредственно из цикла for приведенного выше блока кода if (path.length === 0) { продолжать; } } еще если (resolvedDevice.length === 0) { //Длина разрешенного устройства равна 0, присвойте значение path как текущий рабочий каталог path =process.cwd(); } еще { // Присвоение значения объекту среды или текущему рабочему каталогу path =process.env[`=${resolvedDevice}`] ||process.cwd(); если (путь === не определено || (StringPrototypeToLowerCase(StringPrototypeSlice(path, 0, 2)) !== StringPrototypeToLowerCase(resolvedDevice) && StringPrototypeCharCodeAt(путь, 2) === CHAR_BACKWARD_SLASH)) { // Оцениваем путь по непустым и абсолютным путям, чтобы получить путь path = `${resolvedDevice}\`; } }
Попробуйте сопоставить корневой путь, определите, существует ли только один разделитель пути ('') или путь является абсолютным, затем отметьте абсолютный путь и установите для флага перехвата rootEnd
значение 1 (нижний индекс). Если второй элемент по-прежнему является разделителем пути (''), определите значение перехвата как 2 (нижний индекс) и используйте last
, чтобы сохранить значение перехвата для последующего принятия решения.
Продолжайте определять, является ли третий элемент разделителем пути (''). Если да, то это абсолютный путь, а идентификатор перехвата rootEnd
равен 1 (нижний индекс), но это также может быть путь UNC (servernamesharename). , имя сервера имя сервера). Если есть другие значения, перехваченное значение будет продолжать увеличиваться и читать следующие значения, а также использовать firstPart
для сохранения значения третьего бита, чтобы это значение можно было получить при объединении каталога, и сохранять последнее и перехваченное значения. последователь прекратить судебное решение.
const len = путь.длина; let rootEnd = 0 // индекс конца перехвата пути let device = '' // корень диска D:, C: let isAbsolute = false // Является ли это корневым путем диска const code = StringPrototypeCharCodeAt(path, 0); // длина пути равна 1 если (длин === 1) { // Для абсолютного пути существует только один разделитель пути if (isPathSeparator(code)) { кореньКонец = 1; isAbsolute = правда; } } Еще если (isPathSeparator(код)) { // Может быть корнем UNC, начинающимся с разделителя , по крайней мере один из которых является абсолютным путем (UNC или другим) isAbsolute = правда; // Начинаем сопоставление двойного разделителя путей if (isPathSeparator(StringPrototypeCharCodeAt(path, 1))) { пусть j = 2; пусть последний = j; // Сопоставление одного или нескольких разделителей, не являющихся путями, while (j < len && !isPathSeparator(StringPrototypeCharCodeAt(path, j))) { j++; } if (j <len && j !== последний) { const firstPart = StringPrototypeSlice (путь, последний, j); последний = j; // Сопоставление одного или нескольких разделителей пути while (j < len && isPathSeparator (StringPrototypeCharCodeAt (путь, j))) { j++; } if (j <len && j !== последний) { последний = j; в то время как (j < len && !isPathSeparator(StringPrototypeCharCodeAt(path, j))) { j++; } if (j === len || j !== последний) { устройство= `\\${firstPart}\${StringPrototypeSlice(path, Last, j)}`; rootEnd = j; } } } } еще { кореньКонец = 1; } // Пример определения корневого каталога диска: D:, C: } else if (isWindowsDeviceRoot(code) && StringPrototypeCharCodeAt(path, 1) === CHAR_COLON) { устройство = StringPrototypeSlice (путь, 0, 2); кореньКонец = 2; if (len > 2 && isPathSeparator(StringPrototypeCharCodeAt(path, 2))) { isAbsolute = правда; кореньКонец = 3; } }
Определите путь и сгенерируйте его, проверьте, существует ли корневой каталог диска, или определите, является resolvedAbsolute
абсолютным путем.
//Определить корневой каталог диска if (device.length > 0) { //solveDevice имеет значение if (resolvedDevice.length > 0) { если (StringPrototypeToLowerCase(устройство) !== StringPrototypeToLowerCase(resolvedDevice)) продолжать; } еще { //solveDevice не имеет значения и ему присваивается значение корневого каталога дискаsolveDevice = device; } } // Абсолютный путь if (resolvedAbsolute) { // Существует конечный цикл, если корневой каталог диска существует (resolvedDevice.length > 0) перерыв; } еще { // Получаем префикс пути для склейкиsolveTail = `${StringPrototypeSlice(path, rootEnd)}\${resolvedTail}`; решеноАбсолютное = естьАбсолютное; if (isAbsolute &&solveDevice.length > 0) { // Цикл завершается, когда корень диска существует. } }
join выполняет объединение путей на основе входящих фрагментов пути
Получите несколько параметров, используйте определенные разделители в качестве разделителей для соединения всех параметров пути вместе и создайте новый нормализованный путь.
После получения параметров проверьте их. Если параметров нет, он вернет непосредственно «.». В противном случае он будет проходить и проверять каждый параметр с помощью встроенного метода validateString
. Если есть какое-либо нарушение, напрямую throw new ERR_INVALID_ARG_TYPE(name, 'string', value);
join
escape-символа заключается в том, что при его использовании отдельно считается, что он экранирует строку после косой черты, поэтому для экранирования обратной косой черты используются двойные обратные косые черты ('').
Наконец, объединенная строка проверяется и возвращается в заданном формате.
if (args. length === 0) возвращаться '.'; пусть присоединился; пусть первая часть; // Обнаружение параметров слева направо for (let i = 0; i < args.length; ++i) { const arg = args[i]; // внутренние/валидаторы validateString(arg, 'путь'); if (длина аргумента > 0) { если (присоединился === не определено) // Назначаем первую строку объединению и используем переменную firstPart, чтобы сохранить первую строку для последующего использования join = firstPart = arg; еще // join имеет значение, выполняем операцию += сращивания join += `\${arg}`; } } если (присоединился === не определено) return '.';
В оконной системе требуется обработка сетевого пути из-за использования обратной косой черты ('') и пути UNC (в основном относится к полному имени ресурсов Windows 2000 в локальной сети), ('') представляет собой формат сетевого пути, поэтому метод join
установленный в Win32, будет перехватываться по умолчанию.
Если обратная косая черта ('') совпадает, slashCount
будет увеличиваться. Если найдено более двух обратных косых черт (''), объединенный путь будет перехвачен и вручную объединен и экранирован обратной косой чертой (. '').
пусть потребностиReplace = true; пусть slashCount = 0; // Извлекаем код кода первой строки в последовательности в соответствии с StringPrototypeCharCodeAt и сопоставляем его с определенным кодом кода с помощью метода isPathSeparator if (isPathSeparator(StringPrototypeCharCodeAt(firstPart, 0))) { ++слэшКаунт; const firstLen = firstPart.length; если (firstLen > 1 && isPathSeparator(StringPrototypeCharCodeAt(firstPart, 1))) { ++слэшКаунт; если (firstLen > 2) { если (isPathSeparator(StringPrototypeCharCodeAt(firstPart, 2))) ++слэшКаунт; еще { потребностиЗаменить = ложь; } } } } если (нуждыЗаменить) { while (slashCount < join.length && isPathSeparator(StringPrototypeCharCodeAt(joined, slashCount))) { слэшКаунт++; } если (слэшКаунт >= 2) join = `\${StringPrototypeSlice(joined, slashCount)}`; }
Сортировка результатов выполнения
Разрешение | соединения | |
---|---|---|
не имеет параметров | . | Абсолютный путь к текущему файлу | .
Параметры | не имеют абсолютного | пути. |
Первый параметр — это абсолютный путь. | текущего файла ивставляется в абсолютный путь | последующих неабсолютных путей. |
Пост-параметр пути является параметром абсолютного пути | . Путь перезаписывает абсолютный путь текущего файла и перезаписывает | путь, соединенный с ним. | предварительные параметры.
Первый параметр — (./) | и имеет последующие параметры. Параметр сращивания абсолютного пути текущего файла не имеет последующих параметров. Абсолютный путь к текущему файлу — Путь | имеет последующие параметры, а путь сращивается. по последующим параметрам не имеет последующих параметров. (./) |
Пост-параметр имеет (./) | Разбираемый параметр сращивания абсолютного пути | имеет последующие параметры. Склеенный путь не имеет последующих параметров, а сращивание (/ |
) первый параметр — (../), | и есть последующие параметры. Параметры склейки после каталога последнего уровня, охватывающего абсолютный путь текущего файла, не имеют последующих параметров. Каталог последнего уровня, охватывающий абсолютный путь текущего файла, | имеет последующие параметры. . Сращивание Для последующих параметров нет последующих параметров (../) |
Пост-параметр имеет (../ | )Каталог верхнего уровня, в котором появляется (../), будет перезаписан. перезаписан. Каталог верхнего уровня будет перезаписан. После возврата (/) последующие параметры будут склеены и | появившийся каталог верхнего уровня (../) будет перезаписан. Сколько слоев указано в суффиксе, будет перезаписано. После перезаписи верхнего каталога |
. После исходного кода метод resolve
обработает параметры, учтет форму пути и выдаст в конце абсолютный путь. При его использовании, если вы выполняете такие операции, как файлы, рекомендуется использовать метод resolve
. Для сравнения, метод resolve
вернет путь, даже если нет параметров для работы пользователя, и путь будет обработан. в процессе исполнения. Метод join
выполняет только стандартизированное объединение входящих параметров, что более практично для создания нового пути и может быть создано по желанию пользователя. Однако каждый метод имеет свои преимущества. Вам следует выбрать подходящий метод в соответствии с вашими сценариями использования и потребностями проекта.