[1, [2, 3, [4, 5]]]------ > [1, 2, 3, 4, 5];
递归法:
function flatten(arr) { let res = []; arr.map((item) => { if (Array.isArray(item)) { res = res.concat(flatten(item)); } else { res.push(item); } }); return res; }
Service Worker 是运行在浏览器背后的独立线程,一般可以用来实现缓存功能。使用 Service Worker 的话,传输协议必须为 HTTPS。因为 Service Worker 中涉及到请求拦截,所以必须使用 HTTPS 协议来保障安全。
Service Worker 实现缓存功能一般分为三个步骤:首先需要先注册 Service Worker,然后监听到 install 事件以后就可以缓存需要的文件,那么在下次用户访问的时候就可以通过拦截请求的方式查询是否存在缓存,存在缓存的话就可以直接读取缓存文件,否则就去请求数据。以下是这个步骤的实现:
// index.js if (navigator.serviceWorker) { navigator.serviceWorker .register("sw.js") .then(function (registration) { console.log("service worker 注册成功"); }) .catch(function (err) { console.log("servcie worker 注册失败"); }); } // sw.js // 监听 `install` 事件,回调中缓存所需文件 self.addEventListener("install", (e) => { e.waitUntil( caches.open("my-cache").then(function (cache) { return cache.addAll(["./index.html", "./index.js"]); }) ); }); // 拦截所有请求事件 // 如果缓存中已经有请求的数据就直接用缓存,否则去请求数据 self.addEventListener("fetch", (e) => { e.respondWith( caches.match(e.request).then(function (response) { if (response) { return response; } console.log("fetch source"); }) ); });
Proxy 是 ES6 中新增的功能,它可以用来自定义对象中的操作。 Vue3.0 中将会通过 Proxy 来替换原本的 Object.defineProperty 来实现数据响应式。
let p = new Proxy(target, handler);
target
代表需要添加代理的对象,handler
用来自定义对象中的操作,比如可以用来自定义 set 或者 get 函数。
let onWatch = (obj, setBind, getLogger) => { let handler = { set(target, property, value, receiver) { setBind(value, property); return Reflect.set(target, property, value); }, get(target, property, receiver) { getLogger(target, property); return Reflect.get(target, property, receiver); }, }; return new Proxy(obj, handler); }; let obj = { a: 1 }; let p = onWatch( obj, (v, property) => { console.log(`监听到属性${property}改变为${v}`); }, (target, property) => { console.log(`'${property}' = ${target[property]}`); } ); p.a = 2; // 控制台输出:监听到属性a改变 p.a; // 'a' = 2
因为可以自定义 Hooks, 我们可以非常方便的复用状态逻辑。
// 定时器DEMO function useCount(defaultCount) { const [count, setCount] = useState(defaultCount); const timer = useRef(); useEffect(() => { timer.current = setInterval(() => { setCount((count) => count + 1); }, 1000); }, []); useEffect(() => { if (count >= 10) { clearInterval(timer.current); } }); return [count]; } function App() { const [count] = useCount(0); return ( <> <h1>count: {count}</h1> </> ); }