从基础到进阶,测试你有多了解 JavaScript,刷新你的知识,或者帮助你的 coding 面试!
答案在问题下方的折叠部分,点击即可展开问题。祝你好运
function sayHi() { console.log(name) console.log(age) var name = 'Lydia' let age = 21 } sayHi()
Lydia
和 undefined
Lydia
和 ReferenceError
ReferenceError
和 21
undefined
和 ReferenceError
在函数内部,我们首先通过 var
关键字声明了 name
变量。这意味着变量被提升了(内存空间在创建阶段就被设置好了),直到程序运行到定义变量位置之前默认值都是 undefined
。因为当我们打印 name
变量时还没有执行到定义变量的位置,因此变量的值保持为 undefined
。
通过 let
和 const
关键字声明的变量也会提升,但是和 var
不同,它们不会被初始化。在我们声明(初始化)之前是不能访问它们的。这个行为被称之为暂时性死区。当我们试图在声明之前访问它们时,JavaScript 将会抛出一个 ReferenceError
错误。
for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 1) } for (let i = 0; i < 3; i++) { setTimeout(() => console.log(i), 1) }
0 1 2
和 0 1 2
0 1 2
和 3 3 3
3 3 3
和 0 1 2
由于 JavaScript 的事件循环,setTimeout
回调会在遍历结束后才执行。因为在第一个遍历中遍历 i
是通过 var
关键字声明的,所以这个值是全局作用域下的。在遍历过程中,我们通过一元操作符 ++
来每次递增 i
的值。当 setTimeout
回调执行的时候,i
的值等于 3。
在第二个遍历中,遍历 i
是通过 let
关键字声明的:通过 let
和 const
关键字声明的变量是拥有块级作用域(指的是任何在 {} 中的内容)。在每次的遍历过程中,i
都有一个新值,并且每个值都在循环内的作用域中。
[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"); }) ); });