【金三银四】一个问题就知道你看没看过源码了 深度挖掘必问源码题
引言
金三银四,特地整理一份面试题,现介绍本文特色:
1、适合前端,需要面试找工作
2、即将毕业面临实习,积累经验
3、从务实基础到彻底弄懂
4、探索框架源码,研究前端必备算法
5、直击阿里、腾讯、美团、今日头条等大厂原题,逐步引入
6、学完即准备投简历
BAT/TMD这样的大公司是如何面试的
注意嗷,在这里TMD可不是骂人的话哦,可能你知道BAT,但TMD你知道么?(不知道赶紧去百度!)
T(今日头条)M(美团)D(滴滴)成为了BAT之后互联网江山的新巨头
相关文章
【金三银四】一个问题就知道你会不会JS了 阿里、头条真题解析
上期遗漏的知识拓展
在上一篇关于JS真题,最后忘记对知识进行拓展了,因此在这里进行补充
第一题
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>面试真题</title> </head> <body> <script> var a = ?; //该题意思是变量a应该等于什么值 可以让条件成立 if(a == 1 && a==2 && a==3){ console.log(1); } </script> </body> </html>
相关知识点:
== 数据类型不一样
例如: 对象 == 字符串 会通过对象.toString()变为字符串
null == undefined 相等 但是和其它值进行比较时不相等
NaN == NaN 不相等 因为NaN和任何都不相等,包括自己
剩下的都是转化成数字,例如:
第一种解决办法,自己写一个toString()( 也可以用valueof() )
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>面试真题</title> </head> <body> <script> var a = { i: 0, toString(){ return ++this.i; } } if(a == 1 && a==2 && a==3){ console.log(1); } </script> </body> </html>
第二种解决办法,采用数据劫持
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>面试真题</title> </head> <body> <script> var i=0; Object.defineProperty(window,'a',{ get(){ return ++i; } }) if(a == 1 && a==2 && a==3){ console.log(1); } </script> </body> </html>
第三种解决办法,用数组的shift()方法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>面试真题</title> </head> <body> <script> var a=[1,2,3]; a.toString=a.shift; if(a == 1 && a==2 && a==3){ console.log(1); } </script> </body> </html>
当然,方法还有很多很多,这里就例举容易想到的三个
第二题
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>面试真题</title> </head> <body> <script> function A(){ alert(1); } function Func() { A=function(){ alert(2); } return this; } Func.A=A; Func.prototype={ A:()=>{ alert(3); } }; A(); //'1' Func.A(); //'1' Func().A(); //'2' new Func.A(); //'1' new Func().A(); //'3' new new Func().A(); //'bug' </script> </body> </html>
相关知识点:
箭头函数无法new
箭头函数和普通函数的区别:
- 箭头函数没有this主体,this都是继承上下文的this。
- 箭头函数无法被new的原因是箭头函数没有原型链,也就没有构造器函数constructor
第三题
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>面试真题</title> </head> <body> <script> var x=0,y=1; function fn(){ x+=2; fn=function(y){ console.log(y+ (--x) ); }; console.log(x,y); } fn(3); //2 1 fn(4); //5 console.log(x,y); // 1 1 </script> </body> </html>
相关知识点:
重写fn函数
第四题
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>面试真题</title> </head> <body> <script> setTimeout(() => { console.log(1); }, 20); console.log(2); setTimeout(() => { console.log(3); }, 10); console.log(4); console.time('AA'); for (let i = 0; i < 90000000; i++) { //do something } console.timeEnd('AA'); //97ms左右 console.log(5); setTimeout(() => { console.log(6); }, 8); console.log(7); setTimeout(() => { console.log(8); }, 15); console.log(9); </script> </body> </html>
相关知识点:
宏任务: 定时器例如setTimeout(异步)、事件绑定
面试题引入
1.Vue2.0双向绑定的实现原理
强烈推荐阅读:Vue 技术栈 手写响应式原理 到 探索设计模式(通过源码精通双向绑定)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> name:<span id="spanName"></span> <br> <input type="text" id="inpName"> <script> let obj={ name:'' }; let newObj={ ...obj }; Object.defineProperty(obj,'name',{ get(){ return newObj.name; }, set(val){ if(val===newObj.name) return; newObj.name=val; observer(); } }); function observer(){ spanName.innerHTML=obj.name; inpName.value=obj.name; } observer(); setTimeout(()=>{ obj.name="超逸の博客!"; },2000); inpName.oninput = function() { obj.name=this.value; }; </script> </body> </html>
2.0版本defineProperty存在的问题:
- 需要对原始数据进行拷贝
- 需要分别给对象中的每一个属性设置监听,会需要for in循环以及递归操作
2.Vue3.0双向绑定的实现原理
强烈推荐阅读:Vue 技术栈 手写响应式原理 到 探索设计模式(通过源码精通双向绑定)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> name:<span id="spanName"></span> <br> <input type="text" id="inpName"> <script> let obj={ name:'' }; obj=new Proxy(obj,{ get(target,prop){ return target[prop]; }, set(target,prop,value){ target[prop]=value; observer(); } }) function observer(){ spanName.innerHTML=obj.name; inpName.value=obj.name; } observer(); setTimeout(()=>{ obj.name="超逸の博客!"; },2000); inpName.oninput = function() { obj.name=this.value; }; </script> </body> </html>
总结:为什么Vue 3中使用proxy
- defineProperty只能监听某个属性,不能对全对象进行监听
- 可以省去for in遍历找对象中的属性,提高效率,省去很多代码
- 可以监听数组,不用再去单独的对数组进行特异性操作
- 不会污染原对象,会返回一个新的代理对象,原对象依旧是原对象
- 只需对代理对象进行操作
3.MVC和MVVM的区别
关于这个问题呢,就是关于vue和react的区别,你可以参考如下回答:
没有很大区别,知识MVC是单向数据绑定,只绑定了数据更改然后视图跟着渲染,而MVVM实现了双线数据绑定,在基础上多了一层视图更改,对应数据绑定也跟着更改。要从MVC到MVVM其实不难,一个onchange事件搞定,所以没很大区别。
4.跨域问题的解决方案和实现原理
跨域问题的产生及其价值意义
知识点拓展:
http默认端口 80
https默认端口 443
ftp默认端口 21
在过去,前后端分离之前,不存在跨域问题,是因为那时候前端和后端都是部署在同一个服务器上,同一个域下,同一个端口下,代码都放一起就不存在跨域问题了。
后来,区分Web服务器和数据服务器之后,就存在了跨域问题。
JSONP跨域解决方案的底层原理
客户端
get请求问题:
- 不安全
- 有缓存
- 大小限制
- 需要服务器的支持 拼接数据等
发现问题挺多,JSONP就过时了,于是尝试用post请求
基于iframe的跨域解决方案
- window.name
- document.domin
- location.hash
- post message
但上述都是存在一些问题的,后来呢,能不能让服务器进行跨域请求呢?
于是,出现了如下解决方式:
CORS跨域资源共享
客户端
import axios from 'axios'; import qs from 'qs'; axios.defaults.baseURL = "http://127.0.0.1:3000"; axios.defaults.timeout = 10000; axios.defaults.withCredentials = true; /** * 设置请求传递数据的格式(看服务器要什么格式) * x-www-form-urlencoded */ axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded'; axios.defaults.transformRequest = data =>qs.stringify(data); /** * 设置请求拦截 * TOKEN校验(JWT):接受服务器返回的token,存储到vuex/本地存储中, * 每一次向服务器发送请求,应该把token带上 */ axios.interceptors.request.use(config => { let token = localStorage.getItem('token'); token && (config.headers.Authorization = token); return config; }, error => { return Promise.reject(error); }); /** * 响应拦截器 */ axios.interceptors.response.use(response => { return response.data; },error => {}); export default axios;
服务器端
app.use((req,res,next) => { res.header("Access-Control-Allow-Origin",""); res.header("Access-Control-Allow-Credentials",true); res.header("Access-Control-Allow-Headers","PUT,POST,GET,DELETE,OPTIONS,HEAD"); res.header("Access-Control-Allow-Methods","Content-Type,Content-Length,Authorization,Accept,X-Requested-With"); req.method === 'OPTIONS' ? res.send('CURRENT SERVICES SUPPORT CROSS DOMIN REQUESTS!') : next(); });
CORS跨域与客户端没啥关联,主要是看服务端,但是也存在一点问题:
例如在服务端设置"Access-Control-Allow-Origin","*" (设置这里为 * ) ,允许所有源,此时就不能携带证书凭证了。
于是,后面又出现了新的一种跨域方式:
基于http proxy实现跨域请求(开发时使用)
nginx反向代理(部署时使用)
5.Vue框架中关于组件信息通信问题
(还在学习中,拖更…)
- 属性传递
- 发布订阅(EventBus):$on / &emit
- Provide / inject
- slot
- $parent / $Children
- vuex
客户端
但是,想实现任意组件之间都能通信,只能通过
本地存储方案。包括vuex / redux公共状态管理,不过存储在虚拟机内存里面。
另外,还有一个能够存储在
浏览器里面的就是
localStroage
vuex和localStorage两者区别:
vuex一刷新就没了,而localStorage一直存在(持久化存储),不过需要进行时间限制
因此引申到cookie,为什么不用cookie呢,因为大小限制,只有4k,而localStorage有5M
而且cookie容易被干掉。
那么例如用户是否登录,基本信息就不用localStorage存储了,就考虑使用vuex / redux公共状态管理,因此对性能进行了优化
服务端
与cookie相对应的就是
session,当服务器设置session,服务器返回给客户端的信息,在响应头中,会携带
set-cookie="content_sid"客户端会把信息种植到本地的cookie中,并且是http公认的,只可读不可写。
客户端再次向服务器发送请求的时候,会默认在请求头的cookie中,把content_sid传递发送给服务器,
学如逆水行舟,不进则退
- 点赞 2
- 收藏
- 分享
- 文章举报
- 【金三银四】 一文弄懂 js 数据类型、堆栈内存、作用域(链)、闭包知识拓展 (一)
- 跳跃版图 java 大整数 记忆化搜索 dp
- HNUCM-OJ Problem 1614 幸运数 模拟 最短子段和
- 一文过关 matlab 基础练习题
- 【前端干货】金三银四 我面了腾讯 分享面经/学习笔记/实习经历 (附视频讲解分享)
- 【前端知识梳理】HTML篇 笔记整理(一)
- HNUCM Contest1088 - 2020年春季ACM集训队热身赛-第2场 比赛题解
- HNUCM Contest1092 - 2020年春季ACM集训队热身赛-第3场 比赛题解
- 2020 零基础到快速开发 Vue全家桶开发电商管理系统(Element-UI)【目录】
- 关于我的大学ACM江湖
- 【ACM刷题专题】这个假期一起来刷题把,刷完冲击区域赛,刷完拿不到奖随便打!
- hexo+github+coding 搭建个人博客,你要的 大佬资料 都在这(项目完结整理)
- 【长文总结】2020 从零到博客专家 过去的我,现在的我,将来的我
- 15个前端攻城狮必备的学习网站 | 你知道几个?(附视频介绍)
- 【白嫖党】如何把前端学好?看完这篇,直呼:太强了!(历经半个月之作)
- ccf-csp #201909-2 小明种苹果(续)
- ccf-csp #201909-1 小明种苹果
- ccf-csp #201812-2 小明放学 (100分 附解析)
- 解决Java Web项目无法读取配置文件问题
- ccf-csp #201703-2 学生排队