Create by jsliang on 2019-2-11 15:30:34
Recently revised in 2019-3-17 21:30:36javascript
Hello 小伙伴们,若是以为本文还不错,记得给个 star , 小伙伴们的 star 是我持续更新的动力!GitHub 地址php
【2019-08-16】Hello 小伙伴们,因为 jsliang 对文档库进行了重构,这篇文章中的一些连接可能失效,而 jsliang 缺少精力维护掘金这边的旧文章,对此深感抱歉。请须要获取最新文章的小伙伴,点击上面的 GitHub 地址,去文档库查看调整后的文章。css
并非只有特定的季节才能跑路,只由于人跑得多了,这条路就定下来了。html
金三银四跳槽季,jsliang 于 2019年2月11日 写下了这篇文章,开始准备本身的面试之旅。前端
至 2019年3月17日 为止,jsliang 搭建出我的的面试知识体系,海量地翻阅了一些前辈留下的资料,结合我的需求进行了几场面试,从而进一步完善该文章并进行了发表,但愿对准备跳槽或者正在跳槽中的小伙伴有所帮助。vue
不折腾的前端,和咸鱼有什么区别java
返回目录css3
请时刻准备好本身的简历,无论是互联网经济不佳面临裁人,仍是由于公司内部斗争严重心乱如麻,仍是由于厌倦了目前的一切……只有随时更新本身,把本身的简历准备好,你才知道哪一刻跑路是最佳选择。git
返回目录es6
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,因而就进了这家公司,那时候感受本身前面的大学生活白过了,只懂 ES五、jQuery、HTML/HTML五、CSS/CSS3 的皮毛。
在熟悉了三个月的业务,公司给的任务能顺利完成后,我以为本身不够努力:外面的前端翻天覆地,个人技术却只是 jQuery is all!
因而 2018 年 8 月,jsliang 开始写 Markdown,将 5 月份到 8 月份记录到 Word 文档上的笔记整理成了 jsliang 的文档库,并在 jsliang 的掘金 上发表了第一篇文章。
18 年 8 月至今,jsliang 大体经历了如下这些:
以上,就是 jsliang 的编程生涯。
今儿,在这里写写 jsliang 为了跳槽,根据我的想法进行的一些前端面试资料整理,小伙伴们以为不错的点个赞或者去 GitHub 点个 star,以为有误请指出,谢谢~
马老板曾经说过,跳槽有两个缘由:
首先,若是非要给 jsliang 我本身的跳槽定个位,那确定是钱没给到位,劳动与产出不成正比。在我 2018 年 5 月入职前,与人事的交谈中了解到每一年的 8 月和 2 月能够提薪,当初的技术栈是:HTML、CSS、ES5。
而后,2018 年 6 月到 2019 年 1 月,学习并应用到工做中的技术有:
其中 2018 年 8 月刚转正,也不敢说本身技术进步很大,也不敢说本身项目贡献很大,为公司谋了多大利益,因此没有提薪想法。
2019 年 1 月底感受本身项目也作了,凌晨 4/5/6 点的体育西路也看过了,技术也提高了,因而跟人事交谈,指望 2 月能加薪,人事表示年终述职演讲得好的给提薪,2 月开工的时候表示提薪名单没我份……
你没看错,提薪全靠 PPT。PPT 里提升了不给,没提就是没有。
当初想法很简单,你随便加个 5/600 我也知足了。
最后,jsliang 曾跟项目总监私下谈话,建议能够发展一些新产品,这样公司或许能获取一些新收入,我也能够进一步挑战个人技术。可是,因为我司是个老牌子公司,而且大部分依赖于接手电信项目进行扩张……
enm...因此心也委屈了。
在 2018 的努力下,GitHub 破 600 近 700 star,掘金破 10 万阅读量,3000 粉丝:
GitHub 见证:点击查看
掘金见证:点击查看
1. 熟悉 HTML/HTML五、CSS/CSS三、ES5/ES6。
2. 了解 OOP 概念,并尝试在工做中使用过 OOP 技巧。
3. 对 MVC/MVVM 架构有必定了解,若有 Vue/React/Angular 或者 微信小程序开发经验更佳。
4. 使用过 Bootstrap 或者 ElementUI 等 UI 库,并对前端 UI 库有必定的我的理解。
5. 了解 Git、Webpack 等工具。
6. 对 Java、Node.js 等后端编程有必定了解。
7. 一年及以上工做经验。
复制代码
该分析数据来自 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 内核。
<!--[if IE]><![endif]-->
<!--[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:存储于浏览器端的数据。能够设置 cookies 的到期时间,若是不设置时间,则在浏览器关闭窗口的时候会消失。
session:存储于服务器端的数据。session 存储特定用户会话所需的属性和配置信息。
cookies 和 session 的区别在于:
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-box
box-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
.class
p
、a
等……p span
、div a
等……a:hover
等……input[type="text"]
等……li:firth-child
、p:nth-child(1)
等……!important -> 行内样式 -> #id -> .class -> 元素和伪元素 -> * -> 继承 -> 默认
<!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 新特性都有哪些呢?
为了方便记忆,咱将它们扔到同一个 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 有一系列的渲染规则,利用这些渲染规则能够达到必定的布局效果。
参考文献:《我对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;
}
复制代码
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;
display: flex; justify-content: center;
垂直居中:
line-height: height
display: flex; align-items: center;
参考文献:
① 《CSS实现垂直居中的经常使用方法》
② 《CSS 用 position: absolute 与 transform 来居中块级元素的问题》
HTML 属于结构层,负责描绘出内容的结构。
CSS 属于表示层,负责如何显示有关内容。
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>
复制代码
注意:
<script>
,由于浏览器解析顺序缘故,若是解析到死循环之类的 JS 代码,会卡住页面。关于 prototype
、__proto__
、new
、call()
、apply()
、bind()
、this
这些的知识点,因为篇幅太长,jsliang 已经抽离了出来,并作了简洁详细讲解,详见:
下面放出相关知识点:
__proto__
属性(原型)等于其构造函数的 prototype
属性。在 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 了。
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
定时器外部:2
0
1
2
复制代码
即代码仍是先执行 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 的值也跟着发生了变化,这时候就叫浅拷贝。若是不发生变化,就叫深拷贝。
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 进行的深拷贝,没法拷贝到 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》
⑥ 《浅谈什么是前端工程化》
简单来讲,就是增长代码的可复用性,减小我们的工做,使代码更加流畅。
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); // jsliang
p1.eat(); // jsliang 吃饭
复制代码
固然,jsliang 只能写到这里了,再写下去就是设计模式等知识点了。
因此但愿小伙伴们仍是了解下面向对象思想,有助于进一步提高本身。
关于 防抖与节流,jsliang 特地将资料结合起来:
小伙伴们能够前往 《面试知识点 - JS 防抖与节流》 查看。
ES6 是个大知识点,若是你面试的公司不是 “饱经沧桑” 的那种,那么必定会出点 ES6 问题,例如:
由于 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 来统一管理。
$el
和数据对象 data 以及事件还未初始化。在 created 阶段,Vue 实例的数据对象 data 以及方法的运算有了,$el
尚未。render
函数首次被调用,Vue 实例的 $el 和 data 都初始化了,但仍是挂载在虚拟的 DOM 节点上。在 mounted 阶段,Vue 实例挂载到实际的 DOM 操做完成,通常在该过程进行 Ajax 交互。Vue 实例从建立到销毁的过程,就是生命周期。从开始建立、初始化数据、编译模板、挂载 DOM -> 渲染、更新 -> 渲染、销毁等一系列过程,称之为 Vue 的生命周期。
8 个,建立前/建立后、挂载前/挂载后、更新前/更新后、销毁前/销毁后。Vue 生命周期的做用是方便咱们经过它的生命周期,在业务代码中更好地操做数据,实现相关功能。
会触发 4 个生命钩子:建立前/建立后、挂载前/挂载后
在 beforeMounted
时它执行了 render
函数,对 $el 和 data 进行了初始化,但此时仍是挂载到虚拟的 DOM 节点,而后它在 mounted
时就完成了 DOM 渲染,这时候咱们通常还进行 Ajax 交互。
Vue 采用 数据劫持 结合 发布者-订阅者 模式的方式,经过 Object.defineProperty()
来劫持各个属性的 setter 以及 getter,在数据变更时发布消息给订阅者,触发相应的监听回调。
dep.notice()
通知时,能调用自身的 update()
方法,并触发 Compile 中绑定的回调,则功成身退。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 在 render
中 createElement
的时候,并非产生真实的 DOM 元素,实际上 createElement
描述为 createNodeDescription
,由于它所包含的信息会告诉 Vue 页面上须要渲染什么样的节点。
所以,咱们将这样的节点描述为 “虚拟节点”(Virtual Node),简称 VNode。“虚拟 DOM” 是咱们对由 Vue 组件树创建的整个 VNode 树的称呼。
做为一枚切图仔,很荣幸地跟小伙伴说:“其实我也不懂 Virtual DOM!”
可是,总会有些面试场合会提到的,因此这里找了几篇资料,小伙伴们能够进一步学习:
其余的就须要小伙伴本身寻找了,若是以为有不错的解析 Virtual DOM 的文档/视频,小伙伴也能够推荐过来哈~
Vue 中 template 就是先转化成 AST 树,再获得 render 函数返回 VNode(Vue 的虚拟 DOM 节点)。
key 的做用就是在更新组件时判断两个节点是否相同。相同就复用,不相同就删除旧的建立新的。
对于 diff 过程来讲 key 是起不到提速做用的,详见:key 的做用
用法:Vue.nextTick( [callback, context] )
参数:
{Function} [callback]
{Object} [context]
说明:在下次 DOM 更新循环结束以后执行延迟回调。在修改数据以后当即使用这个方法,获取更新后的 DOM。
案例:
// 修改数据
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);
}
)
复制代码
onLoad()
中经过 options
获取 url 上的参数:代码演示
<navigator url="../index/index?userId={{userId}}"></navigator>
<!-- 这两段是分别在 HTML 和 JS 中的代码 -->
onLoad: function(options) {
console.log(options.userId);
}
复制代码
wx.setStorageSync('userId', 'jsliang');
wx.getStorageSync('userId');
复制代码
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()
预加载用户可能点击的第二个页面。优点:
劣势:
微信小程序有着低开发成本、低获客成本、无需下载的优点。
微信小程序看似就是阉割版的 Vue。
关于 浏览器解析 URL,jsliang 特地将资料结合起来:
小伙伴们能够前往 《面试知识点 - JS 防抖与节流》 查看。
关于 重绘与回流,jsliang 特地将资料结合起来:
小伙伴们能够前往 《面试知识点 - JS 防抖与节流》 查看。
V8 将内存分为两类:新生代内存空间和老生代内存空间。
这二者经过不一样的算法,对内存进行管理操做。
意外的全局变量:没法被回收。
定时器:未被正确关闭,致使所引用的外部变量没法被释放。
事件监听:没有正确销毁(低版本浏览器可能出现)。
闭包:会致使父级中的变量没法被释放。
DOM 引用:DOM 被删除时,内存中的引用未被正确清空。
如何查看内存变化状况?
使用 Chrome 的 Timeline(新版本 Performance)进行内存标记,可视化查看内存的变化状况,找出异常点。
目前网络分层可分为两种:OSI 模型和 TCP/IP 模型。
更多详情能够查看下面这篇文章,里面讲得很是详细:
首先,咱们大体区分下状态码:
而后,常见的状态码:
最后,小伙伴们若是想要了解更多,仍是须要自行查找资料的。
关于 TCP 三次握手与四次挥手,jsliang 特地将资料结合起来:
小伙伴们能够前往 《面试知识点 - JS 防抖与节流》 查看。
经过优化从而提升页面的加载速度。
.c {}
而不是 .a .b .c {}
。padding-left: 10px
而不是 padding: 0 0 0 10px
。.a .b * {}
这样的选择器,根据从右到左的解析顺序在解析过程当中遇到通配符 * {}
会遍历整个 DOM,性能大大损耗。float
在渲染时计算量比较大,能够使用 flex 布局。<script>
标签放在 body
以后,避免 JS 的执行卡住 DOM 的渲染,最大程度保证页面尽快地展现出来。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 参考大量文献,再通过刷选整理,最后根据本身理解后的一些阐述。
下面是我的以为很是优秀的文章。
查看了下掘金评论区,感谢各位大大的反馈,因为本人将于 2019年4月1日 入职,故将一些我的以为不错的本身没有察觉的知识点记录下来,区分于原文,更为了猴年马月后的下一次跳槽进一步完善。
意思就是,jsliang 这货懒得改原文了,小伙伴们看着这里进行知识点补充
函数 A 里面包含了 函数 B,而 函数 B 里面使用了 函数 A 的变量,函数 B 被 return 了出去,那么 函数 B 被称为闭包。
box-sizing
属性:当值为 border-box
时,宽度 width = content + padding + border
,包含内边距与边框。
当值为 content-box
时,宽度 width = content
,不包含内边距与边框。
em
是一个相对的大小,这里的相对于元素父元素的 font-size
。
Side Project 对应的中文就是副业、业余项目或者小项目。
感兴趣的小伙伴能够去了解一下。
push
与 shift
系列:这里原文已备注是有误的,只是一时没空,没有修改。
原文:!important -> 行内样式 -> #id -> .class -> 元素和伪元素 -> * -> 继承 -> 默认
网友:“应该是最后的优先级最高。”
这里最后的优先级最高应该是指同等级优先级覆盖。浏览器经过 CSSParser 将 CSS 解析成 CSS Rule Tree 的时候,没错的话应该是按照原文中的排序先加载,而后同等级的时候,后面的属性覆盖前面的属性。
对于 HTML5 的语义化,ARIA 的意思是 Accessible Rich Internet Application,aria-*
的做用就是描述这个 Tag 在可视化的情境中的具体信息。例如:
aria-label
:为组件指定内置的文本标签,用来替代开发者没有使用 <label>
标签aria-labelledby
:会读取与此具备相同的 id
名的值详情可参考张鑫旭的 《WAI-ARIA无障碍网页应用属性彻底展现》
文章描述不够详细。
child-tow
中设置 width: 100%
的时候 child-one
的宽度会随机而变,设置 flex: 1
就不会。因此看我的需求进行设置。float
进行相关的布局。可参考文章:《深拷贝的终极探索(90%的人不知道)》
Promise
与 async
/await
:文章描述不够详细。
原本打算写的,后面没时间,给我删了这块,评论区有篇文献参考:
以上,即为目前评论区的补充,感谢各位小伙伴的点赞支持。
jsliang 广告推送:
也许小伙伴想了解下云服务器
或者小伙伴想买一台云服务器
或者小伙伴须要续费云服务器
欢迎点击 云服务器推广 查看!
jsliang 的文档库 由 梁峻荣 采用 知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议进行许可。
基于github.com/LiangJunron…上的做品创做。
本许可协议受权以外的使用权限能够从 creativecommons.org/licenses/by… 处得到。