如果你最近想要换工作或者巩固一下自己的前端知识基础,不妨和我一起参与到每日刷题的过程中来,如何?
第13天要刷的手写题如下:
-
不使用临时变量交换两数的值
-
实现一个简单的双向数据绑定
-
实现一个简单的哈希路由
下面是我自己写的答案:
1. 不使用临时变量交换变量的值
如果是交换两个整数的值:
let a =20;
let b =15;
a = a ^ b;
b = a ^ b;
a = a ^ b;
如果是交换两个number的值:
let a =20.1;
let b =15.1;
a = a + b;
b = a - b;
a = a - b;
交换两个变量的值:
[a ,b] = [b, a];
[arr[i], arr[j]] = [arr[j], arr[i]];
2. 实现一个简单的双向数据绑定功能
分以下步骤进行:
-
创建展示需要的数据结构obj和input以及span标签
-
通过propertyDescriptor设置obj的setter和getter
-
监听input的keyup事件,在其回调中实现obj的setter
const obj = {};
const input = document.createElement('input');
const span = document.createElement('span');
Object.defineProperty(obj, 'text', {
configurable: true,
set(v) {
span.innerText = v;
input.value = v;
},
});
input.addEventListener('keyup', (e) => {
obj.text = e.target?.value;
});
document.body.append(input, span);
-
需要注意的点:setter和writable或者value不能同时出现在propertyDescriptor中!
-
也就是说使用PropertyDescriptor的setter和addEventListener是可以实现数据的双向绑定的!
升级版本:使用Proxy -- 唯一的区别就是将Object.defineProperty
换成了const proxyObh = new Proxy(obj, {})
const obj = { text: '' };
const input = document.createElement('input');
const span = document.createElement('span');
const proxyObj = new Proxy(obj, {
set(target, key, value) {
target[key] = value;
if (key === 'text') {
span.innerText = value;
input.value = value;
}
return true;
},
});
input.addEventListener('keyup', (e) => {
proxyObj.text = e.target?.value;
});
document.body.append(input, span);
最直观的升级就是,可以对obj的多个属性进行一次性的绑定了,尽管使用Object.defineProperties也可以达到相同的效果!
3. 实现简单的哈希路由
-
首先必须明确,实现哈希路由到底是在问什么?
-
也就是哈希路由的本质是什么。对于这道题来说,它实际上是想问:在页面的哈希值发生变化的时候能够执行预先存储的回调函数
- 所以需要实现两个功能:
-
-
预先存储路由和对应的回调函数
-
-
-
当路由地址发生变化的时候能够找到当前的url对应的回调并执行
-
-
- 根据上面的分析,需要构件的类中应该包括如下的属性和方法:
-
routes: 是一个哈希表,存放的是路由地址和回调之间的关系
-
currentHash:当前的路由地址
-
storeRoute (path, cb):将路由地址和回调函数对应起来
-
freshRoute ():调用当前路由地址对应的回调函数
-
最后监听window上的load时间和hashchange事件,当事件发生的时候调用freshRoute方法
-
class Route {
constructor () {
this.routes ={};
this.currentHash = '';
window.addEventListener('load', this.refresh, false);
window.addEventListener('hashchange', this.refresh, false);
}
store (path, cb) {
this.routes[path] = cb ?? Function();
}
refresh () {
this.currentHash = location.hash.slice(1) || '/';
this.routes[this.currentHash]();
}
}