Create by jsliang on 2019-2-11 15:30:34 Recently revised in 2019-3-17 21:30:36
Hello 小伙伴们,如果觉得本文还不错,记得给个 star , 小伙伴们的 star 是我持续更新的动力!GitHub 地址
并不是只有特定的季节才能跑路,只因为人跑得多了,这条路就定下来了。
金三银四跳槽季,jsliang 于 2019年2月11日 写下了这篇文章,开始准备自己的面试之旅。
至 2019年3月17日 为止,jsliang 搭建出个人的面试知识体系,海量地翻阅了一些前辈留下的资料,结合个人需求进行了几场面试,从而进一步完善该文章并进行了发表,希望对准备跳槽或者正在跳槽中的小伙伴有所帮助。
不折腾的前端,和咸鱼有什么区别
返回目录
请时刻准备好自己的简历,不管是互联网经济不佳面临裁员,还是因为公司内部斗争严重心乱如麻,还是因为厌倦了目前的一切……只有随时更新自己,把自己的简历准备好,你才知道哪一刻跑路是最佳选择。
返回目录
Hello 小伙伴们好,我叫梁峻荣,网名叫 jsliang ,由于崇拜前端大佬 技术胖 (jspang )的原因,又因为自己学的是前端(JavaScript),所以给自己取了个 jsliang (JavaScriptLiang ) 的网名,希望自己能通过建立自己的前端知识体系,从而在前端路上走得更远。并将自己的经验分享给小伙伴,携手小伙伴们一起前行。
下面是讲讲个人故事:
首先 ,jsliang 高考后的暑期就听大学师兄的建议,开始学习编程,那时候学习了 C 语言,觉得世界上最神奇的事情不过如此,敲两下键盘,按下回车,电脑就会一闪一闪地响应我们!于是在大学的时候,陆陆续续学过 C、C#、.Net 等……。
-_-|| 由于学得都是基础,又都还给老师了,在这里就不多累述了。
然后 ,在大二就开始接触 HTML,那时候选修了个《网页设计基础》,跟着老师做了个只有几个页面的静态网站。在大三的时候,参加了学校的特训班,分角色按流程从头到尾做了个包含角色管理、购物等功能的网站。同时,由于在特训班的时候,看到后端使用 ThinkPHP(简称 TP),觉得蛮不错的,于是自己捣鼓,使用 TP 3.2.3 + Bootstrap 3 + MySQL 打造了自己的博客(已下线)。
接着 ,由于选修了门 Node.js 的课,所以也跟着大佬的步伐接触了下 Vue、Koa 这些,那时候对 npm 等诸多不懂,为了折腾这个,我的前端世界自此打开了个大门。
最后 ,我在自己的毕业设计中使用 Node.js + Vue + ElementUI + MongoDB 打造了个校园外卖、快递代拿等功能的社区单页应用。
在 2018 年 5 月的时候,家里催促,于是直接出来面试。不像其他大佬的毕业等于失业,很幸运地 jsliang 面试第一家就给了 offer,于是就进了这家公司,那时候感觉自己前面的大学生活白过了,只懂 ES5、jQuery、HTML/HTML5、CSS/CSS3 的皮毛。
在熟悉了三个月的业务,公司给的任务能顺利完成后,我觉得自己不够努力:外面的前端翻天覆地,我的技术却只是 jQuery is all!
于是 2018 年 8 月,jsliang 开始写 Markdown,将 5 月份到 8 月份记录到 Word 文档上的笔记整理成了 jsliang 的文档库 ,并在 jsliang 的掘金 上发表了第一篇文章。
18 年 8 月至今,jsliang 大致经历了以下这些:
学 Webpack,并用 Webpack 构建一个多页面配置。然后幸运的是,刚好碰到公司的一个仿站任务,于是整个前端小组直接用了我的 Webpack + jQuery + VS Code 的 Live Share 套路进行协同开发! 学 微信小程序,并将它应用到电信开发的微信小程序项目翼小微中。 学 ECharts 报表,并用它做了个 Vue + ECharts 的报表,来展示爱音乐公司的运营数据。 学 Node,然后搭了个企业网站(company.jsliang.top ),并写了篇小文章(目前最高成就,获得了 1100 多赞)。 学 Vue,由于之前学的 Vue,在工作上有好多没有,逐渐淡忘了,所以从基础开始,准备写一套《Vue 从 0 到 1》。 以上,就是 jsliang 的编程生涯。
今儿,在这里写写 jsliang 为了跳槽,根据个人想法进行的一些前端面试资料整理,小伙伴们觉得不错的点个赞或者去 GitHub 点个 star,觉得有误请指出,谢谢~
返回目录
马老板曾经说过,跳槽有两个原因:
钱没给到位。 心被委屈了。 首先 ,如果非要给 jsliang 我自己的跳槽定个位,那肯定是钱没给到位,劳动与产出不成正比。在我 2018 年 5 月入职前,与人事的交谈中了解到每年的 8 月和 2 月可以提薪,当初的技术栈是:HTML、CSS、ES5。
然后 ,2018 年 6 月到 2019 年 1 月,学习并应用到工作中的技术有:
jQuery Webpack JSP 微信小程序 Vue ECharts 其中 2018 年 8 月刚转正,也不敢说自己技术进步很大,也不敢说自己项目贡献很大,为公司谋了多大利益,所以没有提薪想法。
2019 年 1 月底感觉自己项目也做了,凌晨 4/5/6 点的体育西路也看过了,技术也提升了,于是跟人事交谈,期望 2 月能加薪,人事表示年终述职演讲得好的给提薪,2 月开工的时候表示提薪名单没我份……
你没看错,提薪全靠 PPT。PPT 里提高了不给,没提就是没有。 当初想法很简单,你随便加个 5/600 我也满足了。
最后 ,jsliang 曾跟项目总监私下谈话,建议可以发展一些新产品,这样公司或许能获取一些新收入,我也可以进一步挑战我的技术。但是,由于我司是个老牌子公司,并且大部分依赖于接手电信项目进行扩张……
enm...所以心也委屈了。
在 2018 的努力下,GitHub 破 600 近 700 star,掘金破 10 万阅读量,3000 粉丝: GitHub 见证:点击查看 掘金见证:点击查看
返回目录
目标城市:广州 目标薪资:10K - 15K 目标技术: 1. 熟悉 HTML/HTML5、CSS/CSS3、ES5/ES6。2. 了解 OOP 概念,并尝试在工作中使用过 OOP 技巧。3. 对 MVC/MVVM 架构有一定了解,如有 Vue/React/Angular 或者 微信小程序开发经验更佳。4. 使用过 Bootstrap 或者 ElementUI 等 UI 库,并对前端 UI 库有一定的个人理解。5. 了解 Git、Webpack 等工具。6. 对 Java、Node.js 等后端编程有一定了解。7. 一年及以上工作经验。复制代码
广州 13K 薪资要求:2/3 年工作经验。 熟悉 OOP,并能在工作中使用,且能独立开发插件等…… 你可以不懂 Vue,但 React 你必须得会! 广州 15k+ 薪资要求:5 年+ 工作经验。 全能,懂前端,熟悉后端,能写文档…… 带领过小队进行开发。 广州异常偏科公司:要求必须懂后端。 要求必须懂安卓或者 IOS 开发。 要求必须精通 jQuery 全家桶(jQuery UI、jQuery Mobile 等……)。 该分析数据来自 Boss 直聘
返回目录
本文的知识点将涉及 HTML、CSS、JS、HTTP、Vue、Webpack、打包工具、性能优化等,没有前置条件,看得懂可以瞅瞅复习下,看不懂可以瞅瞅学习下。
关于面试,在这记下慕课网视频看到的,个人非常认同的三个问答:
问:拿到一个面试题,第一时间看到什么? 答:考点 问:如何看待网上搜出来的永远看不完的题海? 答:不变应万变 问:如何对待面试题? 答:题目到知识再到题目 然后在复习面试题的过程中,个人有些小看法:
当编写业务代码中,碰到某个业务 bug 时,我会习惯性地百度这个业务 bug,看看网友是怎么解决的。但是,学霸级的程序猿,会多走一步,他们会思考产生这个业务 bug 的底层原因是什么,下次碰到类似的是如何应用该技术解决。所以,日积月累,我的确比不上人家了。
way 1:面试成功,跟自己公司递辞呈,走流程,同时跟对面 hr 申请一个月后入职。
way 2:面试成功,跟自己公司递辞呈,询问能不能快速离职,收到回复跟对面 hr 确认时间。【推荐】
way 3:先递辞呈,同时面试,面试成功的,一律申请走完原公司一个月的流程之后的日子入职。
jsliang 于 2 月底拿到 offer 并递交辞呈,3 月 - 4 月进入一个月倒计时,4 月第一周才能拿到离职证明。
最后在这里祝各位小伙伴能找到称心如意的工作~
返回目录
HTML 属于结构层,负责描绘出内容的结构。
CSS 属于表示层,负责如何显示有关内容。
JavaScript 属于行为层,负责内容应如何对事件做出反应。
返回目录
返回目录
语义化的含义就是用正确的标签做正确的事情,HTML 语义化就是让页面的内容结构化,它有如下优点:
便于对浏览器、搜索引擎解析; 便于盲人浏览网页; 便于阅读源代码的人对网站进行分开,维护和理解; 简单来说,能用 <header>
、<footer>
等 H5 新标签的就不用 <div class='header'>
,不要使用 <div>
来存放段落等……
返回目录
HTML5 中新增标签大致有:<header>
、<footer>
、<aside>
、<nav>
、<video>
、<audio>
、<canvas>
等等。
返回目录
Chrome Firefox Safari IE Opera 排版引擎 Blink Gecko Webkit Trident Blink JS 引擎 V8 SpiderMonkey Nitro Chakra V8
国内一些浏览器使用较多的是 Webkit 内核。
IE 内核浏览器识别:<!--[if IE]><![endif]-->
非 IE 内核浏览器识别:<!--[if !IE]><![endif]-->
/* 设置文字不可选取 */ * { -moz-user-select : none; /* 火狐 浏览器 */ -webkit-user-select : none; /* Webkit 浏览器 */ -o-user-select : none; /* Opera 浏览器 */ -ms-user-select : none; /* IE10 浏览器 */ -khtml-user-select : none; /* 早期浏览器 */ user-select : none; /* 默认 */ }复制代码
返回目录
cookies 数据存放在客户的浏览器上,session 数据存放在服务器上。 前端都是裸君子,没有安全可言,cookies 可能会被黑客利用作数据欺骗。所以重要信息记得存 session。 session 如果在生效期内量过大,会占用服务器性能。 单个 cookies 保存的数据不能超过 4 K,很多浏览器限制一个站点保存最多 20 个 cookies。 sessionStorage :生命周期存在于标签页或窗口,用于本地存储一个会话(session)中的数据,这些数据会随着窗口或者标签页的关闭而被清空。
localStorage :生命周期是永久的,除非用户主动清除浏览器上存储的 localStorage 信息,否则它将会永久存在。
sessionStorage 和 localStorage 操作方法:setItem
、getItem
以及 removeItem
。
以 localStorage 为例:
localStorage.getItem('name' ); // 获取 name 的值 localStorage.setItem('name' , 'jsliang' ); // 设置 name 的值为 jsliang localStorage.removeItem('name' ); // 删除 name 的值 复制代码
参考 1:《前端分享之cookie的使用及单点登录》 参考 2:《Cookie、session和localStorage、以及sessionStorage之间的区别》
返回目录
HTML 属于结构层,负责描绘出内容的结构。
CSS 属于表示层,负责如何显示有关内容。
JavaScript 属于行为层,负责内容应如何对事件做出反应。
返回目录
返回目录
在工作的过程中,会发现各式各样的浏览器对某个标签有自己独特的样式。
但是在前端开发中,如果不采用统一标准,那么会产生千奇百怪的 bug。所以为了减少后期 bug 的出现,前端开发人员会重置一遍 CSS 样式,尽可能地使开发的网页在各个浏览器相差不大。
下面是 jsliang 在使用的样式重置,当然如果小伙伴有不同的想法,可以去 百度/必应/google 搜索并使用其他版本的样式重置:
返回目录
在工作的过程中,也许小伙伴需要 div 块的总宽度为 100px,然后发现总是被 margin 撑高,这是因为盒模型定义的问题:
CSS 中有个属性叫 box-sizing
。
box-sizing: border-boxbox-sizing: content-box复制代码
border-box
中,整个 div
的宽、高,包括 margin
、padding
、border
。content-box
中,整个 div
的宽、高,则不包括上面元素。如上图,如果一个 div
,你的代码如下:
div { box-sizing: border-box; margin: 10px; width: 100px; height: 100px; padding: 10px;}复制代码
那么,你的整个宽高还是 100px
。
但是,如果你的代码如下:
div { box-sizing: content-box; margin: 10px; width: 100px; height: 100px; padding: 10px;}复制代码
那么,你的整个盒子宽高是 120px
。
如果你在设计页面中,发现内容区被撑爆了,那么,请检查下现在的 border-box
是什么,最好在引用 reset.css
的时候,就对 border-box
进行统一设置,方便管理。
返回目录
在 CSS 中,除了我们常用的 px
,还有其他单位小伙伴们可以了解一下:
单位 描述 % 百分比 px 像素。计算机屏幕上的一个点为 1px
。 em 相对单位。相对于父元素计算,假如某个 p 元素为 font-size: 12px
,在它内部有个 span 标签,设置 font-size: 2em
,那么,这时候的 span 字体大小为:12 * 2 = 24px
rem 相对单位。相对于根元素 html 的 font-size
,假如 html 为 font-size: 12px
,那么,在其当中的 div 设置为 font-size: 2rem
,就是当中的 div 为 24px
。 rpx 微信小程序相对单位。1rpx = 屏幕宽度 / 750 px。在 750px 的设计稿上,1rpx = 1px。
除此之外还有 pt、ex 等单位,但由于不太好换算,故在此不提。
返回目录
选择器是匹配元素的一种模式。
HTML 经过解析生成 DOM Tree;而在 CSS 解析完毕后,需要将解析的结果与 DOM Tree 的内容一起进行分析建立一棵 Render Tree,最终用来进行绘图。
Render Tree 中的元素与 DOM 元素相对应,但非一一对应:一个 DOM 元素可能会对应多个 renderer,如文本折行后,不同的「行」会成为 render tree 种不同的 renderer。也有的 DOM 元素被 Render Tree 完全无视,比如 display:none 的元素。
在建立 Render Tree 时,浏览器就要为每个 DOM Tree 中的元素根据 CSS 的解析结果来确定生成怎样的 renderer。对于每个 DOM 元素,必须在所有 Style Rules 中找到符合的 selector 并将对应的规则进行合并。选择器的「解析」实际是在这里执行的,在遍历 DOM Tree 时,从 Style Rules 中去寻找对应的 selector。
在 CSS 的选择器中,它会按照优先级 从右向左解析 ,因为这样匹配元素的时候,能尽量少地查找,所以选择器最好写地简洁一点。
通配符:*
ID 选择器:#ID
类选择器:.class
元素选择器:p
、a
等…… 后代选择器:p span
、div a
等…… 伪类选择器:a:hover
等…… 属性选择器:input[type='text']
等…… 子元素选择器:li:firth-child
、p:nth-child(1)
等…… !important -> 行内样式 -> #id -> .class -> 元素和伪元素 -> * -> 继承 -> 默认
返回目录
水平垂直居中。这种布局老生常谈,jsliang 在本文也有提到,详解请 点击链接 两列布局。一侧固定,另一侧自适应。 <!DOCTYPE html> <html lang ='en' > <head > <meta charset ='UTF-8' > <meta name ='viewport' content ='width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no' > <meta http-equiv ='X-UA-Compatible' content ='ie=edge' > <title > Two Column Layout</title > <style > .container { display : flex; } .child-one { width : 300px ; height : 300px ; background : red; } .child-two { width : 100% ; height : 300px ; background : deepskyblue; } </style > </head > <body > <div class ='container' > <div class ='child-one' > </div > <div class ='child-two' > </div > </div > </body > </html > 复制代码
三列布局。类似于两列布局,新增多一个固定宽的 <div>
块而已。当然,小伙伴们可能会说:jsliang 你要考虑 flex
的兼容性啊!enm...支持所有最新版本的浏览器!请更新你的浏览器哦亲~ 避免被寄刀片,附上 float
布局:《css常见布局》
返回目录
经典 :CSS3 相关属性你了解吗,说说都有哪些?能说说你工作中常用的一些 CSS3 属性吗?
那么,CSS3 新特性都有哪些呢?
transition:过渡 transform:旋转、缩放、移动或者倾斜 animation:动画 gradient:渐变 shadow:阴影 border-radius:圆角 为了方便记忆,咱将它们扔到同一个 HTML 文件上,小伙伴拷贝到本地上打开,可以看到一个拥有渐变的小球,做着横向运动,如果你鼠标移动到它上面,它的宽度会放大,并且进行倾斜。
<!DOCTYPE html> <html > <head > <meta charset ='utf-8' > <title > CSS3 新特性</title > <style > div { width : 100px ; height : 100px ; border-radius : 50px ; background : linear-gradient (red, orange); box-shadow : 10px 10px 5px #888888 ; position : relative; transition : width 2s ; animation : mymove 5s infinite; } div :hover { width :300px ; transform : rotate (7deg); } @keyframes mymove { from { left : 0px ; } to { left : 200px ; } } </style > </head > <body > <div > </div > </body > </html > 复制代码
参考 1:《CSS3 圆角》 参考 2:《CSS3 渐变(Gradients)》 参考 3:《CSS3 transition 属性》 参考 4:《CSS3 transform 属性》 参考 5:《CSS3 animation(动画) 属性》 参考 6:《CSS3 box-shadow 属性》 参考 7:《个人总结(css3新特性)》
返回目录
BFC 就是 块级格式上下文,它是一个独立的渲染区域,让处于 BFC 内部的元素和外部的元素相互隔离,使内外元素的定位不会相互影响。
一定的 CSS 声明可以生成 BFC,浏览器对生成的 BFC 有一系列的渲染规则,利用这些渲染规则可以达到一定的布局效果。
它可以防止 margin 元素重叠(div 中包含 ul,而 div 与 ul 之间的垂直距离,取决于 div、ul、li 三者之间的最大外边距,这时候给 ul 一个 display:inline-block 即可解决这个问题) 清除内部浮动(div 中包含 ul,而 ul 采用 float:left,那么 div 将变成一长条,这时候给 div 加上规则使其变成 BFC 即可) display: inline-block position: absolute/fixed float 很少使用了,尽可能使用 flex css reset 一般会清除掉一些问题,减少 BFC 的使用。 参考文献:《我对BFC的理解》
返回目录
返回目录
行内元素 :宽度和高度由内容决定,与其他元素共占一行的元素,我们将其叫行内元素。例如:<span>
、<i>
、<a>
等……
块级元素 :默认宽度由父容器决定,默认高度由内容决定,独占一行并且可以设置宽高的元素,我们将其叫做块级元素。例如:<p>
、<div>
、<ul>
等……
在日常开发中,我们经常使用 CSS 的 display
属性来打破两者的壁垒:display: inline-block
,使它们拥有更多的状态。
返回目录
在引用 CSS 上,分为四种形式:行内样式 、内嵌式 、链接式 以及导入式 ,下面介绍这四种模式。
直接对 HTML 的标记使用 style 属性,然后将 CSS 代码直接写进去:
<p style ='color: #fff; backgournd: deepskyblue;' > </p > 复制代码
将 CSS 写 <head>
与 </head>
之间,并且用 <style>
和 </style>
标记进行声明:
<head > <style > p { color : #fff ; background : deepskyblue; } </style > </head > 复制代码
通过将 <style>
上的 CSS 提起到指定的 CSS 文件上,然后通过 <link>
的方式在 HTML 上链接起来。
<head > <link href ='reset.css' type ='text/css' rel ='stylesheet' > </head > 复制代码
<head > <style > @import url(reset.css); </style > </head > 复制代码
在优先级上,行内样式 > 链接式 > 内嵌式 > @import 导入式 。
返回目录
Flex 是 Flexible Box 的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性。
/* 设置 Flex 模式 */display: flex;/* 决定元素是横排还是竖着排,要不要倒序 */flex-direction: column;/* 决定元素换行格式,一行排不下的时候如何排 */flex-wrap: wrap;/* flex-flow = flex-direction + flex-wrap */flex-flow: column wrap;/* 同一排下对齐方式,空格如何隔开各个元素 */justify-content: space-between;/* 同一排下元素如何对齐,顶部对齐、中部对齐还是其他 */align-items: center;/* 多行对齐方式 */align-content: space-between;复制代码
HTML
<div class='container' > <div class='child' ></div></div>复制代码
CSS
.container { margin: 0 auto; width: 300px; height: 200px; background: deepskyblue; display: flex; /* 实现元素水平居中 */ justify-content: center; /* 实现元素垂直居中 */ align-items: center;}.child { width: 100px; height: 100px; background: #fff; }复制代码
除了 Flex,还能使用其他形式进行水平垂直居中吗? HTML
<div class='container' > <div class='child' ></div></div>复制代码
CSS
.container { position: relative; width: 300px; height: 200px; background: pink; margin: 0 auto;}.child { position: absolute; width: 100px; height: 100px; top: 50%; left: 50%; /* 下面两种方式均可 */ /* margin-top: -50px; margin-left: -50px; */ transform: translate(-50%, -50%); background: #fff; }复制代码
水平居中:
行内元素:display: inline-block; text-align: center;
块级元素:margin: 0 auto;
Flex:display: flex; justify-content: center;
垂直居中:
行高 = 元素高:line-height: height
Flex:display: flex; align-items: center;
参考文献: ① 《CSS实现垂直居中的常用方法》 ② 《CSS 用 position: absolute 与 transform 来居中块级元素的问题》
返回目录
HTML 属于结构层,负责描绘出内容的结构。
CSS 属于表示层,负责如何显示有关内容。
JavaScript 属于行为层,负责内容应如何对事件做出反应。
返回目录
《JavaScript 高级程序(第三版)》 《你不知道的 JavaScript》 《JavaScript 忍者秘籍》 《ES6 标准入门》—— 阮一峰 《JavaScript 设计模式》—— 张容铭 《JavaScript 设计模式与开发实践》—— 曾探 返回目录
<body > <input type ='button' onclick ='alert('行内引入')' value ='按钮' /> <button onclick ='alert(123)' > 点击我</button > </body > 复制代码
<script > window .onload = function ( ) { alert('js 内部引入!' ); } </script > 复制代码
<body > <div > </div > <script type ='text/javascript' src ='./js/index.js' > </script > </body > 复制代码
注意 :
不推荐写行内或者在 HTML 中插入 <script>
,因为浏览器解析顺序缘故,如果解析到死循环之类的 JS 代码,会卡住页面。 建议在 onload 事件之后,即等 HTML、CSS 渲染完毕再执行代码。 返回目录
关于 prototype
、__proto__
、new
、call()
、apply()
、bind()
、this
这些的知识点,由于篇幅太长,jsliang 已经抽离了出来,并做了简洁详细讲解,详见:
下面放出相关知识点:
实例的 __proto__
属性(原型)等于其构造函数的 prototype
属性。 Object.proto === Function.prototype Function.prototype.proto === Object.prototype Object.prototype.proto === null 返回目录
在 JS 中,最容易混淆的就是作用域的情况。
在传统的后端语言(例如 C 语言)中,一对花括号 {}
就是一个块级作用域,作用域内变量不会相互影响,但是在 JS 中,像 if 条件语句的 {}
就不算一个独立的作用域:
var x = 1 ;console .log(x); // 1 if (true ) { var x = 2 ; console .log(x); // 2 }console .log(x); // 2 复制代码
所以有时候我们就需要变通,通过自执行函数创建临时作用域:
function foo ( ) { var x = 1 ; console .log(x); // 1 if (x) { (function (x ) { console .log(x); // 1 var x = 2 ; console .log(x); // 2 })(x) } console .log(x); // 1 }foo();复制代码
说到创建临时作用域,我们就不得不谈一下闭包。
那么,什么是闭包呢?
闭包简单定义 :函数 A 里面包含了 函数 B,而 函数 B 里面使用了 函数 A 的变量,那么 函数 B 被称为闭包。
又或者:闭包就是能够读取其他函数内部变量的函数
function A ( ) { var a = 1 ; function B ( ) { console .log(a); } return B();}复制代码
for (var i = 0 ; i < 3 ; i++) { setTimeout(function ( ) { console .log(i); }, 1000 );}复制代码
请问这段代码输出什么?
答案:3 个 3。 解析:首先,for
循环是同步代码,先执行三遍 for
,i 变成了 3;然后,再执行异步代码 setTimeout
,这时候输出的 i,只能是 3 个 3 了。
使用 let: for (let i = 0 ; i < 3 ; i++) { setTimeout(function ( ) { console .log(i); }, 1000 );}复制代码
在这里,每个 let 和代码块结合起来形成块级作用域,当 setTimeout() 打印时,会寻找最近的块级作用域中的 i,所以依次打印出 0 1 2。
如果这样讲不明白,我们可以执行下下面这段代码:
for (let i = 0 ; i < 3 ; i++) { console .log('定时器外部:' + i); setTimeout(function ( ) { console .log(i); }, 1000 );}复制代码
此时浏览器依次输出的是:
定时器外部:0定时器外部:1定时器外部:2012复制代码
即代码还是先执行 for
循环,但是当 for
结束执行到了 setTimeout
的时候,它会做个标记,这样到了 console.log(i)
中,i 就能找到这个块中最近的变量定义。
使用立即执行函数解决闭包问题 for (let i = 0 ; i < 3 ; i++) { (function (i ) { setTimeout(function ( ) { console .log(i); }, 1000 ); })(i)}复制代码
以上,我们就讲解完了闭包及解决闭包的方式。
观点 1 :有些资料表示闭包中产生的大量局部变量,会造成内存消耗过大,从而造成网页的性能问题。观点 2 :有些资料表示目前浏览器引擎都基于 V8,而 V8 引擎有个 gc 回收机制,不用太过担心变量不会被回收。提示 :所以,如果你觉得不够保险,那就在退出函数之前,将不使用的局部变量全部删除。
返回目录
简单来说,有两个对象 A 和 B,B = A,当你修改 A 时,B 的值也跟着发生了变化,这时候就叫浅拷贝。如果不发生变化,就叫深拷贝。
首先我们需要知道基本数据类型(number、string、boolean、null、undefined)与 引用数据类型(无序对象,数据以及函数) 。 然后在基本数据类型中,例如:let a = 1; let b = a; a = 2; console.log(b)
。当我们尝试这样子写时,b 在栈内存中开辟了一个新内存,所以 b 的值不会改变,仍是 1. 接着在引用数据类型中,例如 let a = [1, 2, 3], b = a; a[0] = 3; console.log(b)
。当我们尝试这样子写时,b 会偷懒,引用跟 a 同一块的内存地址,从而 a 的修改会影响 b,使得 b 变成 [3, 1, 3]。 最后,我们可以知道在引用数据类型中,会产生浅拷贝的问题。 首先我们尝试使用递归去解决深拷贝: function deepClone (obj ) { let objClone = Array .isArray(obj) ? [] : {}; if (obj && typeof obj === 'object' ) { for (key in obj) { if (obj.hasOwnProperty(key)) { // 判断 obj 子元素是否为对象,如果是,递归复制 if (obj[key] && typeof obj[key] === 'object' ) { objClone[key] = deepClone(obj[key]); } else { // 如果不是,简单复制 objClone[key] = obj[key]; } } } } return objClone;}let a = [1 , 2 , 3 , 4 ];let b = deepClone(a);a[0 ] = 2 ;console .log(a, b);// Console // a = [2, 2, 3, 4]; // b = [1, 2, 3, 4]; 复制代码
使用 JSON 对象的 parse 和 stringify 注意:采用 JSON 进行的深拷贝,无法拷贝到 undefined、function、symbol 这类数据,它是有小 bug 的深拷贝。
function deepClone (obj ) { let _obj = JSON .stringify(obj); let objClone = JSON .parse(_obj); return objClone}let a = [0 , 1 , [2 , 3 ], 4 ];let b = deepClone(a);a[0 ] = 1 ;a[2 ][0 ] = 1 ;console .log(a, b);// Console // a = [1, 1, [1, 3], 4]; // b = [0, 1, [2, 3], 4]; 复制代码
返回目录
在前端发展中,随着前后端分离,前端社区的不断壮大,前端能做的事情越来越多,承受的任务越来越重,代码也就越来越长了。就好比 jsliang 个人使用 jQuery 开发的时候,动不动就上千行代码,这在一个编辑器上看起来就有点乱了。如果碰上没有代码折叠的编辑器,你就更加难受了。
有的小伙伴的编辑器不是 VS Code,也不能进行代码折叠
所以,面对越来越多的代码,我们就急需将这些代码分门别类,将代码按功能划分,将同一功能的代码整合在一起,于是就有了模块化开发:一个文件就是一个模块,当我们需要某个文件的时候,我们只需要引用这个模块即可……
首先 ,是 CommonJS 的提出,在 Node.js 以及 Webpack 都支持 CommonJS,它规定了一个文件就是一个模块,文件内部定义的变量属于这个模块,不会对外暴露从而污染全局变量的规则。在 CommonJS 中,通过 exports 或者 module.exports 进行导出,通过 require 进行 同步加载 所需要依赖的模块。由于它是同步加载模块的形式,所以比较通用于服务器端。
然后 ,根据 CommonJS 只能同步加载的问题,AMD 根据浏览器的特性,进行了非同步加载模块的提出。同时,AMD 有个问题,就是在使用 require.js 的时候,必须提前加载所有模块。
接着 ,根据 AMD 的问题,CMD 提出来了:通过按需加载的形式,哪里需要就调用哪里,而不用等到所有的模块都加载了再解析。
最后 ,ECMA 国际推出了 ES6 的 modules。在 ES6 中,通过 export 关键字导出模块,通过 import 关键字引用代码。当然,由于浏览器厂商诸多,ES6 在浏览器的尚不支持,目前主流做法是先将 ES6 通过 babel 编译成 require。
当然,JS 都进行模块化了,jsliang 想起自己项目中的那一坨 CSS,真心没有回顾的想法!所以我们还需要知道为了方便管理 CSS,大佬们还是有做事儿的:Less 以及 Sass,这两者使 CSS 的编写更有组织性和目的性了。
说起模块化,我们又可以顺带提及组件化了,一开始为了区分这两者,jsliang 也是百度了大量文章,最后成功把自己整蒙了,还是说说感觉可以的解释:
组件化更关注的是 UI 部分:弹出框、头部,内容区、按钮等,都可以编写成组件,然后在适用的地方进行引用。而模块化更侧重于功能或者数据的封装,比如全局的 JSON 配置文件,比如通用的验证方法,比如规范时间戳等。
所以,说到这里,我们就可以提到前端工程化:将整个开发流程就行工程规划,从而提高整个团队的开发效率。
在前端工程化中,最重要的就是提高整个团队在 编码 -> 测试 -> 维护 这三个阶段的生产效率。团队的协调至关重要,将每个任务细分给各个成员,从而获取极致的工作效率,是管理者最喜欢看到的。而在上面的模块化和组件化的应用,就属于前端工程化中的一部分,其目的就是在一些复杂的项目中,方便团队进行合作开发,提高生产效率。
参考文献: ① 《到底什么是前端工程化、模块化、组件化》 ② 《【前端工程化系列】简谈前端模块化开发与开发规范》 ③ 《个人关于模块化的理解》 ④ 《组件化开发和模块化开发概念辨析》 ⑤ 《JavaScript模块化 --- Commonjs、AMD、CMD、es6 modules》 ⑥ 《浅谈什么是前端工程化》
返回目录
什么是面向过程与面向对象? 面向过程就是做围墙的时候,由你本身操作,叠第一层的时候:放砖头,糊水泥,放砖头,糊水泥;然后第二层的时候,继续放砖头,糊水泥,放砖头,糊水泥…… 面向对象就是做围墙的时候,由他人帮你完成,将做第一层的做法抽取出来,就是放砖头是第一个动作,糊水泥是第二个动作,然后给这两个动作加上步数,最后告诉机器人有 n 层,交给机器人帮你工作就行了。 为什么需要面向对象写法? 简单来说,就是增加代码的可复用性,减少咱们的工作,使代码更加流畅。
手写个面向对象代码? function Person(name, phone) { this.name = name; this.phone = phone; this.eat = function () { console.log(name + ' 吃饭' ); } return this;}let p1 = new Person('jsliang' , '18818881888' );console.log(p1.name); // jsliangp1.eat(); // jsliang 吃饭复制代码
当然,jsliang 只能写到这里了,再写下去就是设计模式等知识点了。
所以希望小伙伴们还是了解下面向对象思想,有助于进一步提升自己。
返回目录
关于 防抖与节流 ,jsliang 特意将资料结合起来:
防抖与节流 重绘与回流 浏览器解析 URL DNS 域名解析 TCP 三次握手与四次挥手 浏览器渲染页面 小伙伴们可以前往 《面试知识点 - JS 防抖与节流》 查看。
返回目录
ES6 是个大知识点,如果你面试的公司不是 “饱经沧桑” 的那种,那么一定会出点 ES6 问题,例如:
说说 let、var、const 区别 讲讲 Promise 及其使用 因为 jsliang 感觉自己连 ES6 的门还没进,所以在这里就不 自作聪明 ,推荐下阮一峰大佬的教程:
希望小伙伴们看完能有所收获,并在工作中大量使用。
返回目录
在 JavaScript 中,用得较多的之一无疑是数组操作,这里过一遍数组的一些用法:
map
: 遍历数组,返回回调返回值组成的新数组forEach
: 无法break,可以用try/catch中throw new Error来停止filter
: 过滤some
: 有一项返回true,则整体为trueevery
: 有一项返回false,则整体为falsejoin
: 通过指定连接符生成字符串push / pop
: 末尾推入和弹出,改变原数组, 返回推入/弹出项【有误】unshift / shift
: 头部推入和弹出,改变原数组,返回操作项【有误】sort(fn) / reverse
: 排序与反转,改变原数组concat
: 连接数组,不影响原数组, 浅拷贝slice(start, end)
: 返回截断后的新数组,不改变原数组splice(start, number, value...)
: 返回删除元素组成的数组,value 为插入项,改变原数组indexOf / lastIndexOf(value, fromIndex)
: 查找数组项,返回对应的下标reduce / reduceRight(fn(prev, cur), defaultPrev)
: 两两执行,prev 为上次化简函数的return值,cur 为当前值(从第二项开始)相信小伙伴在工作中耍的已经是一套一套的了,或者像 jsliang 一样只会简单的使用 push
、map
这几个,感兴趣的小伙伴可以 百度/bing/google 找找一些 奇技淫巧 ,说不定对工作效率有很大提升~
返回目录
推荐:
技术胖 慕课网 返回目录
在 MVVM 架构下,View 和 Model 之间并没有直接的联系,而是通过 ViewModel 进行交互,Model 和 ViewModel 之间的交互时双向的,因此 View 数据会同步到 Model 中,而 Model 数据的变化也会立即反应到 View 上。
ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而 View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需要关注业务逻辑,不需要手动操作 DOM,不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。
M - Model。Model 代表数据模型,也可以在 Model 中定义数据修改和操作的业务逻辑。 V - View。View 代表 UI 组件,它负责将数据模型转化为 UI 展现出来。 VM - ViewModel。ViewModel 监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个同步 View 和 Model 的对象,连接 Model 和 View。 返回目录
创建前/后:在 beforeCreated 阶段,Vue 实例的挂载元素 $el
和数据对象 data 以及事件还未初始化。在 created 阶段,Vue 实例的数据对象 data 以及方法的运算有了,$el
还没有。 载入前/后:在 beforeMount 阶段,render
函数首次被调用,Vue 实例的 $el 和 data 都初始化了,但还是挂载在虚拟的 DOM 节点上。在 mounted 阶段,Vue 实例挂载到实际的 DOM 操作完成,一般在该过程进行 Ajax 交互。 更新前/后:在数据更新之前调用,即发生在虚拟 DOM 重新渲染和打补丁之前,调用 beforeUpdate 。在虚拟 DOM 重新渲染和打补丁之后,会触发 updated 方法。 销毁前/后:在执行实例销毁之前调用 beforeDestory ,此时实例仍然可以调用。在执行 destroy 方法后,对 data 的改变不会再触发周期函数,说明此时 Vue 实例已经解除了事件监听以及和 DOM 的绑定,但是 DOM 结构依然存在。 Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载 DOM -> 渲染、更新 -> 渲染、销毁等一系列过程,称之为 Vue 的生命周期。
8 个,创建前/创建后、挂载前/挂载后、更新前/更新后、销毁前/销毁后。Vue 生命周期的作用是方便我们通过它的生命周期,在业务代码中更好地操作数据,实现相关功能。
会触发 4 个生命钩子:创建前/创建后、挂载前/挂载后
在 beforeMounted
时它执行了 render
函数,对 $el 和 data 进行了初始化,但此时还是挂载到虚拟的 DOM 节点,然后它在 mounted
时就完成了 DOM 渲染,这时候我们一般还进行 Ajax 交互。
返回目录
Vue 采用 数据劫持 结合 发布者-订阅者 模式的方式,通过 Object.defineProperty()
来劫持各个属性的 setter 以及 getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
第一步:需要 Observe 的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter 和 getter。这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化。 第二步:Compile 解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新数据。 第三步:Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁,主要做的事情有:在自身实例化时往属性订阅器(dep)里面添加自己。 自身必须有一个 update() 方法 待属性变动 dep.notice()
通知时,能调用自身的 update()
方法,并触发 Compile 中绑定的回调,则功成身退。 第四步:MVVM 作为数据绑定的入口,整合 Observer、Compile 和 Watcher 三者,通过 Observer 来监听自己的 model 数据变化,通过 Compile 来解析编译模板指令,最终利用 Watcher 搭起 Observer 和 Compile 之间的桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据 model 变更的双向绑定效果。 js 实现简单的双向绑定
<body> <div id='app' > <input type ='text' id='txt' > <p id='show' ></p> </div> <script> window.onload = function () { let obj = {}; Object.defineProperty(obj, 'txt' , { get: function () { return obj; }, set : function (newValue) { document.getElementById('txt' ).value = newValue; document.getElementById('show' ).innerHTML = newValue; } }) document.addEventListener('keyup' , function (e) { obj.txt = e.target.value; }) } </script></body>复制代码
Object.defineProperty 接收三个参数:对象,属性名,配置对象 这里使用的是 Object.defineProperty,这是 Vue 2.0 进行双向数据绑定的写法。在 Vue 3.0 中,它使用 Proxy 进行数据劫持。
Vue 中使用 Object.defineProperty 进行双向数据绑定时,告知使用者是可以监听数组的,但是只是监听了数组的 push()、pop()、shift()、unshift()、splice()、sort()、reverse() 这八种方法,其他数组的属性检测不到。 Object.defineProperty 只能劫持对象的属性,因此对每个对象的属性进行遍历时,如果属性值也是对象需要深度遍历,那么就比较麻烦了,所以在比较 Proxy 能完整劫持对象的对比下,选择 Proxy。 为什么 Proxy 在 Vue 2.0 编写的时候出来了,尤大却没有用上去?因为当时 es6 环境不够成熟,兼容性不好,尤其是这个属性无法用 polyfill 来兼容。(polyfill 是一个 js 库,专门用来处理 js 的兼容性问题-js 修补器) 参考自《实现双向绑定Proxy比defineproperty优劣如何》
返回目录
Vue 在 render
中 createElement
的时候,并不是产生真实的 DOM 元素,实际上 createElement
描述为 createNodeDescription
,因为它所包含的信息会告诉 Vue 页面上需要渲染什么样的节点。
因此,我们将这样的节点描述为 “虚拟节点”(Virtual Node),简称 VNode。“虚拟 DOM” 是我们对由 Vue 组件树建立的整个 VNode 树的称呼。
作为一枚切图仔,很荣幸地跟小伙伴说:“其实我也不懂 Virtual DOM!”
但是,总会有些面试场合会提到的,所以这里找了几篇资料,小伙伴们可以进一步学习:
其他的就需要小伙伴自己寻找了,如果觉得有不错的解析 Virtual DOM 的文档/视频,小伙伴也可以推荐过来哈~
返回目录
Vue 中 template 就是先转化成 AST 树,再得到 render 函数返回 VNode(Vue 的虚拟 DOM 节点)。
通过 compile 编译器把 template 编译成 AST 语法树(abstract syntax tree - 源代码的抽象语法结构的树状表现形式),compile 是 createCompiler 的返回值,createCompiler 是用以创建编译器的。另外 compile 还负责合并 option。 AST 会经过 generate(将 AST 语法树转换成 render function 字符串的过程)得到 render 函数,render 的返回值是 VNode,VNode 是 Vue 的虚拟 DOM 节点,里面有标签名、子节点、文本等待。 返回目录
key 的作用就是在更新组件时判断两个节点是否相同。相同就复用,不相同就删除旧的创建新的。
对于 diff 过程来说 key 是起不到提速作用的,详见:key 的作用
返回目录
// 修改数据 vm.msg = 'Hello' // DOM 还没有更新 Vue.nextTick(function ( ) { // DOM 更新了 })// 作为一个 Promise 使用 (2.1.0 起新增,详见接下来的提示) Vue.nextTick().then(function ( ) { // DOM 更新了 })复制代码
关于 nextTick 的更多理解,jsliang 就不献丑了,需要学习的小伙伴可以查看:
或者自行查找更优秀的资源。
返回目录
关于 Vue 中的父子组件通讯,相信经常开发 Vue 的小伙伴比 jsliang 知道的多很多。
没怎么使用 Vue 的小伙伴可以看下下面的文章,并尝试自己写一写:
下面咱讲下使用 bus.js 实现非父子组件通讯:
假设在工作中,有三个 .vue 文件:A.vue、B.vue、C.vue。A.vue 是主页面,B.vue 和 C.vue 类似于头部导航条和底部导航栏。现在,B.vue 点击会切换路由,C.vue 需要获取 B.vue 传递的信息。
A.vue
<template > <div > <top-nav > </top-nav > <div class ='container' > <router-view > </router-view > </div > <bottom-nav > </bottom-nav > </div > </template > 复制代码
bus.js
import Vue from 'vue' ;// 使用 Event Bus const bus = new Vue();export default bus;复制代码
B.vue
<template > <div class ='bottom-nav' > <div class ='nav-one' @click ='goToPage({path: '/HomeIndex', meta:'首页'})' > <i class ='icon-home' > </i > <span > 首页</span > </div > </div > </template > <script > import bus from '../utils/bus' export default { methods : { goToPage(route) { this .$router.push(route.path); bus.$emit('meta' , route.meta); } } } </script > 复制代码
C.vue
<template > <div class ='top-nav' > <span class ='title' > {{title}}</span > </div > </template > <script > import bus from '../utils/bus' export default { data() { return { title : '' } }, created() { bus.$on('meta' , msg=> { this .title = msg; }) } } </script > 复制代码
返回目录
微信小程序,简称小程序,英文名 Mini Program,是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或搜一下即可打开应用。
返回目录
- component —————————————————— 组件文件夹 - navBar —— 底部组件 - navBar.js —— 底部组件的 JS 代码 - navBar.json —— 底部组件的配置文件 - navBar.wxml —— 底部组件的 HTML 代码 - navBar.wxss —— 底部组件的 CSS 代码- pages ————————————————————— 页面文件夹 - index —— 首页 - index.js —— 首页的 JS 代码 - index.json —— 首页的配置文件 - index.wxml —— 首页的 HTML 代码 - index.wxss —— 首页的 CSS 代码- public ————————————————————— 图片文件夹- utils —————————————————————— 工具文件夹 - api.js —— 控制 API 的文件 - md5.js —— 工具 - MD5 加密文件 - timestamp.js —— 工具 - 时间戳文件- app.json ——————————————————— 设置全局的基础数据等- app.wxss ——————————————————— 公共样式,可通过 import 导入更多- project.config.json ———————— 项目配置文件复制代码
返回目录
onLoad()
:页面加载时触发。onShow()
:页面显示/切入前台时触发。onReady()
:页面初次渲染完成时触发。onHide()
:页面隐藏/切入后台时触发。onUnload()
:页面卸载时触发。返回目录
封装接口: 项目/utils/api.js
// 将请求进行 Promise 封装 const fetch = ({url, data} ) => { // 打印接口请求的信息 console .log(`【step 1】API 接口:${url} ` ); console .log('【step 2】data 传参:' ); console .log(data); // 返回 Promise return new Promise ((resolve, reject ) => { wx.request({ url : getApp().globalData.api + url, data : data, success : res => { // 成功时的处理 if (res.data.code == 0 ) { console .log('【step 3】请求成功:' ); console .log(res.data); return resolve(res.data); } else { wx.showModal({ title : '请求失败' , content : res.data.message, showCancel : false }); } }, fail : err => { // 失败时的处理 console .log(err); return reject(err); } }) })}/** * code 换取 openId * @data { * jsCode - wx.login() 返回的 code * } */ export const wxLogin = data => { return fetch({ url : 'tbcUser/getWechatOpenId' , data : data })}复制代码
调用接口: 项目/pages/login/login.js
import { wxLogin,} from '../../utils/api.js' 复制代码
使用接口: 项目/pages/login/login.js
wxLogin({ jsCode : this .data.code}).then( res => { console .log('【step 4】返回成功处理:' ); console .log(res.data); }, err => { console .log('【step 4】返回失败处理:' ); console .log(err); })复制代码
返回目录
通过 url 携带参数,在 onLoad()
中通过 options
获取 url 上的参数: 代码演示
<navigator url ='../index/index?userId={{userId}}' > </navigator > <!-- 这两段是分别在 HTML 和 JS 中的代码 --> onLoad: function(options) { console.log(options.userId);}复制代码
通过 Storage 来传递参数: wx.setStorageSync('userId' , 'jsliang' );wx.getStorageSync('userId' );复制代码
WXML 传递数据到 JS login.wxml
<text bindtap ='clickText' data-labelId ='{{userId}}' > 点击传递数据到 JS</text > 复制代码
login.js
clickText(e) { console .log(e.currentTarget.labelid)}复制代码
组件调用传参 组件接收数据:component-tag-name
Component({ properties : { // 这里定义了innerText属性,属性值可以在组件使用时指定 innerText: { type : String , value : 'default value' , } }})复制代码
使用组件的页面定义 json
{ 'usingComponents' : { 'component-tag-name' : '../component/component' }}复制代码
使用组件的页面 HTML 代码
<view > <!-- 以下是对一个自定义组件的引用 --> <component-tag-name inner-text ='Some text' > </component-tag-name > </view > 复制代码
通过接口调用传递参数 返回目录
通过 this.$preload()
预加载用户可能点击的第二个页面。 组件化页面,出现两次以上的部分都进行封装成组件。 提取共用的 CSS 样式。 优化图片:TinyPNG 。 返回目录
优势 :
无需下载 打开速度较快 开发成本低于原生 APP 劣势 :
限制多。页面大小不能超过 1M,不能打开超过 5 个层级的页面。 样式单一。小程序内部组件已经成宿,样式不可以修改。 推广面窄。跑不出微信,还不能跑入朋友圈。 微信小程序有着低开发成本、低获客成本、无需下载的优势。
依赖环境不同。一个能在多种手机浏览器运行。一个只能在微信中的非完整的浏览器。 开发成本不同。一个可能在各种浏览器出问题。一个只能在微信中运行。 微信小程序看似就是阉割版的 Vue。
返回目录
本质上就是一个单页面应用,所有的页面渲染和事件处理,都在一个页面中进行。 架构为数据驱动的模式,UI 和数据分离,所有页面的更新,都需要通过对数据的更改来实现。 微信小程序分为两个部分:webview 和 appService。其中 webview 主要用来展示 UI,appServer 用来处理业务逻辑、数据及接口调用。它们在两个进程中进行,通过系统层 JSBridge 实现通信,实现 UI 的渲染、事件的处理。 返回目录
返回目录
关于 浏览器解析 URL ,jsliang 特意将资料结合起来:
防抖与节流 重绘与回流 浏览器解析 URL DNS 域名解析 TCP 三次握手与四次挥手 浏览器渲染页面 小伙伴们可以前往 《面试知识点 - JS 防抖与节流》 查看。
返回目录
关于 重绘与回流 ,jsliang 特意将资料结合起来:
防抖与节流 重绘与回流 浏览器解析 URL DNS 域名解析 TCP 三次握手与四次挥手 浏览器渲染页面 小伙伴们可以前往 《面试知识点 - JS 防抖与节流》 查看。
返回目录
存储于代码中,代码执行完毕释放内存。 存储于浏览器中,cookie 用于短期存储用户身份,登录状态等较小的信息;localStorage/sessionStorage 用于长期存储数据,浏览器关闭不影响它们的内存,相比于 cookie,storage 能存储较多;IndexedDB 是浏览器提供的接近于 NoSQL 的数据库,允许存储大量数据。 存储于数据库中。 返回目录
V8 将内存分为两类:新生代内存空间和老生代内存空间。
新生代内存空间:主要用来存放存活时间较短的对象。 老生代内存空间:主要用来存放存活时间较长的对象。 这两者通过不同的算法,对内存进行管理操作。
返回目录
使用 Chrome 的 Timeline(新版本 Performance)进行内存标记,可视化查看内存的变化情况,找出异常点。
返回目录
返回目录
目前网络分层可分为两种:OSI 模型和 TCP/IP 模型。
应用层(Application) 表示层(Presentation) 会话层(Session) 传输层(Transport) 网络层(Network) 数据链路层(Data Link) 物理层(Physical) 应用层(Application) 传输层(Host-to-Host Transport) 互联网层(Internet) 网络接口层(Network Interface) 更多详情可以查看下面这篇文章,里面讲得非常详细:
返回目录
HTTP :超文本传输协议(HTTP)是用于分布式,协作式和超媒体信息系统的应用协议。它是Web上数据交换的基础,是一种 client-server 协议,也就是说请求通常是由像浏览器这样的接受方发起的。HTTPS :HTTPS(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的 HTTP 通道,简单讲是 HTTP 的安全版。即 HTTP 下加入 SSL 层,HTTPS 的安全基础是 SSL,因此加密的详细内容就需要 SSL。 它是一个 URI scheme(抽象标识符体系),句法类同 http: 体系。用于安全的HTTP数据传输。https:URL 表明它使用了 HTTP,但 HTTPS 存在不同于 HTTP 的默认端口及一个加密/身份验证层(在 HTTP 与 TCP 之间)。这个系统的最初研发由网景公司进行,提供了身份验证与加密通讯方法,现在它被广泛用于万维网上安全敏感的通讯,例如交易支付方面。返回目录
首先,我们大致区分下状态码:
1**开头 - 信息提示 2**开头 - 请求成功 3**开头 - 请求被重定向 4**开头 - 请求错误 5**开头 - 服务器错误 然后,常见的状态码:
200 - 请求成功,Ajax 接受到信息了。 400 - 服务器不理解请求,工作中常见于跨域的时候后端给我报 400! 403 - 服务器拒绝请求。 404 - 请求页面错误。 500 - 服务器内部错误,无法完成请求。 最后,小伙伴们如果想要了解更多,还是需要自行查找资料的。
返回目录
关于 TCP 三次握手与四次挥手 ,jsliang 特意将资料结合起来:
防抖与节流 重绘与回流 浏览器解析 URL DNS 域名解析 TCP 三次握手与四次挥手 浏览器渲染页面 小伙伴们可以前往 《面试知识点 - JS 防抖与节流》 查看。
返回目录
通过优化从而提高页面的加载速度。
返回目录
避免 HTML 中书写 CSS 代码,因为这样难以维护。 使用 Viewport 加速页面的渲染。 使用语义化标签,减少 CSS 代码,增加可读性和 SEO。 减少标签的使用,DOM 解析是一个大量遍历的过程,减少不必要的标签,能降低遍历的次数。 避免 src、href 等的值为空,因为即时它们为空,浏览器也会发起 HTTP 请求。 减少 DNS 查询的次数。 返回目录
优化选择器路径:使用 .c {}
而不是 .a .b .c {}
。 选择器合并:共同的属性内容提起出来,压缩空间和资源开销。 精准样式:使用 padding-left: 10px
而不是 padding: 0 0 0 10px
。 雪碧图:将小的图标合并到一张图中,这样所有的图片只需要请求一次。 避免通配符:.a .b * {}
这样的选择器,根据从右到左的解析顺序在解析过程中遇到通配符 * {}
会遍历整个 DOM,性能大大损耗。 少用 float:float
在渲染时计算量比较大,可以使用 flex 布局。 为 0 值去单位:增加兼容性。 压缩文件大小,减少资源下载负担。 返回目录
尽可能把 <script>
标签放在 body
之后,避免 JS 的执行卡住 DOM 的渲染,最大程度保证页面尽快地展示出来。 尽可能合并 JS 代码:提取公共方法,进行面向对象设计等…… CSS 能做的事情,尽量不用 JS 来做,毕竟 JS 的解析执行比较粗暴,而 CSS 效率更高。 尽可能逐条操作 DOM,并预定好 CSs 样式,从而减少 reflow 或者 repaint 的次数。 尽可能少地创建 DOM,而是在 HTML 和 CSS 中使用 display: none
来隐藏,按需显示。 压缩文件大小,减少资源下载负担。 返回目录
在算法这块,jsliang 觉得自己还是比较薄弱的,如果小伙伴们跟 jsliang 一样,也想丰富下这方面知识,欢迎一起刷 LeetCode 共同进步:
返回目录
在 【其他】 这章,原本 jsliang 想谈谈面试中的一些小技巧,例如谈薪;或者讲讲 HR 面需要询问的问题,例如工作时长、加班机制、调薪机制等……
但是,最终看来,jsliang 的经历还是有所欠缺,所经历的面试不够 “盛大”,所以说出的话可能就是 “胡言乱语”、“误导观众”,故在此就不献丑了,如果小伙伴们想知道更多,可以通过 QQ 群:798961601
找到我。
☆ 目前 jsliang 通过 3 天的请假,去了 5 场面试,收获了 3 份 offer。 ☆ 如果小伙伴不知道简历该怎么写、面试总是镇静不下来、总感觉面试没谱,可以先找 jsliang 聊聊,我会讲讲个人的面试经历,以及听到的其他小伙伴的经历~
返回目录
在观看这篇文章的过程中,小伙伴可能会有这些疑问:
看完觉得不过瘾啊!你怎么就这么 “短” 啊? 回答 :
系列套餐你值得拥有!
你这杂七杂八的都写了什么呀?看完我晕乎了! 回答 :
每个人的学习经历是不同的,所拥有的技术、知识点以及工作经验等都是不同的。
所以 jsliang 的目的是通过这篇文章充实自己的同时,顺带挖掘自己的不足,例如面向对象造轮子、算法问题等让 jsliang 想进一步折腾,并应用到工作中。
因此,小伙伴应该根据自己实际去扩展补充属于自己的知识点。
毕竟了解自己的,只有自己!
好像你这里写得也不是很全啊?看完我还是一知半解的! 回答 :
每个人的目的都是不同的,不可能一篇文章写完所有知识点,同时有些知识点可能 jsliang 也不感兴趣、或者 jsliang 的层次不够,接触不到。
并且每个面试官都可能有自己的一套面试题,如果 jsliang 能将所有的面试题都写出来,那还需要面试官做啥,大家都像考国家证书一样直接电脑考试吧~(我也期待!!!)
如果小伙伴对文章存有疑问,想快速得到回复。 或者小伙伴对 jsliang 个人的前端文档库感兴趣,也想将自己的前端知识整理出来。 或者小伙伴对文章后续的更新感兴趣,掌握更多的面试技巧。 欢迎加 QQ 群一起探讨:798961601
。
返回目录
本文中的许多内容,也许小伙伴看了会觉得眼熟,因为它们大部分是 jsliang 参考大量文献,再经过刷选整理,最后根据自己理解后的一些阐述。
下面是个人觉得非常优秀的文章。
返回目录
《一位前端 2018 绝地求生记》 《中高级前端大厂面试秘籍,为你保驾护航金三银四,直通大厂(上)》 《InterviewMap》 《一篇文章搞定前端面试》 《微信小程序必知面试题》 《微信小程序面试题,附答案》 《小程序踩过的那些面试题坑,附答案解决方法》 返回目录
《前端工程师手册》 《HTML 教程- (HTML5 标准) - 菜鸟教程》 《前端分享之cookie的使用及单点登录》 《Cookie、session和localStorage、以及sessionStorage之间的区别》 返回目录
《前端工程师手册》 《CSS 权威指南》 《CSS 揭秘》 《CSS 世界》 《我对BFC的理解》 《CSS实现垂直居中的常用方法》 《CSS 用 position: absolute 与 transform 来居中块级元素的问题》 《css常见布局》 《CSS3 圆角》 《CSS3 渐变(Gradients)》 《CSS3 transition 属性》 《CSS3 transform 属性》 《CSS3 animation(动画) 属性》 《CSS3 box-shadow 属性》 《个人总结(css3新特性)》 返回目录
【推荐】《JavaScript - MDN》 《小邵教你玩转ES6》 《小邵教你玩转JS面向对象》 《实现双向绑定Proxy比defineproperty优劣如何》 《Vue 中关于 $emit 的用法》 《JavaScript 世界万物诞生记》 《js中的new()到底做了些什么??》 《MDN Function.prototype.call()》 《JavaScript中的call、apply、bind深入理解》 《箭头函数 - 廖雪峰》 《ECMAScript 6 入门 - 阮一峰》 《Vue原理解析之Virtual Dom》 《virtual-dom(Vue实现)简析》 《Vue.nextTick 的原理和用途》 返回目录
《前端性能优化最佳实践》 《到底什么是前端工程化、模块化、组件化》 《【前端工程化系列】简谈前端模块化开发与开发规范》 《个人关于模块化的理解》 《组件化开发和模块化开发概念辨析》 《JavaScript模块化 --- Commonjs、AMD、CMD、es6 modules》 《浅谈什么是前端工程化》 《前端分享之cookie的使用及单点登录》 《Cookie、session和localStorage、以及sessionStorage之间的区别》 《网络分层TCP/IP 与HTTP》 返回目录
查看了下掘金评论区,感谢各位大大的反馈,由于本人将于 2019年4月1日 入职,故将一些个人觉得不错的自己没有察觉的知识点记录下来,区分于原文,更为了猴年马月后的下一次跳槽进一步完善。
意思就是,jsliang 这货懒得改原文了,小伙伴们看着这里进行知识点补充
函数 A 里面包含了 函数 B,而 函数 B 里面使用了 函数 A 的变量,函数 B 被 return 了出去,那么 函数 B 被称为闭包。
当值为 border-box
时,宽度 width = content + padding + border
,包含内边距与边框。
当值为 content-box
时,宽度 width = content
,不包含内边距与边框。
em
是一个相对的大小,这里的相对于元素父元素的 font-size
。
Side Project 对应的中文就是副业、业余项目或者小项目。
感兴趣的小伙伴可以去了解一下。
这里原文已备注是有误的,只是一时没空,没有修改。
原文:!important -> 行内样式 -> #id -> .class -> 元素和伪元素 -> * -> 继承 -> 默认
网友:“应该是最后的优先级最高。”
这里最后的优先级最高应该是指同等级优先级覆盖。浏览器通过 CSSParser 将 CSS 解析成 CSS Rule Tree 的时候,没错的话应该是按照原文中的排序先加载,然后同等级的时候,后面的属性覆盖前面的属性。
对于 HTML5 的语义化,ARIA 的意思是 Accessible Rich Internet Application,aria-*
的作用就是描述这个 Tag 在可视化的情境中的具体信息。例如:
aria-label
:为组件指定内置的文本标签,用来替代开发者没有使用 <label>
标签aria-labelledby
:会读取与此具有相同的 id
名的值详情可参考张鑫旭的 《WAI-ARIA无障碍网页应用属性完全展示》
sessionStorage 和 localStorage :文章描述不够详细。
child-tow
中设置 width: 100%
的时候 child-one
的宽度会随机而变,设置 flex: 1
就不会。所以看个人需求进行设置。文章中没有讲到应对兼容性怎么设置,可以考虑使用 float
进行相关的布局。 可参考文章:《深拷贝的终极探索(90%的人不知道)》
文章描述不够详细。
本来打算写的,后面没时间,给我删了这块,评论区有篇文献参考:
《九种跨域方式实现原理(完整版)》
以上,即为目前评论区的补充,感谢各位小伙伴的点赞支持。
jsliang 广告推送: 也许小伙伴想了解下云服务器 或者小伙伴想买一台云服务器 或者小伙伴需要续费云服务器 欢迎点击 云服务器推广 查看!
jsliang 的文档库 由 梁峻荣 采用 知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议 进行许可。 基于github.com/LiangJunron… 上的作品创作。 本许可协议授权之外的使用权限可以从 creativecommons.org/licenses/by… 处获得。