//31、任务的区分
//vue的源码nextTick方法 描述了浏览器中常见的宏任务和微任务
//宏任务 script/ui/setTimeout/setInterval/requestFrameAnimation/setImmediate/MessageChannel 异步的 click ajax
//语言的本身提供的 promise.then mutationObserver nextTick
//32、模块的概念
/*
模块化规范:
Node中的模块化规范:
commonjs规范(node自己实现的)
es6Module(import export)
umd统一模块规范(如果浏览器不支持commonjs、requirejs,直接将变量放到window上)
amd规范
cmd规范
seajs
requirejs
commonjs规范(模块的概念)
----可以把复杂的代码拆分成小的模块,方便管理代码和维护;
----每个模块之间的内容都是相互独立的,互不影响的。(解决变量冲突的问题)。 单例模式(不能完全解决 命名空间) 使用自执行函数来解决
var name1={
a:1
}
var name2 = {
a:2
}
function (){
var a=1;
}()
function(){
var a =2;
}()
规范的定义:
每个文件都是一个模块;
如果你希望模块中的变量被别人使用,可以使用module.exports导出这个变量;
如果另一个模块想使用这个模块导出的结果,需要使用require语法来引用(同步的)
a.js
let a =1;
module.export = a;
useA.js
let r = require('./a')
console.log(r);
模块的分类:
require('fs') 核心模块、内置模块 不是自己写的,也不是安装来的是node中自己提供的,可以直接使用
require('commander');别人写的模块,通过npm install安装过来的,就是第三方模块,不需要有路径
自定义模块 require('./promise.js'); 自定义模块就是自己写的模块,引用时需要增加路径(相对路径,绝对路径)
//33.core模块使用
核心模块:
fs(fileSystem处理文件的)
path(处理路径)
vm(虚拟机模块 沙箱环境)
const fs = require('fs');
const path = require('path');
console.log(Object.keys(fs));
console.log(Object.keys(fs.promises)); //只会转换异步的方法
打印结果
[
'appendFile', 'appendFileSync', 'access',
'accessSync', 'chown', 'chownSync',
'chmod', 'chmodSync', 'close',
'closeSync', 'copyFile', 'copyFileSync',
'createReadStream', 'createWriteStream', 'exists',
'existsSync', 'fchown', 'fchownSync',
'fchmod', 'fchmodSync', 'fdatasync',
'fdatasyncSync', 'fstat', 'fstatSync',
'fsync', 'fsyncSync', 'ftruncate',
'ftruncateSync', 'futimes', 'futimesSync',
'lchown', 'lchownSync', 'lchmod',
'lchmodSync', 'link', 'linkSync',
'lstat', 'lstatSync', 'mkdir',
'mkdirSync', 'mkdtemp', 'mkdtempSync',
'open', 'openSync', 'opendir',
'opendirSync', 'readdir', 'readdirSync',
'read', 'readSync', 'readv',
'readvSync', 'readFile', 'readFileSync',
'readlink', 'readlinkSync', 'realpath',
'realpathSync', 'rename', 'renameSync',
'rmdir', 'rmdirSync', 'stat',
'statSync', 'symlink', 'symlinkSync',
'truncate', 'truncateSync', 'unwatchFile',
'unlink', 'unlinkSync', 'utimes',
'utimesSync', 'watch', 'watchFile',
'writeFile', 'writeFileSync', 'write',
'writeSync', 'writev', 'writevSync',
'Dir', 'Dirent', 'Stats',
'ReadStream', 'WriteStream', 'FileReadStream',
'FileWriteStream', '_toUnixTimestamp', 'F_OK',
'R_OK', 'W_OK', 'X_OK',
'constants', 'promises'
]
[
'access', 'copyFile', 'open',
'opendir', 'rename', 'truncate',
'rmdir', 'mkdir', 'readdir',
'readlink', 'symlink', 'lstat',
'stat', 'link', 'unlink',
'chmod', 'lchmod', 'lchown',
'chown', 'utimes', 'realpath',
'mkdtemp', 'writeFile', 'appendFile',
'readFile'
]
所有的方法基本上都是同步方法、异步方法;
同步:如果刚刚运行程序,可以去使用同步的方法;
异步:开启一个服务监听客户端程序,就需要使用异步了,异步是非阻塞的;
操作文件时,尽量使用“绝对路径”来进行操作
获取当前的目录, process.cwd() 可变的 __dirname不可变的
const fs = require('fs');
const path = require('path');
//resolve不能遇到/,遇到/回到C盘的根目录
console.log(path.resolve(__dirname,'name.txt','/'));
//C:\Users\dptech\Desktop\test>node test.js
//C:\
console.log(path.join('name.txt','/'));//拼接name.txt \
//C:\Users\dptech\Desktop\test>node test.js
//name.txt\
console.log(path.join(__dirname,'name.txt','/'));
//C:\Users\dptech\Desktop\test>node test.js
//C:\Users\dptech\Desktop\test\name.txt\
console.log(path.extname('a/b/a.min.js'));//获取当前文件的扩展名 .js
//C:\Users\dptech\Desktop\test>node test.js
//.js
console.log(path.resolve(__dirname,'..','name.txt'));
const r = fs.readFileSync(path.resolve(__dirname,'..','name.txt'),'utf8');
console.log(r);
//C:\Users\dptech\Desktop\test\aa>node test.js
//C:\Users\dptech\Desktop\test\name.txt
//age.txt
fs.exists(path.resolve(__dirname,'..','name1.txt'),function(err,data){
console.log(err);//false (此方法已废弃)
})
//C:\Users\dptech\Desktop\test\aa>node test.js
//false
1、同步判断文件是否存在
const exists = fs.existsSync(path.resolve(__dirname,'..','name1.txt'));
console.log(exists);//false
2、同步的读取文件
const r = fs.readFileSync(path.resolve(__dirname,'..','name1.txt'));
console.log(r);
<!--
C:\Users\dptech\Desktop\test\aa>node test.js
false
internal/fs/utils.js:259
throw err;
^
Error: ENOENT: no such file or directory, open 'C:\Users\dptech\Desktop\test\name1.txt'
at Object.openSync (fs.js:461:3)
at Object.readFileSync (fs.js:364:35)
at Object.<anonymous> (C:\Users\dptech\Desktop\test\aa\test.js:6:14)
at Module._compile (internal/modules/cjs/loader.js:1200:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1220:10)
at Module.load (internal/modules/cjs/loader.js:1049:32)
at Function.Module._load (internal/modules/cjs/loader.js:937:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
at internal/main/run_main_module.js:17:47 {
errno: -4058,
syscall: 'open',
code: 'ENOENT',
path: 'C:\\Users\\dptech\\Desktop\\test\\name1.txt'
}
-->
__dirname代表的是当前文件所在的文件夹
__dirname并不属于global,每个模块独有的
*/
/*
//34、基本模板引擎
//虚拟机模块(沙箱) 干净的环境 测试用例
//内部一般情况下操作的都是字符串逻辑,如何让一个字符串来运行`console.log(1)`
//eval 默认会取当前的作用域下的变量,不干净的环境 eval()
const a = 100;
eval(`console.log(a)`);//100
const a = 100;
let fn = new Function(`console.log(a)`);
console.log(fn.toString());
console.log(fn());
//C:\Users\dptech\Desktop\test>node test.js
//function anonymous(
//) {
//console.log(a)
//}
//undefined:3
//console.log(a)
//ReferenceError: a is not defined
const a = 100;
let fn = new Function('c','b',`console.log(a)`);
console.log(fn.toString());
//function anonymous(c,b
//) {
//console.log(a)
//}
//可以使用new Function来创建一个沙箱环境,让字符串执行
let fn = new Function('c','b','d',`let a=1;console.log(a);`);
console.log(fn());
//模板引擎的实现原理 with语法+字符串拼接+new Function来实现
template.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<%= name %>
<%= age %>
</body>
</html>
template.js
//实现自定义的模板引擎
const ejs = require('ejs');//第三方模块 npm init -y ; npm install ejs
const path = require('path');
const fs = require('fs');
//ejs.render();
ejs.renderFile(path.resolve(__dirname,'template.html'),{name:'zf',age:11,arr:[1,2,3]},(err,data)=>{
console.log(data);
})
结果:
<!--
C:\Users\dptech\Desktop\test>node test.js
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
zf
11
</body>
</html>
-->
my-template.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="with=device-width,initial-scale=1.0">
<title>Document</title>
</head>
<body>
{{name}} {{age}}
</body>
</html>
//arguments[0]就是匹配到的原字符串
//arguments[1]就是第一个括号
const ejs = require('ejs');//第三方模块 npm init -y ; npm install ejs
const path = require('path');
const fs = require('fs');
const renderFile = (filePath,obj,cb)=>{
fs.readFile(filePath,'utf8',function(err,html){
console.log(html);
if(err){
return cb(err,html);
}
html = html.replace(/\{\{([^}]+)\}\}/g,function(){
//console.log(arguments[1].trim());
let key = arguments[1].trim();
return obj[key];
});
cb(err,html);
})
}
renderFile(path.resolve(__dirname,'my-template.html'),{name:'zfpx',age:11,arr:[1,2,3]},function(err,data){
console.log(data);
})
结果:
/*
C:\Users\dptech\Desktop\test>node test.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="with=device-width,initial-scale=1.0">
<title>Document</title>
</head>
<body>
{{name}} {{age}}
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="with=device-width,initial-scale=1.0">
<title>Document</title>
</head>
<body>
zfpx 11
</body>
</html>
*/
/*
//35、模板引擎的实现原理
my-template.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="with=device-width,initial-scale=1.0">
<title>Document</title>
</head>
<body>
{{name}} {{age}}
{% arr.forEach(item=>{ %}
<li>1</li>
{% }) %}
</body>
</html>
const path = require('path');
const fs = require('fs');
const renderFile=(filePath,obj,cb)=>{
fs.readFile(filePath,'utf8',function(err,html){
if(err)
{
return cb(err,html);
}
//arguments[0]就是匹配到的原字符串
//arguments[1]就是第一个原来括号
html = html.replace(/\{\{([^}]+)\}\}/g,function(){
console.log(arguments[1]);
let key = arguments[1].trim();
return obj[key];
});
cb(err,html);
})
}
renderFile(path.resolve(__dirname,'my-template.html'),{name:'zf',age:11,arr:[1,2,3]},function(err,data){
console.log(data);
})
/*
C:\Users\dptech\Desktop\test>node test.js
name
age
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="with=device-width,initial-scale=1.0">
<title>Document</title>
</head>
<body>
zf 11
{% arr.forEach(item=>{ %}
<li>1</li>
{% }) %}
</body>
</html>
*/
/*
test.js
function a(obj){
let str = '';
with(obj){
str += `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="with=device-width,initial-scale=1.0">
<title>Document</title>
</head>
<body> `
arr.forEach(item=>{
str += `<li>1</li>`
})
str+=`</body>
</html>`;
}
return str;
}
console.log(a({arr:[1,2,3]}));
//结果
C:\Users\dptech\Desktop\test>node test.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="with=device-width,initial-scale=1.0">
<title>Document</title>
</head>
<body> <li>1</li><li>1</li><li>1</li></body>
</html>
//1、需要把字符串{% %}替换掉,并且拼出一个结果的字符串,new Function的方式 with
my-template.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="with=device-width,initial-scale=1.0">
<title>Document</title>
</head>
<body>
{{name}} {{age}}
{% arr.forEach(item=>{ %}
<li>item</li>
{% }) %}
</body>
</html>
template.js
const path = require('path');
const fs = require('fs');
const renderFile=(filePath,obj,cb)=>{
fs.readFile(filePath,'utf8',function(err,html){
if(err)
{
return cb(err,html);
}
//arguments[0]就是匹配到的原字符串
//arguments[1]就是第一个原来括号
html = html.replace(/\{\{([^}]+)\}\}/g,function(){ //RegExp.$1
console.log(arguments[1]);
let key = arguments[1].trim();
return '${'+key+'}' //{{name}}=>${name}
});
let head = `let str='';\r\n with(obj){\r\n`;
head += 'str+=`';
html = html.replace(/\{\%([^%]+)\%\}/g,function(){
return '`\r\n'+arguments[1]+'\r\nstr+=`\r\n';
})
let tail = '`}\r\n return str;';
console.log(head+html+tail);
let fn = new Function('obj',head+html+tail);
console.log(fn.toString());
cb(err,html);
})
}
renderFile(path.resolve(__dirname,'my-template.html'),{name:'zf',age:11,arr:[1,2,3]},function(err,data){
console.log(data);
})
*/