Fork me on GitHub

【interview questions about Web】

Web方面的知识盲区补漏。

匹配URL的正则表达式

URL由三部分组成:资源类型(协议)、存放资源的主机域名、资源文件名。
URL的一般语法格式为(带方括号[ ]的为可选项):
protocol :// hostname[:port] / path / [;parameters][?query]#fragment
据说比较好用匹配较全面的是这个:
(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]
参考自博客正确匹配URL的正则表达式匹配URL的正则表达式解析

React虚拟DOM的优势,为什么虚拟DOM操作比原生方式快

将数据的变化实时反映到UI上,这时需要对DOM进行操作,但复杂或频繁的DOM操作(会造成重排、重绘)通常是性能瓶颈产生的原因,为此,React引入了虚拟DOM(Virtual DOM)的机制。

虚拟DOM?
在React中,render执行的结果得到的并不是真正的DOM节点,结果仅仅是轻量级的JavaScript对象,称之为virtual DOM。(是不是跟文档片段有异曲同工之妙?dom中的文档碎片)

虚拟DOM是React的一大亮点,具有batching(批处理)和高效的Diff算法 (深入浅出React(四):虚拟DOM Diff算法解析)。这让我们可以无需担心性能问题而”毫无顾忌”的随时“刷新”整个页面,由虚拟 DOM来确保只对界面上真正变化的部分进行实际的DOM操作。

虚拟DOM对比原生操作DOM
原生操作DOM方式,使用 innerHTML。在一个大型列表所有数据都变了的情况下,还算是合理,但当只有一行数据发生变化时,它也需要重置整个 innerHTML,这时候显然就造成了大量浪费。
innerHTML: render html string + 重新创建所有 DOM 元素
Virtual DOM: render Virtual DOM + diff + 必要的 DOM 更新
和 DOM 操作比起来,js 计算是非常便宜的。Virtual DOM render + diff 显然比渲染 html 字符串要慢,但是,它依然是纯 js 层面的计算,比起后面的 DOM 操作来说,依然便宜了太多。

存疑
React虚拟DOM的工作机制还不太理解,深入学习以后需要再回顾。
React虚拟DOM浅析
React 的 diff 算法
为什么 React 的 virtual DOM 比原生的DOM 渲染性能更好?

RESTful

REST(Representational State Transfer),“表述性状态转移”,是一种网络应用架构规范,目标是构建可扩展的web service。
REST规范可以提高架构的性能和可维护性。REST是一种更简单的SOAP协议及以WSDL为基础的web service的替代。(SOAP暴露接口,REST暴露资源)
参考博客WebService两种发布协议–SOAP和REST的区别
RESTful(采用REST架构规范的)系统通常是通过HTTP协议,并且使用HTTP的GET,POST,PUT,DELETE等动词来收发数据。
W3C TAG开发了REST架构,基于HTTP 1.0。万维网代表了最大的REST架构实现,你可以认为所有的网页服务器都是采用REST架构的RESTful系统。
目前在三种主流的Web服务实现方案中,因为REST模式的Web服务与复杂的SOAP和XML-RPC对比来讲明显的更加简洁,越来越多的web服务开始采用REST风格设计和实现。
常见的三种Web服务架构

WebView相关

先了解什么是Hybrid APP。所谓Hybrid,即混合开发,意味着半原生半Web,其实在H5兴盛之前,Hybrid模式就已经比较成熟了,但是一直不愠不火(因为系统的一些现在以及html本身功能的限制)。
怎么样的开发模式才算是Hybrid模式呢:

  • Hybrid是半Native半web开发模式
    Hybrid模式中,底层功能API均由原生容器通过某种方式提供,然后业务逻辑由H5页面完成,最终原生容器加载H5页面,完成整个App
  • 成熟的Hybrid模式意味着业务逻辑均由H5实现
    一款成熟的Hybrid框架,意味着各种类型的api都很完善,那么这时候几乎所有与业务相关的逻辑都是放在H5页面中的,原生只作为容器存在
  • 成熟的Hybrid模式可复用性非常高,可以跨平台开发
    成熟的Hybrid框架,那么原生只会提供底层API,也就是说所有的业务是H5完成,不管是什么项目,业务只由H5实现,这时候就可以发现,业务代码是可以跨平台的,也就是说,开发一次,就可以和各自原生容器结合,组成两种原生安装包了,达到了跨平台开发效果

APP三种开发模式–之–HybridApp解决方案

原生APP开发中有一个webview的组件(Android中是webview,iOS7以下有UIWebview,7以上有WKWebview),这个组件可以加载Html文件。
在Html5没有兴盛之前,加载的Html往往只能用来做一些简单的静态资源显示,但是H5大行其道以后,Html5中有很多新增的功能,炫酷的效果,特别是iOS中H5支持一直都很良好,Android 4.4以上支持也足够,所以这时候发现可以将一些主要的逻辑都用H5页面来编写,然后原生直接用webview加载显示,这样大大提高了开发效率,而且体验也很不错。
webview用来展示网页的view组件,该组件是你运行自己的浏览器或者在你的线程中展示线上内容的基础。使用webkit渲染引擎来展示,并且支持前进后退等基于浏览历史,放大缩小,等更多功能。
简单来说WebView是手机中内置了一款高性能 webkit 内核浏览器,在 SDK 中封装的一个组件。不给过没有提供地址栏和导航栏,只是单纯的展示一个网页界面。
参考文章前端解读WebviewWebView JavascriptBridge机制解析JS交互与WebView的工作原理浅析

软件开发模式之“快速迭代”开发

几种常见的软件开发模式对比参考博客软件开发模式对比(瀑布、迭代、螺旋、敏捷)
迭代成本比较低,一般采用敏捷开发的模式,产品快速的推动上线,上线后会通过用户反馈和用户行为分析不断的进行产品改进,并且每次改进的周期比较短,如果把“快速迭代”理解为快速并持续的更新和改进产品。

敏捷开发-快速迭代

线程和进程的区别

线程和进程的区别是什么?–知乎
进程和线程都是一个时间段的描述,是CPU工作时间段的描述,不过是颗粒大小不同。
进程就是包换上下文切换的程序执行时间总和 = CPU加载上下文+CPU执行+CPU保存上下文。
线程是共享了进程的上下文环境的更为细小的CPU时间段。
进程和线程的区别
进程与线程的一个简单解释–阮一峰

浅谈js运行机制(线程)
js运作在浏览器中,是单线程的,即js代码始终在一个线程上执行,这个线程称为js引擎线程。
浏览器是多线程的,除了js引擎线程,它还有:

 UI渲染线程
浏览器事件触发线程
http请求线程
EventLoop轮询的处理线程
....

单线程的含义是js只能在一个线程上运行,也就说,js同时只能执行一个js任务,其它的任务则会排队等待执行。
js是单线程的,并不代表js引擎线程只有一个。js引擎有多个线程,一个主线程,其它的后台配合主线程。
多线程之间会共享运行资源,浏览器端的js会操作dom,多个线程必然会带来同步的问题,所有js核心选择了单线程来避免处理这个麻烦。js可以操作dom,影响渲染,所以js引擎线程和UI线程是互斥的。这也就解释了js执行时会阻塞页面的渲染。

JavaScript 运行机制详解:再谈Event Loop–阮一峰
Javascript异步编程的4种方法–阮一峰
关于javascript的单线程和异步的一些问题
Node.js的线程和进程

图片加载完成之前获取图片高度

JS快速获取图片宽高的方法

参考自博客图片加载完成之前获取图片高度

原理:利用的就是浏览器加载图片时的一个策略:当图片头部信息加载完成后,浏览器即获知了图片的大小,然后就会在页面上空出相应的区域来,然后再下载图片的剩余数据并且显示到之前空出的区域中。
所以我们要做的就是不断的去问浏览器你得到高度信息了没有,问到之后就可以马上做相应的处理,而此时图片还没有下载完成。

补充:js图片img的onload事件与complete属性之间的关系,onload是图片加载完成执行的事件,complete属性是图片显示出来以后为true,那么在onload之前complete肯定是false的,那么我们就可以在onload事件内部判断complete属性是否为true。如果为true那么代表图片真正的加载成功,否则可以重新加载。

img加载完成就会触发onload事件,src是异步加载图片的,如果在绑定事件前就已经加载完成,onload事件不会触发。img.complete是一直都有的属性,加载完成后为true。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
var imgReady = (function () {
var list = [],
intervalId = null,
// 用来执行队列
tick = function () {
var i = 0;
for (; i < list.length; i++) {
list[i].end ? list.splice(i--, 1) : list[i]();
};
!list.length && stop();
},
// 停止所有定时器队列
stop = function () {
clearInterval(intervalId);
intervalId = null;
};
return function (url, ready, load, error) {
var onready, width, height, newWidth, newHeight,
img = new Image();
img.src = url;
// 如果图片被缓存,则直接返回缓存数据
if (img.complete) {
ready.call(img);
load && load.call(img);
return;
};
width = img.width;
height = img.height;
// 加载错误后的事件
img.onerror = function () {
error && error.call(img);
onready.end = true;
img = img.onload = img.onerror = null;
};
// 图片尺寸就绪
onready = function () {
newWidth = img.width;
newHeight = img.height;
if (newWidth !== width || newHeight !== height ||
// 如果图片已经在其他地方加载可使用面积检测
newWidth * newHeight > 1024
) {
ready.call(img);
onready.end = true;
};
};
onready();
// 完全加载完毕的事件
img.onload = function () {
// onload在定时器时间差范围内可能比onready快
// 这里进行检查并保证onready优先执行
!onready.end && onready();
load && load.call(img);
// IE gif动画会循环执行onload,置空onload即可
img = img.onload = img.onerror = null;
};
// 加入队列中定期执行
if (!onready.end) {
list.push(onready);
// 无论何时只允许出现一个定时器,减少浏览器性能损耗
if (intervalId === null) intervalId = setInterval(tick, 40);
};
};
})();

代码取自腾讯图片详情页。这种做法仅适用于 img 元素的 src 属性是一个 URL 的情况,如果是 Data URI 则不能这么做,因为浏览器是另外一套处理逻辑了。

图片预加载与懒加载

基于用户行为的图片等资源预加载–张鑫旭

预加载和懒加载的区别,懒加载当用户触发到某块内容区后才去加载,预加载是用户行为还没发生,资源已经加载完毕。

实现图片预加载的三大方法

-------------本文结束感谢您的阅读-------------
坚持原创,您的支持将鼓励我继续创作!