Skip to content

位运算实现权限组合

用位运算实现权限组合【渡一教育】_哔哩哔哩_bilibili
目标:使用一串二进制数字来表示当前用户的权限情况。
主要实现的技巧是使用一个某一位为1的二进制数字表示某个权限的开启,然后使用「与运算(&)」计算这个数字和表示全部权限状态的二进制数字,就可以得到该权限的开启情况。
同时还可以通过「按位或运算(|)」进行权限的开启,和「按位异或运算(^)」进行权限的切换。

ts
// 使用二进制数据进行权限控制

/** 是否可读 */
const canRead = 0b0001;
/** 是否可写 */
const canWrite = 0b0010;
/** 是否可执行 */
const canExecute = 0b0100;

/**
 * 检查是否有某个权限
 * @param permission 权限码
 */
function checkPermission(permission: number, permissionCode: number) {
  // 只要对应位上不是1,则进行与运算,结果一定为0
  return permission & permissionCode;
}

/** 切换某个权限 */
function togglePermission(permission: number, permissionCode: number): number {
  // 按位异或运算,其中一个为1,另一个为0,结果为1,反之为0。
  // 所以,不是该权限位的值都会保留原有的值,而该权限对应的位因为permissionCode上对应的位为1,所以会被切换。
  return permission ^ permissionCode;
}

/** 开启或关闭某个权限 */
function setPermission(
  permission: number,
  permissionCode: number,
  enable: boolean,
): number {
  return enable ? permission | permissionCode : permission & ~permissionCode;
}

/** 只有可读权限 */
const readOnlyPermission = 0b0001;
/** 只有可读和可写权限 */
const readWritePermission = 0b0011;
/** 只有可读、可写和可执行权限 */
const readWriteExecutePermission = 0b0111;

console.log('readOnlyPermission', checkPermission(readOnlyPermission, canRead)); // true
console.log(checkPermission(readOnlyPermission, canWrite)); // false
console.log(checkPermission(readOnlyPermission, canExecute)); // false
console.log(setPermission(readOnlyPermission, canWrite, true).toString(2)); // 11
console.log(setPermission(readOnlyPermission, canExecute, true).toString(2)); // 101
console.log(setPermission(readOnlyPermission, canRead, false).toString(2)); // 0

console.log(checkPermission(readWritePermission, canRead)); // true
console.log(checkPermission(readWritePermission, canWrite)); // true
console.log(checkPermission(readWritePermission, canExecute)); // false

console.log(checkPermission(readWriteExecutePermission, canRead)); // true
console.log(checkPermission(readWriteExecutePermission, canWrite)); // true
console.log(checkPermission(readWriteExecutePermission, canExecute)); // true

手写bind函数

手写bind函数【渡一教育】_哔哩哔哩_bilibili
核心在于两点:

  • 使用applycall方法实现返回的函数运行时会绑定新的上下文;
  • 使用new.target判断是否通过new进行函数调用的,如果是,则返回通用通过new调用的结果,否则返回函数执行的结果;

this指向

this 指向【渡一教育】_哔哩哔哩_bilibili
重点是this是存在于执行上下文中的,也只有在函数执行时才会产生执行上下文,也才会产生this

数组去重方法实现

你不知道的数组去重【渡一教育】_哔哩哔哩_bilibili
核心思路:

  • 逐个遍历数组元素的属性,查找剩余的数组元素中的有没有完全相同的。
  • 两个值如果有一个是基本数据类型,直接使用Object.is()进行判断`;
  • 非基本数据类型,先判断内容长度;
  • 具体每个属性的比对,遵循上面的逻辑;

使用预加载优化接口响应时间

说个你没见过的白屏优化方案 /dog_哔哩哔哩_bilibili
如果有个参数固定的get接口是必定会调用,且影响后续的页面加载或功能执行的。可以使用<a>标签,设置ref属性为prefetch让这个接口提前调用,并且缓存返回值,这样在后续调用改接口时,浏览器就会使用之前的缓存的结果(如果之前的接口还没完成返回,那就会等待完成)。
但是需要注意,这个方法有以下缺点:

  • 不支持get以外的请求;
  • 不支持动态配置参数,token相关的参数最好通过cookie进行传递;
  • 浏览器的缓存策略会受到响应头中相关字段的配置影响;

控制CSS animation的播放暂停

animation-play-state - CSS:层叠样式表 | MDN
使用animation-play-state属性进行控制

CSS的层叠规则

层叠规则【渡一教育】_哔哩哔哩_bilibili
当同一个元素出现相同的CSS属性定义时,就会根据特定的规则进行比较,从而确定最终使用的CSS属性。比较的优先级为:

  • 优先级:
    • 作者样式表 !import
    • 默认样式表!import
    • 作者样式表;
    • 默认样式表;
  • 特殊性
    • 行内样式;
    • id选择器;
    • 类、伪类选择器;
    • 元素选择器;
  • 源次序 这里面作者样式表即自己编写的CSS样式,默认样式表即浏览器自带的样式。特殊性即常说的权重,其中的选择器可以通过重复出现来增加权重。源次序即样式代码出现的先后顺序(注意,标签内添加的class或id的先后次序不影响源次序)。