commonJS
属性描述的问题
//有什么区别?var a = 1; configurable false; 不可删除不可配置window.b; configurable true; writable true
问题:require是什么?
它不属于全局对象提供的方法,它源于commonJS规范
问题:commonJS模块是什么?
后端模块化规范
问题:为什么区分前后端规范?
前端以前没有规范,随着业务复杂才有,前后端干活不一样,一个同步加载,一个异步加载
问题:后端commonJS规范有什么用?
(function(exports require, module, __filename, __dirname){})();
//arguments在前端会报错,后端是一个arguments对象arguments{0: {}, //this1: '...', //require(fn)2: '...', //module3: '...', //__filename 绝对路径4: '...' //__dirname}console.log(this === module.exports); //trueconsole.log(this === exports); //trueconsole.log(exports === module.exports); //true 说明两者指针相同,指向同一对象//module.exports = {} exports = {}console.log(argument[0] === this); //trueconsole.log(argument[0] === module.exports); //trueconsole.log(argument[1] === require); //trueconsole.log(argument[2] === module); //trueconsole.log(argument[3] === __filename); //trueconsole.log(argument[4] === __dirname); //true//写法1:module.exports = { a: 1 }//写法2:exports.a = 1;
//重写require实现模块加载function myRequire(filename){//相对目录变成绝对目录const current = resolveFilename(filename);//判断是否存在模块if(Module._cache[current]){return Module._cache[current].exports;}//根据路径实例化一个模块let module = new Module(current);//缓存加载Module._cache[current] = module;//加载模块module.load();//返回对象return module.export;}function Module(filename){//每个模块有自己的idthis.id = filename;//默认为空对象this.exports = {};}//相对目录变成绝对目录Module.resolveFilename = function(filename){//PS://current work directorly - 当前工作目录//__filename 绝对路径//process.cwd() 当前路径//path.resolve() 将多个路径片段拼接成为绝对路径//当前路径 + 当前文件名const absPath = path.resolve(__dirname, filename);console.log(absPath);//c:\users\desktop\alet current = absPath;//判断文件是否存在let flag = fs.existsSync(absPath);if(!flag){//路径不存在,没有找到路径,需要加后缀//['.js', '.json'] => ['c:\users\desktop\a.js', 'c:\users\desktop\a.json']Object.keys(Module.extensions).map(key => current + key).filter(current => fs.existsSync(current)).join();//如果current为空if(!current){throw new Error('文件不存在');}}}//根据不同文件类型采取不同的方式Module.prototype.load = function(){//获取当前路径的拓展名let ext = path.extname(this.id);//console.log(ext);//.js//读取JS or 读取JSON 调用后缀对应的方法 传入当前模块Module.extensions[ext](this);}//调用对应模块后缀对应的方法Module.extensions = {'.js'(module){//读取JS文件let script = fs.readFileSync(module.id, 'utf-8');//用函数的方式把JS文件里的字符串包裹//node的API 可以替代eval方法//vm.runInThisContext(Module.wrapper[0] + script + Module.wrapper[1]);let fn = eval(Module.wrapper[0] + script + Module.wrapper[1]);//exports require, module, __filename, __dirnamefn.call(module.exports,module.exports,myRequire,module,module.id,path.dirname(module.id));//挂载当前模块的export上module.exports = JSON.parse(json);},'.json'(module){//读取JSON文件let json = fs.readFileSync(module.id, 'utf-8');console.log(json);//["xx":"xx", "xxx":"xxx"]//挂载当前模块的export上module.exports = JSON.parse(json);}:}//包装函数Module.wrapper = ['';(function(){','})()']//缓存模块Module._cache = {}myRequire('./a');
补充:策略模式是什么?
