如何限制网页中JavaScript文件间的访问?模块模式权限疑问
嘿,我来帮你把这个问题捋明白!首先直接回应你的核心疑问:你之前“只能完全开放或完全限制访问”的理解是不对的——我们有多种灵活的方式,既能用模块模式封装代码,又能精准控制哪些JavaScript文件可以访问封装的内容。
一、先修正你当前的模块模式写法
你现在的smiley.js用(this)作为导出对象,在浏览器环境里this就是全局的window对象,相当于直接把smiley函数挂到了全局作用域,所以所有脚本都能随便调用,这才让你觉得只能“完全开放”。我们先调整写法,把代码真正封装起来:
二、给特定脚本授予访问权限的两种常用方案
1. 闭包+显式授权(兼容旧浏览器)
利用闭包创建私有作用域,只通过一个授权方法给指定脚本开放接口:
修改后的smiley.js:
// 创建一个闭包,内部变量默认对外不可见 const SmileyModule = (function() { // 私有函数,只有内部能访问 function smiley(string) { return string + ' :)'; } // 定义允许访问的脚本标识(你可以自己约定规则,比如用文件名) const allowedScripts = ['play.js']; // 暴露授权方法,只有合法标识才能拿到接口 return { getAccess: function(scriptId) { if (allowedScripts.includes(scriptId)) { return { smiley: smiley }; } throw new Error('抱歉,你没有访问权限!'); } }; })();
对应的play.js需要主动申请权限:
// 用约定的标识申请访问 try { const { smiley } = SmileyModule.getAccess('play.js'); console.log(smiley('Hello')); // 正常输出 "Hello :)" } catch (err) { console.error(err.message); }
其他脚本如果用SmileyModule.getAccess('other.js')调用,就会抛出权限错误,实现了定向授权。
2. ES模块(现代浏览器推荐)
ES模块天生支持模块级作用域,只有显式export的内容才能被外部访问,而且通过import机制,只有明确导入的脚本才能获取接口:
修改smiley.js为ES模块:
// 私有函数,外部无法直接访问 function addSmiley(string) { return string + ' :)'; } // 只导出需要暴露的接口 export function smiley(string) { return addSmiley(string); }
play.js作为模块导入使用:
import { smiley } from './smiley.js'; console.log(smiley('Hello'));
HTML里要把脚本标记为模块类型:
<script type="module" src='smiley.js'></script> <script type="module" src='play.js'></script>
这种方式下,smiley函数不会暴露到全局作用域,只有通过import导入的脚本才能使用,完美实现了权限控制。
三、打破“只能二选一”的误解
你之前觉得只能完全开放或限制,是因为用了全局暴露的写法(把exports指向window)。实际上:
- 闭包可以帮我们把内部变量/函数隐藏起来,只暴露我们想开放的部分
- 通过显式授权或者ES模块的导入导出,我们可以精细控制哪些脚本能访问哪些接口,既不是全开放,也不是全封闭。
四、你的原始代码问题点回顾
你原来的smiley.js中(this)在浏览器里等价于window,所以exports.smiley = smiley就是把函数挂到了全局,自然所有脚本都能访问。换成上面的闭包或ES模块写法,就能解决这个问题。
内容的提问来源于stack exchange,提问作者jackdewinter

