前言在Linux或者MacOS系统中,ln命令是一个重要的命令。它的作用是为另一个位置的某个文件建立一个同步链接。对于前端,ln命令用的最多的地方就是全局安装,创建一个npm命令npmi-gxxx(nrm)回车的时候,上面的安装完成后,在输出中,会看到这样一串字符:/usr/local/bin/nrm->/usr/local/lib/node_modules/nrm/cli.js这串字符背后的意思是系统已经建立了到node_modules/nrm的软链接/cli.js/bin/nrm其实bin文件夹下的可执行命令基本都是以软链接的形式存在。ln的更多使用请参考菜鸟教程。下面将重点以路径A和B这两个例子来说明软硬链接和文件副本的区别:路径A:/user/wam/A/request.js路径B:/user/wam/B/request.jsrequest.js内容importutilsfrom'./utils';console.log('res:',utils.res());目录和文件然而,您可能在那里见过文件系统,这里以简单易懂的Linux为例。大多数Linux文件系统(如ext2、ext3)规定一个文件由一个目录、一个节点(inode)和一个数据块(block)组成:包括文件名和inode节点号。Inode:也称为文件索引节点,它包含了文件的基本信息和数据块所在的位置。block:包含文件的具体内容。当我们随便打开一个我们的开发项目,在命令行中输入ls-li,就可以看到目录和inode的对应信息了。下图中第一行是目录对应的inode。由于一个文件块的大小有限(通常为4kb),往往一个文件需要存储在多个文件块中,因此inode需要存储多个块的位置信息(如上图),以及一个inode本身只有128个Btyes的存储空间,所以文件块位置的存储也是通过block间接完成的,所以block可以理解为两种类型:文件内容块和inode信息块,你可以如果您了解这些,请继续。参考资料鸟哥Linux:磁盘分区鸟哥Linux:文件系统备份软链接软链接(softlink)也叫符号链接,相当于Windows系统中的快捷方式。eg:创建从A到B的软链接ln-s/user/wam/B/request.js/user/wam/A/request.js创建软链接的本质是为某个路径创建一个超链接(这里表示A是指向B)的超链接,它没有文件实体。当我们尝试打开路径A所在的文件时,最终会在编辑器中打开路径为B的文件,所以文件中的相对路径引用文件也是相对于路径B计算的,即utils文件路径为:/user/wam/B/utils.js删除文件B,再访问A,会发现索引不存在,无法访问。硬链接硬链接(hardlink),就是为源文件创建另一个索引。eg:创建一个从A到B的硬链接//少一个-s选项ln/user/wam/B/request.js/user/wam/A/request.js建立硬链接的本质是创建另一个文件entity要访问的路径索引。所以当我们尝试打开路径A所在的文件时,与软链接不同的是它最后在编辑器中打开路径A本身,所以文件中的相对路径引用文件也是相对于路径计算的A,即utils文件路径为:/user/wam/A/utils.js但值得一提的是,由于A和B路径都指向同一个源文件,因此对文件内容所做的编辑A路径会反映在B路径文件中,即两边文件的变化是同步的。当删除路径B时,源文件不会被垃圾回收,因为路径A仍然维护源文件的索引。硬链接和软链接还有一个区别:由于系统限制,硬链接要求路径在文件维度,而软链接可以是文件也可以是文件夹。文件复制,用过电脑的人应该都懂。eg:copyfileBtopathA//少一个-soptioncp-f/user/wam/B/request.js/user/wam/A/request.js文件复制是我们日常生活中最常见的操作,只是比较常见的形式是用ctrl+c/v代替cp命令(其实cp也可以实现ln链接的操作),其实质是复制一个文件实体,创建一个可访问的路径索引。所以当我们尝试打开A的路径所在的文件时,它指向的实体与B的不同(克隆),所以文件中的相对路径引用文件也是相对于路径A计算的,即,utils文件的路径为,与建立hard链接一致:/user/wam/A/utils.js由于A路径和B路径都指向自己的实体,A/B是独立的。当B被删除时,B对应的源文件会被回收,而A不会受到任何影响。神看JS对象和硬链接和软链接作为前端,我们都知道JS对象(object)是引用类型。引用类型的值是保存在内存中的对象。JS不允许直接访问内存中的位置,即不能直接操作对象的内存空间。当操作一个对象时,你实际上是在操作一个对该对象的引用,而不是实际的对象。为此,引用类型的值是通过引用来访问的。(摘自红皮书P87)你尝,你仔细尝。是不是觉得reference类型和我们上面说的文件链接和源文件很像。致:constB={a:1};所以当进行如下操作时:constC=B;C.a=2;console.log('B.a:',B.a);//2B.a=3;安慰。日志('C.a:',C.a);//3从上面的执行输出我们不难看出,JS中的引用类型变量赋值和硬链接是一回事。然后我们引入一个lodash深拷贝(cloneDeep)函数:import{cloneDeep}from'lodash';constC=cloneDeep(B);C.a=2;console.log('B.a:',B.a);//B.a:1B.a=3;console.log('C.a:',C.a);//C.a:2从上面的执行输出我们不难看出,JS中的深拷贝和文件拷贝是一回事。软链接如何在JS中描述?代理人?Proxy翻译成中文是代理,其实在性能上和硬链接是一致的,而硬链接和软链接在性能上最大的区别是:B(父)删除后,A(超链接)是无法访问。所以这不是正确的答案。正确答案是:WeakRef,弱引用。目前处于提案阶段,但已在最新版本的Chrome和Firefox中实现;看一个演示:letB={a:1};constC=newWeakRef(B);constregistry=newFinalizationRegistry(heldValue=>{console.log('GCworked:',heldValue);//GCworked:B//当B指向的值被垃圾回收时,将执行此回调console.log('C.a:',C.deref()?.a);//C.a:undefined});//注册B指向的值为垃圾回收的侦听器registry.register(B,"B");console.log('C.a:',C.deref().a);//C.a:1C.deref().a=2;//通过索引改变值console.log('B.a:',B.a);//B.a:2B.a=3;console.log('C.a:',C.deref().a);//C.a:3//截掉值索引,观察上面的GC回调B=null;//console.log('afterC.a:',C.deref()?.a);上面的JS代码似乎能勉强说明软链接的原理,但离理想还差得很远。让大家对ES新提案中的WeakRef和FinalizationRegistry有一个感性的认识。关于WeakRef的更多信息,请阅读https://v8.dev/features/weak-referencestc39/proposal-weakrefsWeakRefFinalizationRegistry结语通过这篇文章,你是否发现,这个世界上的一切都不是特别美好。虽是神言,但看完之后,希望你能有所收获。原文见:https://github.com/closertb/c...
