面试题答案
一键面试设计思路
- 利用闭包封装状态:通过闭包将全局状态数据封装在一个函数内部,对外只暴露特定的访问和修改方法,这样可以防止外部直接访问和修改状态,提高数据安全性。
- 属性特性实现权限控制:使用JavaScript的属性特性(如
Object.defineProperty()
)来定义访问器属性(getter和setter),在这些访问器中根据运行环境和用户权限进行相应的权限检查,实现细粒度的权限控制。 - 模块间状态共享:将封装状态和操作方法的对象作为一个单例模块导出,各个模块引入该模块来共享状态数据。
利用属性特性实现细粒度权限控制
通过Object.defineProperty()
定义访问器属性时,在getter和setter中添加权限判断逻辑。例如,根据用户角色判断是否有权限获取或修改某个状态值。
不同模块间状态共享和管理
- 创建状态管理模块:
// stateManager.js
let _state = {
// 假设这里是全局状态数据
sensitiveData: 'default value',
userRole: 'guest'
};
const stateManager = (function () {
function checkPermission(role, requiredRole) {
// 简单的权限判断逻辑,实际应用中可能更复杂
return role === requiredRole;
}
function getState() {
return _state;
}
function setState(newState) {
if (checkPermission(_state.userRole, 'admin')) {
_state = { ..._state, ...newState };
} else {
throw new Error('Permission denied');
}
}
// 使用属性特性定义访问器属性
Object.defineProperty(_state, 'publicData', {
get: function () {
return this.sensitiveData;
},
set: function (value) {
if (checkPermission(this.userRole, 'admin')) {
this.sensitiveData = value;
} else {
throw new Error('Permission denied');
}
}
});
return {
getState,
setState
};
})();
export default stateManager;
- 在其他模块中使用:
// otherModule.js
import stateManager from './stateManager.js';
// 获取状态
const state = stateManager.getState();
console.log(state.publicData);
// 修改状态(只有admin角色能修改)
try {
stateManager.setState({ sensitiveData: 'new value' });
} catch (error) {
console.error(error.message);
}
代码解释
stateManager
模块:- 使用闭包将
_state
数据和操作方法封装起来,外部无法直接访问和修改_state
。 checkPermission
方法用于简单的权限判断。getState
方法返回当前状态对象,setState
方法用于更新状态,但会进行权限检查。- 使用
Object.defineProperty
为_state
对象定义了publicData
访问器属性,在getter和setter中进行权限控制。
- 使用闭包将
otherModule
模块:通过导入stateManager
模块来获取和修改共享状态数据,在操作过程中会触发权限控制逻辑。