前端面试题分享一
1. forEach如何跳出循环?
forEach()为每个数组元素执行一次callback函数;与map()或者reduce不同的是,它总返回undefined值,并且不可链式调用。其典型用例是在一个调用链子的最后执行副作用(side effects,函数式编程上,指函数进行返回结果值以外的操作)。
不会改变原数组。
forEach
不会直接改变调用它的对象,但是那个对象可能会被 callback
函数改变。
forEach使用break和continue会报错,如果要实现continue的效果,可以直接return
除了抛出异常以外,没有办法中止或跳出forEach循环。如果你需要中止或跳出循环,forEach方法不是应当使用的工具。
如果你需要提前中止循环,你可以使用:
- 一个简单的 for 循环
- for...of / for...in 循环
Array.prototype.every()
Array.prototype.some()
Array.prototype.find()
Array.prototype.findIndex()
这些数组方法则可以对数组元素判断,以便确定是否需要继续遍历:
实例:
function getItemById(arr, id) { var item = null; try { arr.forEach(function (curItem, index) { if (curItem.id == id) { item = curItem; throw Error(); } }) } catch (e) { } return item; }
在外套一层try{}catch(){}
forEach的优势一个是它的回调函数形成了一个作用域,它的curItem和index不会像for循环一样污染全局变量,再一个是更容易写出来函数式的代码,和map、filter、reduce这些高阶函数是一脉相承的。
forEach()本身无法跳出循环,必须遍历所有的数据才能结束。
如果 thisArg
参数有值,则每次 callback
函数被调用时,this
都会指向 thisArg
参数。如果省略了 thisArg
参数,或者其值为 null
或 undefined
,this
则指向全局对象。按照函数观察到 this
的常用规则,callback
函数最终可观察到 this
值。
2. 用一句话描述 JS 异常是否能被 try catch 到?
能被 try catch 捕捉到的异常,必须是在报错的时候,线程执行已经进入 try catch 代码块,且处在 try catch 里面,这个时候才能被捕捉到。
function a(){ return new Promise((resolve, reject) =>{ setTimeout(() => { reject(1); }) }) } try{ await a(); }catch(e){ console.log('error',e); } console.log(111); //output error 1
Promise 在执行回调中都用 try catch 包裹起来了,其中所有的异常都被内部捕获到了,并未往上抛异常。
function a(){ return new Promise((resolve, reject) =>{ setTimeout(() => { reject(1); }) }) } try{ await a(); }catch(e){ console.log('error',e); } console.log(111); //output error 1
这个例子的异常被 catch 捕获到了,那么这里的 Promise 为啥能捕获到异常呢?
报错的时候(setTimeout 里面的 reject),线程执行已经进入 try catch 代码块,但是并未执行完成,这样的话当然可以捕获到异常。await 是将代码执行停留在 try catch 代码块里面。
事实上,Promise 的异常都是由 reject 和 Promise.prototype.catch 来捕获,不管是同步还是异步。
Promise没有异常,不要用 try catch 包裹 Promise , Promise 很强大,不用担心异常会往上抛!我们只需要给 Promise 增加 Promise.prototype.catch 就 OK 了
function a(){ return new Promise((resolve, reject) =>{ setTimeout(() => { reject(1); }) }) } try{ await a(); }catch(e){ console.log('error',e); } console.log(111); //output error 1
3. localStorage(存储大小,怎么判断localStorage存满了)
一般为5M,或者更大
(function(){ if(!window.localStorage) { console.log('浏览器不支持localStorage'); } var size = 0; for(item in window.localStorage) { if(window.localStorage.hasOwnProperty(item)) { size += window.localStorage.getItem(item).length; } } console.log('当前localStorage已使用容量为' + (size / 1024).toFixed(2) + 'KB'); })()
上面的代码可以得到localStorage的已使用的容量
一些小题目:
1、a.meituan.com 和 b.meituan.com 这两个域能够共享同一个 localStorage 吗?
2、在 webview 中打开一个页面:i.meituan.com/home.html,点击一个按钮,调用 js 桥打开一个新的 webview:i.meituan.com/list.html,这两个分属不同 webview 的页面能共享同一个 localStorage 吗?
3、如果 localStorage 存满了,再往里存东西,或者要存的东西超过了剩余容量,会发生什么?
答案
1、同一个域名(document.domain)共享同一个 localStorage,a.meituan.com 和 b.meituan.com 是两个域名,所以不能共享
2、能。相当于同一个浏览器的不同标签页。不同浏览器之间不能共享。
3、存不进去并报错(QuotaExceededError)