1.列举2中数组去重方法
去重1:利用indexof返回第一次下标是否存在,增加到一个新数组中
去重2:先利用sort将数组在第一位进行排序,然后比较数组相邻2个值,如果不相同就将之前一个放入新的数组中
去重3:循环数组,判断数组中每一个元素在数组中第一次出现的下标是不是当前下标,如果是的说明没有重复,增加到新数组中
2.数组的冒泡和快排
大神博客:https://www.cnblogs.com/beli/p/6297741.html
冒泡:比较2个数大小,前一个比后一个大则交换位置
第一轮的时候最后一个最大;
然后按照步骤1相邻2个数比较,由于最后一个已经比较了,所以不需要再比较了
快排:
2.for in和for of的区别
for in可以遍历数组上的原型属性,方法和数组的下标,
for in遍历对象的key比较合适
for of不能遍历对象
for of适合遍历数组的key
大神博客:https://www.jianshu.com/p/15859385eb24
3.一句话概括闭包,有什么作用
1、闭包是什么?
闭包时有权限访问 其他函数作用域的局部变量 的一个函数
这是《 JavaScript高级程序设计 》中给出的定义, 如果你想用一句话就把面试官搞定几乎是不可能的。
因为这句话还存在下面几个深入的问题:
为什么其他非闭包的函数,没有权限访问另一个函数的内部作用域
为什么闭包有这个权限
什么是函数作用域
面试官更想知道的是你是否知道上面的内容
更周全的解释方法:
由于在JS中,变量的作用域属于函数作用域,在函数执行后作用域就会被清理、内存也随之被收回,但是由于闭包时建立在一个函数内部的子函数,由于其可访问上级作用域的原因,即使上级函数执行完,作用域也不会随之销毁,这时的子函数---也就是闭包,便拥有了访问上级作用域中的变量的权限,即使上级函数执行完后,作用域内的值也不会被销毁。
稍微有些啰嗦,但是一分钟以内应该足够了。这样一来,面试官基本上了解了你对于上面三个知识点的是掌握的。
2、闭包解决了什么?
请放心,就凭上面那段话,面试官是不会善罢甘休的。他一定会继续追问,一般来说会问---闭包解决了什么问题。
阮一峰在他的博客中写到:在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
务实一点的说法应该是下面这样:
由于闭包可以缓存上级作用域,那么就使得函数外部打破了“函数作用域”的束缚,可以访问函数内部的变量。以平时使用的 AJAX 成功回调为例,这里其实就是个闭包,由于上述的特性,回调就拥有了整个上级作用域的访问和操作能力,提高了极大的便利。开发者不用去学钩子函数来操作上级函数作用域内部的变量了
闭包最大的用处有两个: 1) 一个是可以读取函数内部的变量;
2) 另一个就是让这些变量的值始终保存在内存中。
3、闭包有哪些应用场景
这个问题也极有可能被追问
闭包随处可见,一个 Ajax 请求的成功回调,一个事件绑定的回调方法,一个 setTimeout 的延时回调,或者一个函数内部返回另一个匿名函数,这些都是闭包。简而言之,无论使用何种方式对函数类型的值进行传递,当函数在别处被调用时,都有闭包的身影
4、使用闭包应该注意什么
代码难以维护:闭包内部是可以上级作用域,而如果闭包又是异步执行的话,一定要清楚上级作用域都发生了什么,而这样就需要对代码的运行逻辑和JS运行机制相当了解才能弄明白究竟发生了什么。
使用闭包的注意点:1) 由于闭包会使得函数中的变量都保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄漏。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
内存泄漏:程序的运行需要内存。对于持续运行的服务进程,必须及时释放不再用到的内存,否则占用越来越高,轻则影响系统性能,重则导致进程崩溃。不再用到的内存,没有及时释放,就叫做内存泄漏。
结果为2,3 结果为2,24.一句话概括primise,解决了哪些问题,没有primise,用什么解决异步回调问题
Promise对象用于异步操作,它表示一个尚未完成且预计在未来完成的异步操作。
关于Promise 的问题一览
什么是 promise
传统的回调式异步操作有什么缺点?(Promise是如何解决异步操作)
Promise中的异步模式有哪些?有什么区别?
如果想 Promise.all()和Promise.race()传递空数组,运行结果会有什么不同?
如何确保一个变量是可信任的 Promise(Promise.resolve方法传入不同值的处理有哪些)
Promise是如何捕获异常的?与传统的 try / catch 相比有什么优势?
解答如下:
1、什么是promise
下面的回答很像在背概念,但是很精辟
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的API ,各种异步操作都可以用同样的方法进行处理,让开发者不用关注于时序和底层的结果。Promise 的状态具有不受外界影响和不可逆两个特点。
2、传统的回调式异步操作有什么缺点?(Promise是如何解决异步操作)
传统的回调有五大信任问题:
1)调用回调过早
2)调用回调过晚(或没有被调用)
3)调用回调次数过少或过多
4)未能传递所需的环境和参数
5)吞掉可能出现的错误和异常
Promise 的解决办法:
1)调用回调过早
对于Promise 来说,即使是立即完成的 Promise 也无法被同步观察到,也就是说一个Promise调用 then() 的时候,即使这个 Promise 已经决议了,提供给 then的回调也总会被异步调用。
2)调用回调过晚(或没有被调用)
对于一个 Promise 对象注册每一个观察回调都是相对独立、互不干预的。而 Promise 对象调用 resolve() 和 reject() 时,每个注册的观察回调也都会被自动调用。所以这些观察回调的任意一个都无法影响或延误对其他回调的调用。
此外,关于回调未调用,正常情况下,没有任何东西可以阻止 Promise 想你通知它的决议,即使你的 js代码报错了,一会通过异常回调来获取到。如果Promise 永远不被决议的话, Promise 本身已提供了竞态的抽象机制来作为解决方案
3)调用回调次数过少或过多
promise 的定义方式使得它只能被决议一次。即使代码中出现多次决议,这个 Promise 也会接受第一次决议,并会忽略掉其他任何后续调用。所以任何通过 then() 注册的回调只会被调用一次
4)未能传递所需的环境和参数
凡是被决议的值,都会被传递到观察回调中,如果没有显示的决议也会传递一个 undefined 给观察回调。需要主要的是,Promise 只允许传一个决意值,其他值会被默默忽略掉
5)吞掉可能出现的错误和异常
如果在创建 Promise 时,存在 JS 代码错误,会直接导致该 Promise 的拒绝决议,那么你可以通过 reject() 来获取异常,代码中的任何异常都不会吞掉。
以上的回答十分的啰嗦,但是如果上面的五点都能记住的话,会了解很多关于 Promise 的细节问题,也会应对一些面试官的追问,如 Promise的 then()会不会被重复调用等。
3、Promise 中的异步模式有哪些?有什么区别?
这个问题会把面试者问懵。。。可以考虑另一种问法,或者直接进入下一个问题。
说一说 Promise.all( ) 和 Promise.race( ) 的区别。因为 ES6中的 Promise中只有这两个模式 all 和 race,其他的如 first、any、last等都是其他 Promise库提供的。
Promise.all( ) 和 Promise.race( ) 的区别
all会将传入的数组中的所有 Promise 全部决议以后,将决议值以数组的形式传入到观察回调中,任何一个 Promise决议为拒绝,那么就会调用拒绝回调
race会将传入的数组中的所有 promise 中第一个决议的决议值传递给观察回调,即使决议结果是拒绝的。
4、如果向Promise.all( ) 和 Promise.race( )传递空数组,运行结果会有什么不同?
all会立即决议,决议结果是 fullfilled, 值是 undefined
race会永远都不决议,程序卡死。。。
5、如何确保一个变量是可信任的Promise(Promise.resolve方法传入不同值的不同处理有哪些)
可以通过 Promise.resolve( )方法对不确定的值进行 Promise化,返回一个Promise对象。
如果是一个立即值,比如一个普通变量,那么该Promise会立即决议为成功
如果是一个Promise值,那么会将该Promise直接返回赋值给这个Promise,不会有额外开销
如果是一个类Promise值,比如其中含有名称为 then的成员变量,那么会将 then展开形成一个新的 Promise对象。
6、Promise是如何捕获异常的?与传统的 try / catch 相比有什么优势?
传统的 try / catch 捕获异常方式是无法捕获异步的异常的,代码如下
try{
setTimeout(function(){
undefined(); // undefined 不是一个方法,会抛出异常
},500)
} catch(err){
console.log(err)
}
而对于Promise对象来说,构造Promise实例时的代码如果出错,则会被认为是一个拒绝的决议,并会想观察回调中传递异常信息。所以即使是一个异步的请求,Promise也是可以捕获异常的,此外,Promise还可以通过 catch回调来捕获回调中的异常。
大神博客:http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html
5.js的基本类型:
(ES6之前)其中5种为基本类型:string,number,boolean,null,undefined,ES6出来的Symbol也是原始数据类型 ,表示独一无二的值。Object 为引用类型(范围挺大),也包括数组、函数
6.怎么实现浅拷贝
ES6:object.assign()
展开运算符…
7.怎么实现深拷贝
8.面向对象三大要素
9.js的节流和防抖
防抖:应用场景:
1.search搜索联想,用户在不断输入值时,用防抖来节约请求资源
2.window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次。
节流:
1.用户点击调教按钮,假设我们知道接口大致的返回时间的情况下,我们使用节流,只允许一定时间内点击一次。
2.监听滚动事件,比如是否滑到底部自动加载更多,并触发css动画,用throttle来判断。
10.本地存储
问题列表
常用的客户端存储方法有哪些?
cookie、sessionStorage和localStorage的区别
cookie由哪些部分组成?
如何用原生JS方法来操作cookie
在Hybrid环境下(混合应用),使用客户端存储应该注意哪些?
sessionStorage和localStorage存储的数据类型是什么?
session级存储中,session cookie和sessionStorage有哪些区别?
答案列表
1.常用的客户端存储方法有哪些?
平时前端开发中用到最多的是cookie、sessionStorage、localStorage,也有少量的业务场景会使用indexedDB。
2.cookie、sessionStorage和localStorage的区别
(敲黑板啦,这题必考)
很多博客上会提到此题,但是一般说的都很浅。我觉得可以从以下几个方面说:
存储时效来说:
cookie可以手动设置失效期,默认为会话级
sessionStorage的存储时长是会话级
localStorage的存储时长是永久,除非用户手动利用浏览器的工具删除
访问的局限性:
cookie可以设置路径path,所有他要比另外两个多了一层访问限制
localStorage和sessionStorage的访问限制是文档源级别,即协议、主机名和端口
还要注意的是,cookie可以通过设置domain属性值,可以不同二级域名下共享cookie,而Storage不可以,比如http://image.baidu.com的cookiehttp://map.baidu.com是可以访问的,前提是Cookie的domain设置为".http://baidu.com",而Storage是不可以的(这个很容易实验,就不细说了)
存储大小限制:
cookie适合存储少量数据,他的大小限制是个数进行限制,每个浏览器的限制数量不同
Storage的可以存储数据的量较大,此外他是通过占用空间大小来做限制的,每个浏览器的实现也是不同的,大家可以看这篇文章来进一进步了解Web Storage Support Test
操作方法:
cookie是作为document的属性存在,并没有提供标准的方法来直接操作cookie
Storage提供了setItem()和getItem()还有removeItem()方法,操作方便不易出错
其他:
cookie在发送http请求时,会将本地的cookie作为http头部信息传递给服务器
cookie可以由服务器通过http来设定
3.cookie由哪些部分组成?
大家一般都是用已有的库来操作cookie,很少有人利用原生方法直接操作cookie,所以cookie究竟由哪些部分也会被人忽视。
除了基础的键值对外,cookie还有下面的属性:
Expires :cookie最长有效期
Max-Age:在 cookie 失效之前需要经过的秒数。(当Expires和Max-Age同时存在时,文档中给出的是已Max-Age为准,可是我自己用Chrome实验的结果是取二者中最长有效期的值)
Domain:指定 cookie 可以送达的主机名。
Path:指定一个 URL 路径,这个路径必须出现在要请求的资源的路径中才可以发送 Cookie 首部
Secure:一个带有安全属性的 cookie 只有在请求使用SSL和HTTPS协议的时候才会被发送到服务器。
HttpOnly:设置了 HttpOnly 属性的 cookie 不能使用 JavaScript 经由Document.cookie属性、XMLHttpRequest和RequestAPIs 进行访问,以防范跨站脚本攻击(XSS)。
4.如何用原生JS方法来操作cookie
上面已经说过了,在浏览器中cookie做为document的一个属性存在,并没有提供原生的操作方法,并且所有形式都以字符串拼接的形式存储,需要开发利用字符串操作的方法来操作document.cookie,从而达到操作客户端cookie的目的。
想操作cookie,必须知道document.cookie中存储的字符串是怎样的结构。
document.cookie返回的结构大概如下面的样子:
name1=value1;name2=value2;name1=value3
即:document.cookie返回当前页面可用的(根据cookie的域、路径、失效时间和安全设置)所有cookie的字符串,一系列由分号隔开的名值对儿。
当想设置cookie时,可以直接对document.cookie赋值,对document.cookie赋值并不会覆盖掉cookie,除非设置的cookie已经存在。设置cookie的格式如下,和Set-Cookie头中的使用的格式是一样的。
name=value; expires=expiration_time; path=domain_path; domain=domain_name; secure
上面这些参数中,只有cookie中的名字和值是必须的。下面是一个简单的例子:
document.cookie='name=Roy';
此外,需要注意的是设置值时需要对于属性和值都用encodeURIComponent()来保证它不包含任何逗号、分号或空格(cookie值中禁止使用这些值).
5.在Hybrid环境下(混合应用),使用客户端存储应该注意哪些?
在混合应用中,主要是注意会话级存储——sessionStorage。
因为混合应用中的webview从一个页面跳转的另一个页面时,会话并没有像浏览器中那样是继承延续的,也就是说,当在A页面中设置的了sessionStorage值后跳转的下一个页面时,这是sessionStorage是全新的,根本获取不到A页面中设置的任何sessionStorage。
所以如果你们的app开发者还没有解决这个问题的话,建议这时使用session级别的cookie来代替sessionStorage,因为cookie是可以跨标签访问的,不要会话连续。
6.sessionStorage和localStorage存储的数据类型是什么?
sessionStorage和localStorage只能存储字符串类型的数据,如果setItem()方法传入的数据不是字符串的话,会自动转换为字符串类型再进行存储。所以在存储之前应该使用JSON.stringfy()方法先进行一步安全转换字符串,取值时再用JSON.parse()方法再转换一次。
7.session级存储中,session cookie和sessionStorage有哪些区别?
详细的分析可以看 :https://zhuanlan.zhihu.com/p/31404516
大体的概括就是说:
sessionStorage的会话基于标签,即标签关闭则会话终止,而cookie基于浏览器进程。
sessionStorage的访问必须基于会话继承和延续,即只有在当前标签下或当前标签打开的标签下可以访问sessionStorage中的数据,而cookie是可以跨标签进行访问的。
网友评论