期末答疑(一):前端代码单元测试怎么做?
文章目录
你好,我是 winter。
我们专栏课程的知识部分已经告一段落了。今天,我来集中解决一下大家在学习中遇到的问题,我争取用快问快答的形式,咱们多回答一些问题。
1. 前端代码单元测试还是非常有必要的,不知道老师这一块是怎么做的,能否分享一下?
答:关于单元测试这件事,虽然在业务代码我没做成功过,但是它在框架和基础库开发中起到了非常积极的作用。
我们平时写代码也肯定写一部分就要运行一下试试,其实这种行为就是单元测试,只是我们把很多自动化的内容,用人肉执行了,并且没有保存和管理 case,也没有统计 code coverage。
只要选择一个好的单元测试框架,单元测试成本其实不高,尤其是比较复杂的底层库,引入单元测试不但不会消耗时间,还会提高效率。
所以我认为单元测试要实行,有两个关键点你要格外注意:一是出一套好的单元测试方案,二是在基础库和框架开发中引入单元测试。
2. 关于 Undefined,如果一个变量没有赋值后面又赋值,这个过程就是“变量会被篡改”的意思么?而 null 为什么又不会被篡改?一个变量开始定义为 null 然后赋值其他数据这个过程不算篡改吗?
答:undefined 是个全局变量,null 是个关键字,在一些版本比较旧的浏览器上,你可以试试:
|
|
但是你在任何版本的浏览器上,都不能这么干:
|
|
这样的话,上面这个代码就会报错了。
3. winter 老师你好,我们公司的前端是 Node.js 写的,如何做性能监控呢,如何做页面加载优化呢,我对您的页面性能打分系统很感兴趣,能详细讲一讲吗?谢谢了。
答:首先,Node.js 写的是服务端代码跟前端性能没有任何关系,Node.js 的性能监控比前端性能监控复杂得多,你可以了解下 alinode。
前端性能打分可能主要包含几个部分。
- 图片:检查图片数量和图片大小,比如单个超过 50k,总量超过 400k 的图片就要注意了,如果检查到小图片,也可以建议用 data uri 内联。
- 请求数:检查请求数,检查是否有独立的 JS、CSS 请求,这些都是潜在的优化点。
域名:检查域名是否有在 http dns 的范围内,检查域名数量是否过多,检查资源文件域名是否属于 CDN。 - 实际加载时间:如果测试环境加载时间过程,也可能说明一些问题。
- 缓存:检查静态资源是否设置了正确的缓存。
你可以自己动手试试。
4. 有一个疑惑是,大小写的两个属性有什么区别呢,比如:
|
|
答:这里面大写的是类,小写的是对象。
5. 我还是比较认同,从左往右匹配的规则,这样就像老师讲的可以在构建 DOM 树的同时来进行匹配 CSS 规则,相当于同时构建渲染树了,而不必等到 DOM 构建完毕再进行 CSS 的规则匹配。
进行构建渲染树,虽然从右向左匹配对于复杂的选择器更优,但是这里面浪费了等待 DOM 构建完毕,才能使用的 CSS 匹配规则。而且相对于同为 id 等单一选择器而言,明显从左向右更具有优势!这是我的一点想法,望老师指正!
答:其实我在之前的分享中做过一个试验,当时的 Chrome 确实是从右往左,如果 #id 在最左,速度会更快,但是那个过程是后添加 CSS 的情况。
6. 程老师你好。我在很多地方看到的说法是:CSS 会阻塞 DOM 渲染,但不会阻塞 DOM 的解析,且 CSS 文件的请求是异步请求。
那么如果按照您所说,DOM 的构建和 CSS 属性的计算是同步的话,head 中 CSS 文件的下载以及 CSSOM 的 rule 部分的构建,应该会阻塞 HTML 的解析和 DOM 的构建。好像这两种说法之间就有了冲突。麻烦程老师有空的时候可以帮忙解释一下,万分感谢。
答:其实你误解了我的意思,DOM 构建的结果到 CSS 属性计算是个流水线,所以 CSS 会阻塞 CSS 计算,不会阻塞 DOM 构建。
7. 老师,我记得有的书上或者是资料上说超过五次的 if else 就最好用 switch case 来替换。这样效率更好。您这里为什么说不用这个呢?
答:我在性能部分讲了,“凡是不做 profiling 的性能优化都是耍流氓”。
具体的话,你可以看一看“43 | 性能:前端的性能到底对业务数据有多大的影响”这一篇。
8. 函数调用和函数执行有什么区别?有没有相应的标准?
答:我们一般讲“A 函数调用了 B 函数”“浏览器执行了 B 函数”,所以你看,两者的区别是主语不同,你可以感受一下区别。它们对应的标准都是 ECMA262。
9. 请问下老师,为什么 flexible 布局方案不再维护了呢?这个方案本身存在问题吗?
答:不存在问题,但是 rem 计算是个历史方案,现在,我比较推荐大家使用 vw。
10. 有的工业软件,3D 建模的也可以用浏览器来实现了,用的是 ThreeJS WebGL,老师了解这些嘛?怎么看待这个发展前景。
答:挺好的,但是我觉得这件事由本来做 3D 的工程师转型更方便。
11. 最近出于好奇,我 clone 了 github 上 chrome 的源码仓库,发现竟然有 12G 多,貌似比 linux 内核的源码还多。个人特别想探索一下浏览器源码,但面对如此庞大的代码,不禁望而生畏,也不知从何下手。
请问老师,浏览器内核源码该如何去研究,skia 渲染引擎是最先进吗,svg,canvas,WebGL 该如何选择,怎样深入地学习和掌握它们呢?望老师拨冗答疑,谢谢!
答:你先编译通过吧,然后试着跑起来打断点这样子,其实这件事没有捷径,多花些时间就可以。
skia 引擎是不是最先进,这事我也不好说,其实在工程领域我们一般不追求“最先进”,我们只需要它“足够先进”。
关于如何选择,我收到了很多问题,不过我其实都不做回答,毕竟我没法替你决定你自己的职业发展道路,这个责任实在是有些重大了。
12. 看完老师列出的表格更迷茫了,比如,为什么 transform 属于 level 1,transform 不是 CSS3 里的属性么?level4 是什么?是 CSS4 么?为什么 color 这种常用属性属于 level4? 不应该属于 level1 么?好迷茫哦。
答:我先解释一下你的问题,一方面,level4 里有不等于 level3 里没有,另一个是,W3C 定 level 并不是十分严谨,有从 1 开始,也有从 3 开始的。
除此之外,我想提醒一下,这个表格并不是给你去看 level 的,而是告诉你标准在哪里,让你去读标准的。
13. 请问老师,我后台用的是 Tomcat 服务器,前端用 ajax 请求静态资源时会间隔会报 412,也就是一次成功进入后台,一次报 412,这该怎么解决呢?
答:理论上 412 意思是你浏览器的问题。从你提供的信息我没法给你解决方案,建议你可以搞一个最小复现环境去 Tomcat 社区问。
14. 老师好,有个疑问:WHATWG 和 W3C 标准以哪个为准,这两个标准有什么区别?是不是相互不认可的。
答:这个问题比较复杂,WHATWG 最初是几家不满 W3C,出走搞出来的,后来被招安了把 HTML5 带回了 W3C,不过两边出标准的思路还是不太一样,WHATWG 是 living standard,就是随时更新标准,没有版本的概念,我是个人会倾向于 WHATWG 版本,因为比较新,而且 Chrome 跟得比较紧。
15. winter 老师好,可以给我讲一下那个 presentational attributes,有些看不懂。
|
|
我知道函数中的 this 是由调用函数的对象决定的,但这种理解总感觉是由结论推原因;老师能不能讲解下。
答:this 是由调用函数的对象决定,这完全是个规定,没有什么原因。(你后面的问题我节选掉了,我其实没太理解到你想表述的意思,你看到了可以再给我留言)。
16. 喜欢使用 let 和 const,看很多库里面,他们都喜欢使用 const,并且推荐使用 const,比如声明一个数组。
老师能讲解下声明一个数组用 let 和 const 有什么区别吗?在操作数组时,都是往数组中 push 值,原先的变量并物理地址并没有发生变化,如果用 let,和用 const 有什么区别,为什么 const 的性能会好一点?
答:性能好一些完全是乱说的,用 const 的话,可以避免你误把数组整个赋值掉,比较有安全感吧。
- 老师我有几个问题希望你回答:
老师讲到:“注意,我们这里讲的渲染过程,是不会把子元素绘制到渲染的位图上的,这样,当父子元素的相对位置发生变化时,可以保证渲染的结果能够最大程度被缓存,减少重新渲染。”
- 缓存的是什么东西,位图吗?如何减少重新渲染的?
- 是不是所有的元素都有对应的位图?
文中你举了两个例子,说如果只有一个位图,任何改变都会引起所有重新渲染。这个好理解,一个大位图就是一个单元,任何的改动相当于这个单元被变了,所以要重新创建这个,这样理解对吗?
但是你下面又说如果不合并,每次还是所有的重新渲染。感觉说的很矛盾啊。希望老师能回答一下我的疑问。
答:缓存的是位图,父子元素位置变化时,因为子元素的位图被缓存,子元素不需要重新渲染,因为父元素的位图也被缓存,父元素也不需要重新渲染,只有父子元素合成起来的位图需要被渲染。
你这样理解是对的,如果不合并,每次改点什么东西,都要重新逐级合成最终的大位图,也相当于重新渲染。
18. 老师,“当没有强制指定文字书写方向时,在左到右文字中插入右到左向文字,会形成一个双向文字盒,反之亦然。”这个能不能给个例子,不明白什么意思。
答:比如你在中文中插入几个阿拉伯语字符,阿拉伯语字符就会形成一个双向文字盒。
19. 看了您的流式数据的解释,是不是可以理解当看到页面渲染的时候,DOM 是不是有可能都还没构建完成呢?即使是理论上,有这种可能吗?
答:渲染不但发生在 DOM 构建之前,甚至可能发生在你下载网页完成之前,比如你上个 XX 软件下载站,是不是下载链接还没见到,就看到广告了(你提到的网上的那段是别人写错了。我节选掉了)。
20. footer 也可以和 aside,nav,section 相关联 (header 不存在关联问题),不存在关联问题是什么意思啊,不应该在 header 中使用吗?下面又说 header 中可以使用 nav,老师的“关联”是什么意思啊?
答:因为 footer 有自己的语义,footer 必须要指明是谁的 footer,这样 footer 中的作者、地址才有意义,所谓的关联就是这个意思了。
21. 子元素的事件委托给父元素时,添加事件监听的第三个参数直接设置为 true,在捕获过程就判断父元素上的事件目标会比冒泡好些嘛?
答:对,但是你需要在捕获阶段想办法知道事件具体发生在哪个子元素上。
22. 老师 如果我想更深入的了解移动端的兼容问题,有没有好的学习路线呢?
答:兼容问题不是学出来的,你想在山中苦修,自出洞来无敌手?手机早就更新好几代了。所以兼容问题必须靠实践,在一个需要兼容性的业务上,不断积累和更新兼容性知识。
23. 老师,我在理解 SICP 这本书的过程抽象和数据抽象的时候,代入到前端,比如生命周期、事件处理等更多是过程的抽象,能提出一些公用的过程,而数据抽象更多指的是组件内的数据定义、api 的设计、高阶组件等。
请问我这样理解对吗?或者说老师对过程抽象和数据抽象在前端中怎么理解的?如果理解得不对,有什么好的书或者文章帮助理解?
答:SICP 讲的是很实在的编程技巧,在前端中对应的是变量、循环、条件这些东西,SICP 是一本好书,你应该更认真地去阅读它。
24. 通过这个课程老师对于前端的划分为 JavaScript、HTML 和 CSS、浏览器、工程实践几个部分。
- 疑问 1:现在前端基本把 Node 也包括进来了,对于 Node 的知识应该怎么定位?
- 疑问 2:Node 属于后端的范畴了,是否应该去学习下 java 相关的后端体系?学习了后端的体系是否会反过来促进前端知识的学习呢。
winter 老师对这两个问题怎么看呢?谢谢。
答:Node 属于后端,electron 属于客户端,不论你学哪个体系,肯定对前端都有促进作用。
但是,你不能认为懂了 Node 就懂了后端,懂了 electron 就懂了客户端,每个领域都可以很深入,知识本来就是学不完的,你能掌握多少只跟投入的时间有关,这道理是很简单的,与其困惑,不如把困惑的时间拿来学习,相信你会有所收获的。
25. 老师,CSS 是如何依附在 DOM 树上的?是通过前面讲得 Node 实例来实现的?
答:在 Node 实例上添加属性,我在“12 | 浏览器:一个浏览器是如何工作的(阶段三)”讲到了,你可以返回去看看。
26. 清楚为什么要使用语义化标签,是否有必要使用之前,很难让自己有动机去应用每个标签。另外标签新推出如何保持实时掌握最新的标签呢,如何解决浏览器兼容的问题?
答:对语义化标签,我是建议不必追求全部掌握,现有需求再找标签即可。
27. 老师您好,有个疑问想请教一下,为啥基于对象关联风格的面向对象并不是像模拟类的行为的面向对象那么流行呢?原型委托这种的不是应该更符合 JavaScript 语言本身的设计嘛?类似这种:
|
|
答:大部分人在学校学的都是 C++ 和 Java,我就没见过教原型的,这是现实,没办法。
28. 老师,可否稍加解释一下执行上下文的分类?网络上的文章说“JavaScript 中可执行的代码可分为三种类型:全局代码、函数代码、eval 代码,对应三种执行上下文(全局执行上下文、函数执行上下文、eval 执行上下文)。
在 ECMAScript 2018 中没有找到这种说法的依据。我的意思是,我不太清楚这些文章的说法是否正确,是否不够全面。
答:这个说法倒不能说不正确,但是严重过时了。
现在 ECMAScript 2018 里面执行上下文非常复杂,你可以看看各种 Record,重学前端课程里面也没有讲全。
29. 老师,在 ES5 之前版本规范中,会提及 JavaScript 的可执行代码分为全局、函数、Eval。但是在 ES6 之后版本规范中,再也不提及可执行代码的概念了,这是为什么呢?
答:其实这里是重构了一下表达方式,新加入了模块什么的。
30. 试过好多次,找了很多方法 flex 兼容 IE9 以下,每次都失败,有什么好的解决办法吗?
答:如果真有 IE9 兼容需求,我想只能单独写一份 CSS 了。
31. 请问大佬,如何冻结对象,一般什么样的场景可以用到?
答:Object.freeze 函数可以冻结对象。一般都是写底层库,希望避免篡改。
32.
|
|
两者到底有什么区别,想不明白,求教。
答:这个区别不大的,第二种写法一般都是为了给 resolve 传参数,不过如果你不想给 resolve 传特定参数,为什么还要多写一个函数呢。
33. 我听 JavaScript 像听天书,怎么办,是不是要从 0 重新学起呀?
答:理论上,我的课程是把 JavaScript 的内容重新组织了一下,如果平时就在用 JavaScript,我认为问题不大。如果这部分完全听不懂,可能说明确实基础薄弱,建议你从 0 学起。
好了,本期的答疑告一段落,如果你还有其他的问题,或者还是没有弄清楚,你可以继续给我留言,我会继续解答大家的问题,并一起讨论。
文章作者 anonymous
上次更新 2024-01-09