先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Web前端全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip1024c (备注前端)
正文
- 在
JavaScript
标准中,规定了ToPrimitive
函数,它是对象类型到基本类型的转换(即,拆箱转换)
❝
对象到 String 和 Number 的转换都遵循“先拆箱再转换”的规则。通过拆箱转换,把对象变成基本类型,再从基本类型转换为对应的 String 或者 Number。
❞
- 拆箱转换会尝试调用
valueOf
和toString
来获得拆箱后的基本类型。如果valueOf
和toString
都不存在,或者没有返回基本类型,则会产生类型错误 TypeError。
var o = {
valueOf: () => {
console.log(“valueOf”);
return {};
},
toString: () => {
console.log(“toString”);
return {};
},
};
// Number 的转换 先 valueOf 再 toString
o * 2; // TypeError
// String 的转换则是 先 toString 再 valueOf
String(o); // TypeError
// 在 ES6 之后,还允许对象通过显式指定 @@toPrimitive Symbol 来覆盖原有的行为。
o[Symbol.toPrimitive] = () => {
console.log(“toPrimitive”);
return “hello”;
};
// toPrimitive
console.log(o + “”); // hello
11. try
里面放 return
,finally
还会执行吗?
finally
不管try
/catch
如何处理最终都会执行,并且如果finally
中加入return
/throw
则会覆盖try
/catch
的return
或者throw
;
function foo() {
try {
return 0;
} catch (err) {
} finally {
// 这里会先执行
console.log(“a”);
}
}
console.log(foo());
// a
// 0
function foo() {
try {
i++;
return 0;
} catch (err) {
throw err;
} finally {
// 最终以 finally 为主
return 1;
}
}
console.log(foo()); // 1
12. 为什么 12.toString
会报错?
- 这时候
12.
会被当作省略了小数点后面部分的数字,而单独看成一个整体,所以我们要想让点单独成为一个token
,就要加入空格,或者 .,这样写:12 .toString()
/12..toString()
// 数字直接量
.01
12.01
❝
Token 词
- IdentifierName 标识符名称,典型案例是我们使用的变量名,注意这里关键字也包含在内了。
- Punctuator 符号,我们使用的运算符和大括号等符号。
- NumericLiteral 数字直接量,就是我们写的数字。
- StringLiteral 字符串直接量,就是我们用单引号或者双引号引起来的直接量。
- Template 字符串模板,用反引号` 括起来的直接量。
❞
13. 关于 **
乘方表达式?
**
运算是右结合的,因此2 ** 2 ** 3
运算规则如下:
2 ** (2 ** 3); // 256
-2
这样的一元运算表达式,是不可以放入乘方表达式的,如果需要表达类似的逻辑,必须加括号。
(++i) ** 30;
2 ** 30; //正确
// -2 ** 30 //报错
(-2) ** 30;
14. 关于 ==
的几个错觉?
- 即使字符串与布尔值比较,也都要转换为数字
false == “0”; // true
true == “true”; // false
- 对象如果转换成了 primitive 类型跟等号另一边类型恰好相同,则不需要转换成数字。
[] == “” // true
[] == 0 // true
[] == false // true
❝
所以
==
比较坑,尽量还是使用===
,或者仅在确定字符串与数值比较时去使用==
❞
15. 从输入 URL 到看到网页,经历了什么?
-
浏览器首先使用 HTTP 协议或者 HTTPS 协议,向服务端请求页面;
-
把请求回来的 HTML 代码经过解析,构建成 DOM 树;
-
计算 DOM 树上的 CSS 属性;
-
最后根据 CSS 属性对元素逐个进行渲染,得到内存中的位图;
-
一个可选的步骤是对位图进行合成,这会极大地增加后续绘制的速度;
-
合成之后,再绘制到界面上。
16. HTTP1.1/HTTP2/HTTPS 区别?
- HTTP2 相比于 HTTP1.1
❝
总的来说 HTTP2 大幅度的提升了 web 性能。在与 HTTP/1.1 完全语义兼容的基础上,进一步减少了网络延迟,在性能上大幅提升。
❞
❝
在二进制分帧层中, HTTP/2 会将所有传输的信息分割为更小的消息和帧(frame),并对它们采用二进制格式的编码 ,其中 HTTP1.x 的首部信息会被封装到 HEADER frame,而相应的 Request Body 则封装到 DATA frame 里面。
HTTP/2 通信都在一个连接上完成,这个连接可以承载任意数量的双向数据流。
在过去, HTTP 性能优化的关键并不在于高带宽,而是低延迟。TCP 连接会随着时间进行自我「调谐」,起初会限制连接的最大速度,如果数据成功传输,会随着时间的推移提高传输的速度。这种调谐则被称为 TCP 慢启动。由于这种原因,让原本就具有突发性和短时性的 HTTP 连接变的十分低效。
HTTP/2 通过让所有数据流共用同一个连接,可以更有效地使用 TCP 连接,让高带宽也能真正的服务于 HTTP 的性能提升。
❞
❝
HTTP/1.1 并不支持 HTTP 首部压缩,为此 SPDY 和 HTTP/2 应运而生, SPDY 使用的是通用的 算法,而 HTTP/2 则使用了专门为首部压缩而设计的 HPACK 算法。
❞
-
- 单连接多资源的方式,减少服务端的链接压力,内存占用更少,连接吞吐量更大
-
由于 TCP 连接的减少而使网络拥塞状况得以改善,同时慢启动时间的减少,使拥塞和丢包恢复速度更快
-
首部压缩
-
服务端推送:能够在客户端发送第一个请求到服务端时,提前把一部分内容推送给客户端,放入缓存当中,这可以避免客户端请求顺序带来的并行度不高,从而导致的性能问题。
-
TCP 连接复用,则使用同一个 TCP 连接来传输多个 HTTP 请求,避免了 TCP 连接建立时的三次握手开销,和初建 TCP 连接时传输窗口小的问题。
-
二进制分帧
-
HTTPS 有两个作用,一是确定请求的目标服务端身份,二是保证传输的数据不会被网络中间节点窃听或者篡改。
-
❝
HTTPS 是使用加密通道来传输 HTTP 的内容。但是 HTTPS 首先与服务端建立一条 TLS 加密通道。TLS 构建于 TCP 协议之上,它实际上是对传输的内容做一次加密,所以从传输内容上看,HTTPS 跟 HTTP 没有任何区别。
❞
17. ['1', '2', '3'].map(parseInt)
输出什么?
- 乍一看可能会说出
[1, 2, 3]
,其实不然,答案是[1, NaN, NaN]
[“1”, “2”, “3”].map(parseInt);
// parseInt(string, radix) 接收2个参数,(要处理的值, 解析时的基数)
// 基数是一个介于2和36之间的整数
// 平铺一下
[“1”, “2”, “3”].map((item, idx) => parseInt(item, idx));
parseInt(“1”, 0); // 1 radix为 0时该值无效,且第一个参数不以“0x”和“0”开头时,按照10为基数处理。这个时候返回1
parseInt(“2”, 1); // NaN 当radix小于2并且大于36或第一个参数的第一个非空格字符不能转换为数字。
parseInt(“3”, 2); // NaN 基数为2(2进制)表示的数中,最大值小于3,所以无法解析,返回NaN
18. Set/Map/WeakSet/WeakMap 区别?
- Set
❝
- 成员不能重复
- 只有健值,没有健名,有点类似数组。
- 可以遍历,方法有 add, delete, has
❞
- WeakSet
❝
- 只能储存对象引用,不能存放值,而 Set 对象都可以
- 成员都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的应用,随时可以消失。可以用来保存 DOM 节点,不容易造成内存泄漏
- 不能遍历,方法有 add, delete, has
❞
- Map
❝
- 本质上是健值对的集合,类似集合
- 可以遍历,方法很多,方便跟各种数据格式进行转换
❞
- WeakMap
❝
- 直接受对象作为健名(null 除外),不接受其他类型的值作为健名
- 健名所指向的对象,不计入垃圾回收机制
- 不能遍历,方法同 get, set, has, delete
❞
19. 描述下 es5/es6 继承的区别?
class
的声明没有被变量提升,类似let/const
的声明,不能前置使用;
var t = new Test(); // Test is not defined
class Test {}
class
声明内部会启用严格模式
class Test {
constructor() {
empty = “test”; // empty is not defined
}
}
class
的所有方法(包括静态方法和实例方法)都是不可枚举的
class Text {
constructor() {
this.a = 1;
}
func1() {}
func2() {}
}
console.log(Object.keys(Text)); // []
console.log(Object.keys(Text.prototype)); // []
Object.keys(new Text()); // [‘a’]
function Func() {
this.a = 1;
this.fun1 = function () {};
this.fun2 = function () {};
}
Func.prototype.func3 = function () {};
console.log(Object.keys(Func)); // []
console.log(Object.keys(Func.prototype)); // [‘func3’]
Object.keys(new Func()); // [‘a’, ‘func1’, ‘func2’]
class
的所有方法(包括静态方法和实例方法)都没有原型对象prototype
,所以也没有constructor
,不能使用 new 来调用其方法
var a = new Text();
new a.func1(); // a.test is not a constructor
- 必须使用
new
调用class
Text(); // Class constructor A cannot be invoked without ‘new’
new Text();
20. 简述下浏览器的渲染过程?
-
解析 HTML,生成 DOM 树,解析 CSS,生成 CSSOM 树
-
将 DOM 树和 CSSOM 树结合,生成渲染树(Render Tree)
❝
构建渲染树:
- 从 DOM 树的根节点开始遍历每个可见节点。
- 对于每个可见的节点,找到 CSSOM 树中对应的规则,并应用它们。
- 根据每个可见节点以及其对应的样式,组合生成渲染树。
❞
-
Layout(回流):根据生成的渲染树,进行回流(Layout),得到节点的几何信息(位置,大小)
-
Painting(重绘):根据渲染树以及回流得到的几何信息,得到节点的绝对像素
-
Display:将像素发送给 GPU,展示在页面上。(这一步其实还有很多内容,比如会在 GPU 将多个合成层合并为同一个层,并展示在页面中。而 css3 硬件加速的原理则是新建合成层,这里我们不展开,之后有机会会写一篇博客)
浏览器渲染过程
21. 回流和重绘?
- 重绘:由于节点的几何属性发生改变或者由于样式发生变化而不影响布局的成为重绘。
❝
例如 outline, visibility, color、background-color 等,重绘的代价是高昂的,因为浏览器必须验证 DOM 树上其他节点元素的可见性。
❞
- 回流:回流是布局或者几何属性需要改变就称为回流。回流是影响浏览器性能的关键因素,因为其变化涉及到部分页面(或是整个页面)的布局更新。一个元素的回流可能会导致了其所有子元素以及 DOM 中紧随其后的节点、祖先节点元素的随后的回流。
❝
大部分的回流将导致页面的重新渲染,回流必定会导致重绘,但是,重绘不一定会引发回流
❞
22. 如何优化重绘重排?
- 1.浏览器优化
❝
现代浏览器大多都是通过
队列机制
来批量更新布局,浏览器会把修改操作放在队列中,至少一个浏览器刷新(即 16.6ms)才会清空队列,但当你获取布局信息的时候,队列中可能有会影响这些属性或方法返回值的操作,即使没有,浏览器也会强制清空队列
,触发回流与重绘来确保返回正确的值。
以下属性或方法的使用都会强制刷新队列,应避免频繁使用:
- offsetTop、offsetLeft、offsetWidth、offsetHeight
- scrollTop、scrollLeft、scrollWidth、scrollHeight
- clientTop、clientLeft、clientWidth、clientHeight
- width、height
- getComputedStyle()
- getBoundingClientRect()
❞
- 2.减少重绘与回流
❝
- 使用 transform 替代 to
- 使用 visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流(改变了布局)
- 避免使用 table 布局,可能很小的一个小改动会造成整个 table 的重新布局。
- 尽可能在 DOM 树的最末端改变 class,回流是不可避免的,但可以减少其影响。尽可能在 DOM 树的最末端改变 class,可以限制了回流的范围,使其影响尽可能少的节点。
- 避免设置多层内联样式,CSS 选择符从右往左匹配查找,避免节点层级过多。
- 将动画效果应用到 position 属性为 absolute 或 fixed 的元素上,避免影响其他元素的布局,这样只是一个重绘,而不是回流,同时,控制动画速度可以选择 requestAnimationFrame
- 避免使用 CSS 表达式,可能会引发回流。
- 将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点,例如 will-change、video、iframe 等标签,浏览器会自动将该节点变为图层。
- CSS3 硬件加速(GPU 加速),使用 css3 硬件加速,可以让 transform、opacity、filters 这些动画不会引起回流重绘 。但是对于动画的其它属性,比如 background-color 这些,还是会引起回流重绘的,不过它还是可以提升这些动画的性能。
- 避免频繁操作样式,最好一次性重写 style 属性,或者将样式列表定义为 class 并一次性更改 class 属性。
- 避免频繁操作 DOM,创建一个 documentFragment,在它上面应用所有 DOM 操作,最后再把它添加到文档中。
- 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
- 对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。
❞
23. 介绍下 js 的模块化?
- Commonjs(2009):号召规范服务端的 js 接口,形成了 ServerJs 规范(即 CommonJs)CommonJS 内的模块规范成为了 Node.js 的标准实现规范
// file module.js
// 对外输出
module.exports = {
a: 1,
b: 2,
};
// file test.js 引入一个模块
var test = require(“module.js”).a; // 1
- AMD(2009):js 模块的异步加载 ,
require.js
、curl
是其对应实现
❝
总结
-
框架原理真的深入某一部分具体的代码和实现方式时,要多注意到细节,不要只能写出一个框架。
-
算法方面很薄弱的,最好多刷一刷,不然影响你的工资和成功率😯
-
在投递简历之前,最好通过各种渠道找到公司内部的人,先提前了解业务,也可以帮助后期优秀 offer 的决策。
-
要勇于说不,对于某些 offer 待遇不满意、业务不喜欢,应该相信自己,不要因为当下没有更好的 offer 而投降,一份工作短则一年长则 N 年,为了幸福生活要慎重选择!!!
喜欢这篇文章文章的小伙伴们点赞+转发支持,你们的支持是我最大的动力!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
❞
23. 介绍下 js 的模块化?
- Commonjs(2009):号召规范服务端的 js 接口,形成了 ServerJs 规范(即 CommonJs)CommonJS 内的模块规范成为了 Node.js 的标准实现规范
// file module.js
// 对外输出
module.exports = {
a: 1,
b: 2,
};
// file test.js 引入一个模块
var test = require(“module.js”).a; // 1
- AMD(2009):js 模块的异步加载 ,
require.js
、curl
是其对应实现
❝
总结
-
框架原理真的深入某一部分具体的代码和实现方式时,要多注意到细节,不要只能写出一个框架。
-
算法方面很薄弱的,最好多刷一刷,不然影响你的工资和成功率😯
-
在投递简历之前,最好通过各种渠道找到公司内部的人,先提前了解业务,也可以帮助后期优秀 offer 的决策。
-
要勇于说不,对于某些 offer 待遇不满意、业务不喜欢,应该相信自己,不要因为当下没有更好的 offer 而投降,一份工作短则一年长则 N 年,为了幸福生活要慎重选择!!!
喜欢这篇文章文章的小伙伴们点赞+转发支持,你们的支持是我最大的动力!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-CbR2MGLH-1713119252877)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!