
Durante o processo de desenvolvimento, o Node.js é frequentemente usado, que usa os recursos fornecidos pelo V8 para expandir os recursos do JS. Em Node.js, podemos usar o módulo path que não existe em JS. Para nos familiarizarmos mais com o aplicativo, vamos dar uma olhada nele ~
A versão Node.js deste artigo é 16.14.0. , e o código-fonte deste artigo vem daqui Versão. Espero que depois de ler este artigo, seja útil para todos lerem o código-fonte.
Path é usado para processar os caminhos de arquivos e diretórios. Este módulo fornece algumas funções de ferramenta que são convenientes para os desenvolvedores desenvolverem para nos ajudar a fazer julgamentos de caminhos complexos e melhorar a eficiência do desenvolvimento. Por exemplo:
Configurar aliases no projeto A configuração do alias facilita a referência de arquivos e evita a busca passo a passo.
reamar: {
apelido: {
// __dirname caminho do diretório 'src' onde o arquivo atual está localizado: path.resolve(__dirname, './src'),
// process.cwd diretório de trabalho atual '@': path.join(process.cwd(), 'src'),
},
} No webpack, o caminho de saída do arquivo também pode ser gerado para o local especificado através de nossa própria configuração.
módulo.exportações = {
entrada: './caminho/para/minha/entrada/arquivo.js',
saída: {
caminho: path.resolve(__dirname, 'dist'),
nome do arquivo: 'meu-primeiro-webpack.bundle.js',
},
}; Ou para operações de pasta
let fs = require("fs");
deixe caminho = exigir("caminho");
// Exclua a pasta let deleDir = (src) => {
// Leia a pasta let children = fs.readdirSync(src);
filhos.forEach(item => {
deixe caminho filho = path.join(src, item);
// Verifica se o arquivo existe let file = fs.statSync(childpath).isFile();
se (arquivo) {
// Exclua o arquivo se ele existir fs.unlinkSync(childpath)
} outro {
//Continua detectando a pasta deleDir(childpath)
}
})
// Exclua a pasta vazia fs.rmdirSync(src)
}
deleDir("../floor") entende brevemente os cenários de uso do caminho. A seguir, estudaremos seu mecanismo de execução e como ele é implementado com base em seu uso.

Quando o módulo path é introduzido e a função da ferramenta path é chamada, a lógica de processamento do módulo nativo será inserida.
Use a função _load para usar o nome do módulo que você introduziu como ID para determinar se o módulo a ser carregado é um módulo JS nativo. Depois disso, a função loadNativeModule será usada para usar o id para encontrar o código ASCII correspondente de _source (. a string do código-fonte que salva o módulo JS nativo). Os dados são carregados no módulo JS nativo.
Execute o arquivo lib/path.js e use o processo para determinar o sistema operacional Dependendo do sistema operacional, pode haver processamento diferencial de caracteres operacionais no processamento do arquivo, mas o método é aproximadamente o mesmo. Após o processamento, ele é retornado. o chamador.
resolve retorna o caminho absoluto do caminho atual
resolve emenda vários parâmetros em sequência para gerar um novo caminho absoluto.
resolver(...args) {
deixe resolvidoDevice = '';
deixe resolvidoTail = '';
deixe resolvidoAbsoluto = falso;
// Detecta parâmetros da direita para a esquerda for (let i = args.length - 1; i >= -1; i--) {
...
}
//Caminho normalizado resolveTail = normalizeString(resolvedTail, !resolvedAbsolute, '\', isPathSeparator);
retornar resolvidoAbsoluto?
`${resolvedDevice}\${resolvedTail}` :
`${resolvedDevice}${resolvedTail}` || '.';
} 
Obtenha o caminho de acordo com os parâmetros, percorra os parâmetros recebidos, inicie a emenda quando o comprimento dos parâmetros for maior ou igual a 0, execute a verificação de não string no caminho emendado, se houver algum parâmetro que não corresponda , throw new ERR_INVALID_ARG_TYPE(name, 'string', value) , se os requisitos forem atendidos, o comprimento do caminho será julgado. Se houver um valor, += path será usado para a próxima etapa.
deixe caminho;
se (eu >= 0) {
caminho = args[i];
// interno/validadores
validarString(caminho, 'caminho');
// Se o comprimento do caminho for 0, ele saltará diretamente para fora do loop for do bloco de código acima if (path.length === 0) {
continuar;
}
} else if (resolvedDevice.length === 0) {
//O comprimento de resolveDevice é 0, atribua o valor ao path como o diretório de trabalho atual path = process.cwd();
} outro {
// Atribua o valor ao objeto de ambiente ou ao diretório de trabalho atual path = process.env[`=${resolvedDevice}`] || process.cwd();
if (caminho === indefinido ||
(StringPrototypeToLowerCase(StringPrototypeSlice(caminho, 0, 2)) !==
StringPrototypeToLowerCase(resolvidoDevice) &&
StringPrototypeCharCodeAt(caminho, 2) === CHAR_BACKWARD_SLASH)) {
//Julgue o caminho para caminhos não vazios e absolutos para obter o caminho path = `${resolvedDevice}\`;
}
} 
Tente corresponder o caminho raiz, determine se há apenas um separador de caminho ('') ou se o caminho é um caminho absoluto, marque o caminho absoluto e defina rootEnd como 1 (subscrito). Se o segundo item ainda for um separador de caminho (''), defina o valor de interceptação como 2 (subscrito) e use last para salvar o valor de interceptação para julgamento subsequente.
Continue a determinar se o terceiro item é um separador de caminho (''). Nesse caso, é um caminho absoluto e o identificador de interceptação rootEnd é 1 (subscrito), mas também pode ser um caminho UNC (servernamesharename). , nome do servidor nome do servidor). nome do recurso compartilhado). Se houver outros valores, o valor interceptado continuará a incrementar e ler os seguintes valores, e usar firstPart para salvar o valor do terceiro bit para que o valor possa ser obtido ao emendar o diretório, e manter os últimos valores interceptados consistente para encerrar o julgamento.
const len = caminho.comprimento;
let rootEnd = 0; // Subscrito final da interceptação do caminho let device = '';
let isAbsolute = false; // Se é o caminho raiz do disco const code = StringPrototypeCharCodeAt(path, 0);
//o comprimento do caminho é 1
if (len === 1) {
// Existe apenas um separador de caminho para caminho absoluto if (isPathSeparator(code)) {
rootEnd = 1;
éAbsoluto = verdadeiro;
}
} else if (isPathSeparator(código)) {
// Pode ser uma raiz UNC, começando com um delimitador , pelo menos um dos quais é algum tipo de caminho absoluto (UNC ou outro)
éAbsoluto = verdadeiro;
// Começa a combinar o separador de caminho duplo if (isPathSeparator(StringPrototypeCharCodeAt(path, 1))) {
seja j = 2;
deixe por último = j;
// Corresponde a um ou mais delimitadores que não sejam de caminho while (j < len &&
!isPathSeparator(StringPrototypeCharCodeAt(caminho, j))) {
j++;
}
if (j < len && j !== último) {
const primeiraPart = StringPrototypeSlice(caminho, último, j);
último = j;
// Corresponde a um ou mais separadores de caminho while (j < len &&
isPathSeparator(StringPrototypeCharCodeAt(caminho, j))) {
j++;
}
if (j < len && j !== último) {
último = j;
while (j <len &&
!isPathSeparator(StringPrototypeCharCodeAt(caminho, j))) {
j++;
}
if (j === len || j !== último) {
dispositivo =
`\\${firstPart}\${StringPrototypeSlice(caminho, último, j)}`;
rootEnd = j;
}
}
}
} outro {
rootEnd = 1;
}
// Detecta exemplo de correspondência do diretório raiz do disco: D:, C:
} else if (isWindowsDeviceRoot(código) && StringPrototypeCharCodeAt(caminho, 1) === CHAR_COLON) {
dispositivo = StringPrototypeSlice(caminho, 0, 2);
rootEnd = 2;
if (len > 2 && isPathSeparator(StringPrototypeCharCodeAt(caminho, 2))) {
éAbsoluto = verdadeiro;
rootEnd = 3;
}
} Detecte o caminho e gere-o, verifique se o diretório raiz do disco existe ou resolva se resolvedAbsolute é um caminho absoluto.
//Detecta o diretório raiz do disco if (device.length > 0) {
// resolveDevice tem valor if (resolvedDevice.length > 0) {
if (StringPrototypeToLowerCase(dispositivo)!==
StringPrototypeToLowerCase(resolvidoDevice))
continuar;
} outro {
// resolveDevice não tem valor e recebe o valor do diretório raiz do disco resolviDevice = device;
}
}
// Caminho absoluto if (resolvedAbsolute) {
//Há um loop final se o diretório raiz do disco existir (resolvedDevice.length > 0)
quebrar;
} outro {
// Obtém o prefixo do caminho para emendar resolveTail =
`${StringPrototypeSlice(caminho, rootEnd)}\${resolvedTail}`;
resolvidoAbsoluto = éAbsoluto;
if (isAbsolute && resolveDevice.length > 0) {
// O loop termina quando a raiz do disco existe break;
}
} join executa a emenda do caminho com base nos fragmentos do caminho de entrada

Receba vários parâmetros, use separadores específicos como delimitadores para conectar todos os parâmetros do caminho e gere um novo caminho normalizado.
Depois de receber os parâmetros, verifique-os. Se não houver parâmetros, ele retornará '.' Caso contrário, ele percorrerá e verificará cada parâmetro por meio do método validateString integrado. Se houver alguma violação, throw new ERR_INVALID_ARG_TYPE(name, 'string', value);
join função do caractere de escape é que quando usado sozinho, ele é considerado um escape da string após a barra, portanto, barras invertidas duplas são usadas para escapar da barra invertida ('').
Finalmente, a string concatenada é verificada e retornada em formato.
if (args. comprimento === 0)
retornar '.';
deixe-se juntar;
deixe firstPart;
// Detecta parâmetros da esquerda para a direita for (let i = 0; i < args.length; ++i) {
const arg = args[i];
// interno/validadores
validarString(arg, 'caminho');
if (comprimento do argumento > 0) {
if (ingressou === indefinido)
// Atribua a primeira string à junção e use a variável firstPart para salvar a primeira string para uso posterior join = firstPart = arg;
outro
// unido tem um valor, execute += operação de emenda unido += `\${arg}`;
}
}
if (ingressou === indefinido)
return '.'; No sistema de janelas, o processamento do caminho de rede é necessário devido ao uso de barra invertida ('') e UNC (referindo-se principalmente ao nome completo dos recursos do Windows 2000 na LAN), ('') representa é um formato de caminho de rede, portanto, o método join montado no win32 interceptará por padrão.
Se uma barra invertida ('') for correspondida, slashCount será incrementado Enquanto houver mais de duas barras invertidas ('') correspondentes, o caminho emendado será interceptado e emendado e escapado manualmente (. '').
deixe necessidadesReplace = true;
deixe barraCount = 0;
// Extraia o código da primeira string em sequência de acordo com StringPrototypeCharCodeAt e combine-o com o código definido por meio do método isPathSeparator if (isPathSeparator(StringPrototypeCharCodeAt(firstPart, 0))) {
++Contagem de barras;
const firstLen = firstPart.length;
if (firstLen > 1 &&
isPathSeparator(StringPrototypeCharCodeAt(firstPart, 1))) {
++Contagem de barras;
if (firstLen > 2) {
if (isPathSeparator(StringPrototypeCharCodeAt(firstPart, 2)))
++Contagem de barras;
outro {
precisaReplace = falso;
}
}
}
}
if (precisa substituir) {
while (slashCount <unido.comprimento &&
isPathSeparator(StringPrototypeCharCodeAt(juntado, slashCount))) {
barraContagem++;
}
if (contagem de barras >= 2)
unido = `\${StringPrototypeSlice(juntado, slashCount)}`;
} Classificação dos resultados da execução
| resolve | join | |
|---|---|---|
| não tem parâmetros | . | O caminho absoluto do arquivo atual |
| absoluto | ||
| do | arquivo atual é dividido | em ordem. |
| dividido no caminho absoluto dos | caminhos não absolutos subsequentes. | O|
| pós-parâmetro do caminho é um | parâmetro de caminho absoluto. O caminho substitui o caminho absoluto do arquivo atual e substitui | o caminho emendado pelo. | pré-parâmetros
| O primeiro parâmetro é (./) | e possui parâmetros subsequentes. O parâmetro de emenda do caminho absoluto do arquivo atual não possui parâmetros subsequentes | . pelos parâmetros subseqüentes não possui parâmetros subseqüentes (./) |
| pós | ||
| -parâmetro possui (./) | O parâmetro de emenda do caminho absoluto analisado | possui parâmetros subseqüentes. |
| o primeiro parâmetro é (../) | e há parâmetros subsequentes. Os parâmetros de emenda após o último diretório de nível que cobre o caminho absoluto do arquivo atual não possuem parâmetros subsequentes | . . Splicing Não há parâmetros subseqüentes para parâmetros subseqüentes (../) |
| O pós-parâmetro possui (../ | )O diretório de nível superior onde (../) aparece será substituído. substituído. O diretório de nível superior será sobrescrito. Após retornar (/), os parâmetros subsequentes serão emendados e | o diretório superior que aparece (../) será sobrescrito Quantas camadas aparecem no sufixo. Após a substituição do diretório superior, o |
lido. Após o código-fonte, o método resolve processará os parâmetros, considerará a forma do caminho e descartará o caminho absoluto no final. Ao usá-lo, se você estiver realizando operações como arquivos, é recomendado usar o método resolve . Em comparação, o método resolve retornará um caminho mesmo que não haja parâmetros para o usuário operar, e o caminho será processado. durante o processo de execução. O método join realiza apenas a emenda padronizada dos parâmetros recebidos, o que é mais prático para gerar um novo caminho e pode ser criado de acordo com a vontade do usuário. No entanto, cada método tem suas vantagens. Você deve escolher o método apropriado de acordo com seus próprios cenários de uso e necessidades do projeto.