前端面试题分享一

1. forEach如何跳出循环?

forEach()为每个数组元素执行一次callback函数;与map()或者reduce不同的是,它总返回undefined值,并且不可链式调用。其典型用例是在一个调用链子的最后执行副作用(side effects,函数式编程上,指函数进行返回结果值以外的操作)。

不会改变原数组。

forEach 不会直接改变调用它的对象,但是那个对象可能会被 callback 函数改变。

forEach使用break和continue会报错,如果要实现continue的效果,可以直接return

除了抛出异常以外,没有办法中止或跳出forEach循环。如果你需要中止或跳出循环,forEach方法不是应当使用的工具。

如果你需要提前中止循环,你可以使用:

这些数组方法则可以对数组元素判断,以便确定是否需要继续遍历:

实例:

  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 或 undefinedthis 则指向全局对象。按照函数观察到 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)

 



 

上一篇:vue中使用localStorage存储信息


下一篇:Vue 打包部署,自动清理缓存