前端面试题合集1-5(浏览器缓存方式,js数据类型详解,闭包详解,Promise解析,跨域以及解决方式详解)

一.cookie,sessionStorage,localStorage区别

cookie,sessionStorage,localStorage都是浏览器的本地存储。
共同点

  • 它们都是存储在浏览器本地的。

区别

  • cookie是由服务器端写入的,而sessionStorage和localStorage都是由前端写入的
  • cookie的生命周期在服务器端写入时就已经设置好了的;localStorage一旦写入就会永久存在,除非手动清除;sessionStorage是页面关闭的时候就会自动清除。
  • cookie存储空间比较小,大概4KB;sessionStorage和localStorage比较大,大概5MB
  • Cookie、SessionStorage、 LocalStorage数据共享都遵循同源原则,SessionStorage还限制必须是同一个页面。
  • 在前端给后端发送请求的时候会自动携带Cookie中的数据,但是SessionStorage、 LocalStorage不会。

由于它们的以上区别,所以它们的应用场景也不同:
Cookie一般用于存储登录验证信息SessionID或者token;
LocalStorage常用于存储不易变动的数据,减轻服务器的压力;
SessionStorage可以用来检测用户是否是刷新进入页面,如音乐播放器恢复播放进度条的功能。

详细的相关介绍请参考:
w3c手册上Storage的介绍以及使用:
https://www.w3school.com.cn/jsref/api_storage.asp
一篇写的比较全面的localStorage介绍:
https://www.cnblogs.com/st-leslie/p/5617130.html
es6用户使用js-cookie插件介绍:
https://www.jianshu.com/p/6e1bacd35f59

二. JS数据类型有哪些?

JS数据类型分为两类

  • 基本数据类型(也叫简单数据类型),包含7种类型,分别是:
    Number,String,Boolean,Null,Undefined,Symbol,BigInt。
  • 另一类是引用数据类型也叫复杂数据类型,通常用Object代表(普通对象,数组,正则,日期,Math数学函数都属于Object)。

数据分成两大类的本质区别:

基本数据类型和引用数据类型它们在内存中的存储方式不同

  • 基本数据类型是直接存储在栈中的简单数据段,占据空间小,属于被频繁使用的数据。
  • 引用数据类型是存储在堆内存中,占据空间大。引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址,当解释器寻找引用值时,会检索其在栈中的地址,取得地址后从堆中获得实体。

扩展:
(1) Symbol是ES6新出的一种数据类型,这种数据类型的特点就是没有重复的数据,可以作为object的key。
数据的创建方法:

 const symbol1 = Symbol('foo')

因为它的构造不完整,所以不能使用new Symbol()创建数据。
由于Symbol()创建的数据具有唯一性,所以Symbol()!==Symbol()。
同时使用Symbol数据作为key不能使用for获取到这个key值,需要使用Object.getOwnPropertySymbols(obj)获得这个obj对象中key类型是Symbol的key值。

let key = Symbol('key');
let obj = { [key]: 'symbol'};
let keyArray = Object.getOwnPropertySymbols(obj); // 返回一个数组[Symbol('key')]
obj[keyArray[0]] // 'symbol'

MDN上对于Symbol的介绍(比较官方化):
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Symbol
阮一峰ES6教程中对Symbol介绍的比较详细:
https://es6.ruanyifeng.com/#docs/symbol
一篇通俗易懂的symbol简单介绍:
https://www.zhangxinxu.com/wordpress/2018/04/known-es6-symbol-function/
(2)BigInt也是ES6新出的一种数据类型,这种数据类型的特点就是数据涵盖的范围大,能够解决超出普通数据类型范围报错的问题。
Number的范围:
JavaScript中Number范围为正负2的53次方,
也即从最小值-9007199254740992到最大值+9007199254740992之间的范围,
BigInt可以处理超出Number范围的数。
使用:
可以用在一个整数字面量后面加 n 的方式定义一个 BigInt ,如:10n,或者调用函数 BigInt()(但不包含 new 运算符)并传递一个整数值或字符串值。

const theBiggestInt = 9007199254740991n;

const alsoHuge = BigInt(9007199254740991);
// ↪ 9007199254740991n

const hugeString = BigInt("9007199254740991");
// ↪ 9007199254740991n

const hugeHex = BigInt("0x1fffffffffffff");
// ↪ 9007199254740991n

const hugeBin = BigInt("0b11111111111111111111111111111111111111111111111111111");
// ↪ 9007199254740991n
  • 注意:BigInt和Number之间不能进行混合操作。
    可以看到咱们控制台的运算结果报的错误。
    在这里插入图片描述

一篇比较好的BigInt基本介绍:
https://segmentfault.com/a/1190000019912017
来自MDN官方介绍:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/BigInt

三. 如何理解闭包

一个函数和词法环境的引用捆绑在一起,这样的组合就是闭包(closure)。

说通俗点,闭包其实就是一个函数,一般就是一个函数A,return其内部的函数B,被return出去的B函数能够在外部访问A函数内部的变量,这时候就形成了一个B函数的变量背包,A函数执行结束后这个变量背包也不会被销毁,并且这个变量背包在A函数外部只能通过B函数访问。

闭包形成的原理作用域链,当前作用域可以访问上级作用域中的变量。

闭包解决的问题:能够让函数作用域中的变量在函数执行结束之后不被销毁,同时也能在函数外部可以访问函数内部的局部变量。

闭包带来的问题:由于垃圾回收器不会将闭包中变量销毁,于是就造成了内存泄露,内存泄露积累多了就容易导致内存溢出

闭包的应用: 能够模仿块级作用域,能够实现柯里化,在构造函数中定义特权方法、Vue中数据响应式Observer中使用闭包等。
相关详细文章:
https://segmentfault.com/a/1190000023356598
https://segmentfault.com/a/1190000023425946

四. Promise是什么?使用方法?

Promise的作用: Promise是异步微任务,解决了异步多层嵌套回调的问题,让代码的可读性更高,更容易维护。

Promise使用: Promise是ES6提供的一个构造函数,可以使用Promise构造函数new一个实例,Promise构造函数接收一个函数作为参数,这个函数有两个参数,分别是两个函数 resolverejectresolve将Promise的状态由等待变为成功,将异步操作的结果作为参数传递过去;reject则将状态由等待转变为失败,在异步操作失败时调用,将异步操作报出的错误作为参数传递过去。实例创建完成后,可以使用then方法分别指定成功或失败的回调函数,也可以使用catch捕获失败,then和catch最终返回的也是一个Promise,所以可以链式调用。
Promise的特点:
(1) 对象的状态不受外界影响(Promise对象代表一个异步操作,有三种状态)。 - pending(执行中) - Resolved(成功,又称Fulfilled) - rejected(拒绝) 其中pending为初始状态,fulfilled和rejected为结束状态(结束状态表示promise的生命周期已结束)。
(2) 一旦状态改变,就不会再变,任何时候都可以得到这个结果。 Promise对象的状态改变,只有两种可能(状态凝固了,就不会再变了,会一直保持这个结果): - 从Pending变为Resolved - 从Pending变为Rejected
(3) resolve 方法的参数是then中回调函数的参数,reject 方法中的参数是catch中的参数
(4) then 方法和 catch方法 只要不报错,返回的都是一个fullfilled状态的promise
Promise的其他方法:
Promise.resolve() :返回的Promise对象状态为fulfilled,并且将该value传递给对应的then方法。
Promise.reject():返回一个状态为失败的Promise对象,并将给定的失败信息传递给对应的处理方法。
Promise.all():返回一个新的promise对象,该promise对象在参数对象里所有的promise对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则立即触发该promise对象的失败。
Promise.any():接收一个Promise对象的集合,当其中的一个 promise 成功,就返回那个成功的promise的值。
Promise.race():当参数里的任意一个子promise被成功或失败后,父promise马上也会用子promise的成功返回值或失败详情作为参数调用父promise绑定的相应句柄,并返回该promise对象。

五. 跨域是什么?如何解决?

跨域:当前页面中某个接口请求的地址和当前页面的地址,如果协议,域名,端口其中有一项不同,就说名该接口跨域了。
跨域限制的原因:浏览器为了保证网页的安全,出的同源协议策略。
跨域解决方案

  1. cors 通过服务端设置允许跨域实现
    如设置:res.setHeader(‘Acess-Control-Allow-Origin’,‘*’);
    res.setHeader(“Access-Control-Allow-Methods”, “GET, PUT, OPTIONS, POST”);
  2. JSONP (比较老了,据说是当年的程序猿想出的临时解决方法)
    原理:script标签可以跨域请求资源,将回调函数作为参数拼接在url中。后端收到该请求,拼接成回调函数并且调用,将数据作为参数返回出去,前端运行script就能拿到后端返回的资源。
  3. 代理
    如node中间件,niginx反向代理,当然还有我们常用的proxyLight。
    原理:虽然跨域限制的时候浏览器不能跨域访问服务器,但是node中间件和其他代理方式都是让请求发给代理服务器,静态页面和代理服务器是同源的,然后代理服务器再向后端服务器发起请求,服务器和服务器之间没有同源策略。
  4. postMessage: H5新增的API,通过发送和接受API实现跨域通信。
    mdn上的解释是:
    window.postMessage() 方法可以安全地实现跨源通信。通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为 https),端口号(443 为 https 的默认值),以及主机 (两个页面的模数 Document.domain设置为相同的值) 时,这两个脚本才能相互通信。window.postMessage() 方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。
    使用方法:
    发送数据用postMessage,接收数据是监听message事件:element.addEventListener(‘message’, callback)
    如:otherWindow.postMessage(message, targetOrigin, [transfer]);
    window.addEventListener(‘message’, function (e) {})
    message 的属性有:
    data
    从其他 window 中传递过来的对象。
    origin
    调用 postMessage 时消息发送方窗口的 origin . 这个字符串由 协议、“😕/“、域名、“ : 端口号”拼接而成。例如 “https://example.org (隐含端口 443)”、“http://example.net (隐含端口 80)”、“http://example.com:8080”。请注意,这个 origin 不能保证是该窗口的当前或未来 origin,因为 postMessage 被调用后可能被导航到不同的位置。
    source
    对发送消息的窗口对象的引用;
    这里引用mdn官方原话,很好解释了使用postMessage时候的安全问题。
    安全问题:
    如果不希望从其他网站接收 message,请不要为 message 事件添加任何事件侦听器。 这是一个完全万无一失的方式来避免安全问题。

如果希望从其他网站接收 message,请始终使用 origin 和 source 属性验证发件人的身份。 任何窗口(包括例如 http://evil.example.com)都可以向任何其他窗口发送消息,并且您不能保证未知发件人不会发送恶意消息。 但是,验证身份后,您仍然应该始终验证接收到的消息的语法。 否则,您信任只发送受信任邮件的网站中的安全漏洞可能会在您的网站中打开跨网站脚本漏洞。

当使用 postMessage 将数据发送到其他窗口时,始终指定精确的目标 origin,而不是*。 恶意网站可以在您不知情的情况下更改窗口的位置,因此它可以拦截使用 postMessage 发送的数据。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

godlike-icy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值