前端基础(浏览器引擎/HTTP/目录/异步、延迟、承诺/文件API/事件/加载、渲染、绘制/编码、转码、转义/进程与线程/正则表达式)

浏览器引擎

浏览器引擎包括排版引擎浏览器内核渲染引擎)和JS引擎JS解析器

一、Trident (IE内核)

         许多壳浏览器都采用Trident内核,其中部分浏览器的新版本是“双核”甚至是“多核”,其中一个内核是Trident,然后再增加一个其他内核。国内的厂商一般把其他内核叫做“高速浏览模式”,而Trident则是“兼容浏览模式”,用户可以来回切换。

        IE的JS引擎先后是JScript 、Chakra。

二、Gecko(Firefox内核,开源)

       Netscape浏览器Netscape公司已经停止的项目,Netscape公司被美国在线收购后,已经解散。Mozilla基金会是Netscape公司成立的一个组织,支持和领导开源的Mozilla项目,Firefox浏览器是这个项目中的一个部分。

      Firefox的JS引擎先后是SpiderMonkey、TraceMonkey、JaegerMonkey。

三、WebCore(Safari内核,开源)

       WebCore是苹果的Safari浏览器使用的排版引擎。

       Safari的JS引擎先后是JavaScriptCore、Nitro。WebCore和JavaScriptCore是Webkit浏览器引擎的两个组件,均是从KDE的KHTML及KJS引擎衍生而来,它们都是自由软件。

四、Blink(Chrome引擎,开源)

        Blink是Google开发的WebCore的分支。

        Chrome的JS引擎是V8。

HTTP

一、请求

1、请求行 GET   www.baidu.com/index.html   HTTP/1.1 (Method Request-URI HTTP-Version)

请求方法GET、POST、HEAD、PUT、DELETE,语义不同,表现不同。

2、请求头

Cache(缓存)

If-Modified-Since:Wed, 11 Feb 2015 04:12:02 GMT   值为该请求上一次响应的得到的Last-Modified,服务器段据此判断文件是否改变过,没改变则返回304
If-None-Match:W/"2275-1423627922000"                  值为该请求上一次响应的得到的ETag,服务器收到If-None-Match后,对比新计算的tag,判断是否返回304

Client(客户端信息)
Accept:*/*          接受何种MIME类型(文档类型,格式为:类/子类)的响应
Accept-Encoding:gzip,deflate,sdch   接受何种压缩编码的响应
Accept-Language:en-US,en;q=0.8   浏览器支持的语言
User-Agent: AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.72 浏览器版本、内核
X-Requested-With:XMLHttpRequest  标明是ajax异步请求
Cookie:locale=zh_CN; language=zh_CN; Secure=true; HttpOnly=true; JSESSIONID=E3C4995099A245125E1E8D4C766891B2
Entity(实体)
Content-Length:73                 请求体长度  
Content-Type:application/json; charset=UTF-8  请求体的MIME类型,表单提交的Content-Type通常是application/x-www-form-urlencoded或multipart/form-data(有附件上传)
Miscellaneous(杂项)
Origin:https://www.sina.com              请求来源,只在POST请求中有
Referer:https://www.sina.com/index.html  请求详细来源
还有一些自定义的信息,如token
Transport(传输)
Connection:keep-alive   保持TCP链接,多个http请求,使用同一个TCP链接。close表示不保持
Host:https://www.baidu.com  请求目标域名
3、请求体

                                                                                                          二、响应
1、状态行 HTTP/1.1 200 OK (HTTP-Version Status-Code Reason-Phrase)
状态码
1xx:指示信息--表示请求已接收,继续处理
2xx:成功--表示请求已被成功接收、理解、接受
3xx:重定向--要完成请求必须进行更进一步的操作
4xx:客户端错误--请求有语法错误或请求无法实现
5xx:服务器端错误--服务器未能实现合法的请求
常见状态代码、状态描述、说明:
200 OK //客户端请求成功

302 Moved Temporarily // 重定向,响应头里会有 Location,即重定向目标;在CDN 302调度中,CDN调度器会返回302指向一个CDN接入节点
304 Not Modified //响应体为空,客户端使用缓存
400 Bad Request //客户端请求有语法错误,不能被服务器所理解
401 Unauthorized //请求未经授权
403 Forbidden //服务器收到请求,但是拒绝提供服务
404 Not Found //请求资源不存在
500 Internal Server Error //服务器发生不可预期的错误
503 Server Unavailable //服务器当前不能处理客户端的请求,一段时间后可能恢复正常

2、响应头
Cache(缓存)
Date:Tue, 17 Feb 2015 03:57:40 GMT 响应时间
Vary:Accept-Charset, Accept-Encoding, Accept-Language, Accept 指明该响应依据请求的哪些字段产生,因此如果下一次的请求有个字段的值不同,就不会使用该响应作为缓存
Expires:Tue, 24 Feb 2015 05:04:40 GMT 缓存有效期
Cache-Control:max-age=604800 缓存时长(秒),优先级高于Expires
Set-Cookie: UserID=JohnDoe; Max-Age=3600 httpOnly;    每条cookie除了key-value,还有各自的域、寿命、httpOnly、secure等属性。
Entity(实体)
Content-Length:3237 响应体长度
Content-Type:application/json;charset=UTF-8 响应体MIME类型
ETag:W/"22667-1423627922000" 文件标识符
Last-Modified:Wed, 11 Feb 2015 04:12:02 GMT 返回的文件的最后修改时间
Miscellaneous(杂项)
Server:apache 服务器名称
Accept-Ranges:bytes 支持断点续传的粒度
X-Download-Options:noopen 禁止浏览器打开下载的文件
Security(安全)
X-Content-Type-Options:nosniff 禁止浏览器自动判断文档类型
X-Frame-Options:SAMEORIGIN 禁止响应被其他网站frame
X-XSS-Protection:1; mode=block 开启xss防护并通知浏览器阻止而不是过滤用户注入的脚本。0 – 关闭xss防护 1 – 开启xss防护

Access-Control-Allow-Origin:http://www.test.com 允许来自www.test.com的跨域请求

Access-Control-Allow-Credentials:true 允许跨域请求时带cookie

Transport(传输)
Connection:keep-alive

Location: xxxx 跳转目标
3、响应体

                                                                                                                三、现象
1、浏览器是否使用缓存:
(1)、看缓存是否存在,存在则到第2步,不存在则到第3步。
(2)、看缓存是否过期(Expires、Cache-Control),不过期则使用缓存。无Expires、Cache-Control默认为过期,过期则到第3步。
(3)、发送请求,带上If-Modified-Since、If-None-Match,服务器判断资源是否发生变化,无变化,返回304,浏览器使用缓存。无If-Modified-Since、If-None-Match默认为变化,返回200,不使用缓存。

2、跳转或地址栏回车刷新与浏览器左上角刷新不一样

四、版本

HTTP 0.9,只有基本的文本 GET 功能。
HTTP 1.0,完善的请求/响应模型,并将协议补充完整。1996年发布
HTTP 1.1,在 1.0 基础上进行更新,增加了如 长久连接 keep-alive 与 chunked 等功能。1999 年发布
HTTP 2.0 语义与 1.1 兼容
1、多路复用流:多个请求或响应被拆分,在同一个连接上传输,到达目的地后再重新组装。资源合并、域名分区变得不重要。
2、优先权和依赖:客户端发出的请求带有 优先权和依赖 的信息
3、头部压缩:多个请求的头部 很多重复,可以进行压缩
4、服务器端推

默认连接方式
HTTP1.1下Connection: Keep-Alive
HTTP1.0下Connection: Close

五、安全策略

内容安全策略(Content Security Policy,CSP)
   在 HTTP 响应头里设置 CSP
Content Security Policy: default-src 'self'  // 所有资源 只能 来自 本域名
Content Security Policy: font-src 'a.com'  // webFont 只能 来自 a.com
Content Security Policy: content-src 'https:'  // ajax、websocket 只能通过https
还可以设置 style-src 、img-src、script-src、media-src、frame-src等

目录

传统浏览器处理依赖的文件路径算法如下:

如果依赖是相对路径, 那么该依赖是以当前文件作为参考路径的

build/src/index.html
<img  src="./theme/default/images/home/user_status_gd.png">
那么user_status_gd.png的路径为:build/src/theme/default/images/home/user_status_gd.png

如果依赖是绝对路径,那么该依赖路径为

build/src/index.html
<img  src="/theme/default/images/home/user_status_gd.png">
那么user_status_gd.png的路径为:contextname/theme/default/images/home/user_status_gd.png

如果直接以目录开始,那么该依赖的路径为

build/src/index.html
<img  src="theme/default/images/home/user_status_gd.png">
那么user_status_gd.png的路径为:build/theme/default/images/home/user_status_gd.png

异步、延迟、承诺

延迟模块的API遵循 promise 规范

$.Deferred()

$.Deferred()返回一个deferred(延迟)对象
var deffered = jQuery.Deferred();

给deffered添加延迟处理函数(承诺),可以链式调用
deferred.done()    解决
deferred.fail()    拒绝
deferred.always()  结束(解决或拒绝)
deferred.progress()进度变化
deferred.then()    结束或进度变化
延迟判决
deferred.notify()、deferred.notifyWith(args)  延迟进度通知,回调progress、then
deferred.reject()、deferred.rejectWith(args)  延迟被拒绝,回调fial、always、then
deferred.resolve()、deferred.resolveWith(args)延迟解决,回调done、always、then

同时处理多个deffered,$.when(deffered1,deffered2).then(function(){});

var promise = deferred.promise();返回承诺对象
promise可像deffered一样添加承诺(延迟处理函数)

$.ajax()

$.ajax() 发出请求并返回一个jqXHR对象,它是一个deferred对象,和XHR对象一样拥有 readyState、responseText、status、statusText等属性。
var jqXHR = $.ajax({});

给jqXHR 添加回调函数,可以链式调用
jqXHR .done() :请求成功回调,取代了 jqXHR .success        
jqXHR .always():请求结束回调,取代了jqXHR .complete
jqXHR .fail() :请求失败回调,取代了jqXHR .error
jqXHR同样拥有progress()、then()、promise()
同时处理多个jqXHR对象,$.when(jqXHR1 , jqXHR2).done(function(){})

$q.defer()


angularjs的$q.defer()返回一个延迟对象
var deferred = $q.defer();

延迟判决
  deferred.notify(args)  延迟进度通知
  deferred.resolve(args) 延迟解决
  deferred.reject(args)  延迟被拒绝
  
  var promise = deferred.promise;承诺对象
  添加承诺(延迟处理函数)
  promise.then(successCallback, errorCallback, notifyCallback)  按顺序添加承诺
  promise.catch(errorCallback)  拒绝
  promise.finally(callback)     始终(解决、拒绝、进展)

文件API

 参考 https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader

获取文件

1、从表单中读取

var file = document.getElementById("uploadImage").files[0];

2、本地拖入(见文章【HTML5 拖放】)

function drop(event)
{
    event.preventDefault();
    var file = event.dataTransfer.files[0];
}

3、从网络获取

// XMLHttpRequest 下载
var blob = new Blob([xhr.response], {type: 'image/png'});
// fetch 下载
let res = await fetch();
let blob = await res.blob();
// axios 下载
axios({
    method: 'get',
    responseType: 'blob',
});

使用文件

// FileReader 为 HTML5新增对象
var fileReader = new FileReader();

1、预览图片

// 读取后生成URL
fileReader.readAsDataURL(file);
// 读取完毕事件
fileReader.onload = function (fileEvent) {
  // 预览图片
  document.getElementById("uploadPreview").src = fileEvent.target.result;
};

2、上传(见文章【上传下载】)

let data = new FormData();
data.append("file", file);

let xhr = new XMLHttpRequest();
xhr.open('POST', 'http://**');
xhr.send(data);
xhr.onload = (request)=>{
    console.log(request.target.response);
};

// 使用 axios
axios({
    method: "post",
    url: 'http://**',
    data: form
}).then((response) => {});

3、读取文本

//读取文本
fileReader.readAsText(file);
//读取完毕事件
fileReader.onload = function (fileEvent) {
  console.log(fileEvent.target.result);
};

4、下载到本地

var link = `<a href="data:text/csv;charset=utf-8,${content}" download="export.csv">download</a>`;
document.write(link);
URL.createObjectURL(blob);
window.open(blob)

事件

事件模型与事件委托

 事件模型:捕获模型,冒泡模型;IE8以及之前不支持捕获模型
 先捕获阶段,再冒泡阶段;addEventListener(“事件名”,方法名,事件模型 );第三个参数为true即在事件的捕获阶段执行


事件处理函数为先添加先执行,event.stopPropagation(); 停止冒泡,return false; 停止后续的所有响应


 事件委托
 意义:不用每个元素都去绑定事件,优化性能;新增元素不用单独绑定事件
 
 JS事件委托
 给父元素绑定事件,在事件处理函数中,判断e.target是哪个元素
 
 jQuery事件委托
 live 把td的事件委托到#info_table,第二个参数默认是document
 $("td",$("#info_table")).live("click",function(){});
 delegate实现同样的功能,优化于live
 $("#info_table").delegate("td","click",function(){});
 on实现同样的功能
 $("#info_table").on("click","td",function(){});

组件自定义事件

var widget = {
    _listener : {
    "click": [func1, func2],
    "change": [func3]
    },
    addEvent : function(type, fn) {
    // 添加
    },
    fireEvent : function(type) {
    // 触发
    },
    removeEvent : function(type, fn) {
    // 删除
    }
}

出错事件

window.addEventListener('error', function (e) { // 用于全局统一处理出错
   var error = e.error;
   console.log(error);  

});

高频事件

scroll、resize、mouseover

防抖 underscore.debounce

var debounce = function(fn, delay){ // 将参数delay结合到原函数fn,得到一个新函数,这个过程称为柯里化

    var timer; // 闭包变量

    return function(){

        // 将类数组对象转化为数组

        var args = [].slice.call(arguments);

        // 事件处理函数的this指向事件主体

        var context = this;

        // 重设定时器

        clearTimeout(timer);

        timer = setTimeout(_fn, delay);

        function _fn(){

            fn.applay(context, _args);

        }

    }

}

window.addEventListener("scroll", debounce(function(){// 事件处理函数}, 1000))

节流 underscore.throttle

目的:解决 debounce 可能导致多次事件触发都不会执行事件处理函数

方案:在 debounce 的基础上,如果这次事件距离上次处理的时间差大于一定值,则清除上个定时器,并马上执行处理函数,否 则设置定时器

请求动画帧 requestAnimationFrame

var rafThrottle = function(fn){

    var isLocked;

    return function(){

        var _args = arguments;

        var context = this;

        if(isLocked) return;

        isLocked = true;

        requestAnimationFrame(function(){

            isLocked = false;

            fn.apply(context, _args);

        });

    }

}

加载,渲染,绘制

浏览器加载过程

(1)、浏览器通过DNS获取域名对应IP
(2)、建立TCP连接
(3)、发送http请求
(4)、html边下载边渲染
(5)、碰到内嵌JS 和 CSS,启动新的连接下载,阻塞渲染和JS执行(因此要把脚本放后面)
(6)、获取到CSS后,重新渲染
(7)、JS按标签顺序下载并执行
(8)、碰到内嵌img,启动新的连接下载,不会阻塞渲染

(9)、获取到img后,重新渲染

DNS: (1)客户机向本地域名服务器dns.company.com发出解析域名www.linejet.com的请求报文。 (2)本地域名服务器查询本地缓存, 假设没有该纪录, 则向根域名服务器NS.INTER.NET发出请求。  (3)根域名服务器查询本地记录得到如下结果:linejet.com NS dns.linejet.com (表示linejet.com域中的域名服务器为dns.linejet.com)

渲染
1、HTML代码转化成DOM
2、CSS代码转化成CSSOM(CSS Object Model)
3、cascade级联DOM和CSSOM,生成一棵渲染树(包含每个节点的视觉信息)
4、生成布局(layout),即将所有渲染树的所有节点进行平面合成
5、将布局绘制(paint)在屏幕上


页面发生变化时,要重新渲染reflow(重新生成布局并绘制)。有元素位置发生变化或滚动时,需要重排并重绘。元素位置都没发生变化时,只需重绘repain。
浏览器会将几个连续的改变累积起来,再一次重新渲染,以减少重新渲染的次数。
脚本读取位置,尺寸等信息时,浏览器不得不把之前累积的变化,重新渲染一次,再返回最新的位置和尺寸。


优化    
1、读取位置和尺寸的脚本最好放在一起,不要与改变页面的脚本穿插
2、缓存位置和尺寸信息, 不要重复读取        
3、对离线DOM 操作完后,再加入DOM树。不用加入后再操作。
4、对DOM的复杂改变,可以先隐藏,再操作,再显示
5、position属性为absolute或fixed的元素重排开销较小,动画最好设置在它们身上       
6、window.requestAnimationFrame(function(){写操作}) ,把这次写操作放到下一次渲染     
7、尽量避免写在HTML标签中写Style属性,会阻塞渲染

加载完成

当 HTML 文档解析绘制完成就会触发 DOMContentLoaded,而所有资源(图片和非阻塞脚本)加载完成之后,load 事件才会被触发。
另外需要提一下的是,我们在 jQuery 中经常使用的 $(document).ready(function() { // ...代码... }); 其实监听的就是 DOMContentLoaded 事件,而 $(document).load(function() { // ...代码... }); 监听的是 load 事件。
在chrome network 左下方能看到,打开overview能看到两条对应的线

编码、转码、转义

 字符 =》二进制

字符集:规定字符 和 对应的码点

Unicode 是一个字符集,需要四个字节才能表示完所有字符。Unicode的前127个码点 与 ASCII字符集相同

双字节码点范围 /[\u0100-\uffff]/

中文码点范围  /[\u4e00-\u9fa5]/

字符编码:将字符的码点编入字节

UTF-32编码采用Unicode字符集,用四个字节编码一个字符

UTF-8编码采用Unicode字符集,变长编码方式,码点小的字符用一个字节编码,码点大的字符用2-4个字节编码。

字符转码

获取十进制Unicode码点:

String.prototype.charCodeAr(index)、String.prototype.codePointAt(index): 

获取十六进制Unicode码点:

escape:  获取Unicode码点,不转码范围{ ASCII字母 数字 @*/+ },用于字符串转码。unescape解码

获取十六进制UTF-8编码(两个16进制数对应一个字节,即每4比特转成一个1-16的数字):
encodeURI: 获取UTF-8编码,不转码范围{ ASCII字母 数字 ~!@#$&*()=:/,;?+' },用于URI转码。decodeURI解码

encodeURIComponent: 获取UTF-8编码,不转码范围 { ASCII字母 数字 ~!*()' },用于URI的组成部分转码,转码范围比encodeURI大一些。decodeURIComponent解码

二进制 =》字符

Base64编码:每6比特转成一个1-64的数字,再用这个数字在字母表(包含大小写字母数字+/)上找到一个字母
btoa: 对单字节字符进行Base64转码。atob解码

转义

"&单词;" 转成 "特殊字符",浏览器自动完成。浏览器没有自带的转义和反转义API

encodeHTML: function(a) {
    return String(a).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
},
decodeHTML: function(a) {
    var b = String(a).replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
    return b.replace(/&#([\d]+);/g, function(d, c) {
        return String.fromCharCode(parseInt(c, 10))
    })
},

进程与线程

 浏览器进程

1、Brower进程:负责Tab之间的公共功能

2、Render进程:一个Tab对应一个进程,也可能几个进程被合并

3、GPU进程:负责3D绘制

4、第三方插件进程

Render进程

1、GUI渲染线程:负责布局、绘制、重绘Repain、回流Reflow

2、JS引擎线程:解析、运行JS,一个Render进程只有一个JS引擎线程(单线程)

3、事件触发线程

4、定时触发线程,由setInterval 和 setTimeout 创建

5、异步触发线程

6、web work线程,是JS引擎线程的子线程,不会阻塞JS引擎

三种触发线程适时将回掉函数添加到 JS引擎线程的待处理任务队列中,由JS引擎依次执行

JS引擎事件轮询

一个tick(JS引擎从任务队列中提取一个任务(宏任务,macrotask,task) -> 执行宏任务 -> 执行当前tick添加的微任务(microtask, job)-> GUI渲染引擎 repain\reflow) -> 下一个tick

原生 promise resolve/reject 时,会把 then注册的回调函数添加到微任务队列中

vue中的$nextTick 就是下一个宏任务

setTimeout,即使延迟0毫秒,也是到下一个宏任务进行

常见问题

为什么要用setTimeout模拟setInterval?

setInterval准时把回调函数添加到 JS引擎的任务队列,这时候可能上一次添加的任务还没被处理

面试题

setTimeout(() => {
            console.log(4);
        }, 0);
 
        new Promise(resolve=>{
            console.log(1);
            for(let i =0;i<10000;i++){
                i == 9999 && resolve();
            }
            console.log(2)
        }).then(()=>{
            console.log(5)
        })
 
        console.log(3)

// 1 2 3 5 4

正则表达式

POSIX(UNIX操作系统接口标准)定义了两种正则表达式语法,基本正则表达式(Basic Regular Expression,BRE)和扩展正则表达式(Extended Regular Expression,ERE)

正则表达式的用途
用于查找和替换:在一行里查找匹配模式的字符串  linux grep, linux sed, String.match, String.replace
用于检验:把源串当作一行,查找匹配模式的子串,存在匹配串则检验成功  RegExp.test

匹配并分组:String.match /g模式,返回所有匹配的串

                      String.match 非/g模式,返回第一个匹配的串 和 这个匹配串里的分组;分组即表达式里的()

基础正则表达式

支持:linux sed,linux grep

+、()、{}、?、+、| 得用 \ 转义,以下简化为不加 \

/^[^a-z]*.+\b(ss|st){1,3}\b[123]?$/

^表示匹配串得在行首,[^a-z]表示不能是小写字母,*表示0-n个,.表示任意字符(不能匹配换行符),+表示1-n个,\b表示单词边界,()表示组,|表示或(得用在小括号内),{1,3}表示1-3个,[123]表示取123任意一个,?表示0-1个,$表示匹配串得在行尾
常用类:数字\d(不包括小数点和负号),非数字\D,字母\w,非字母\W,空白符\s(包括换行符),非空白符\S

[\s\S]* 可以跨多行匹配


扩展正则表达式

支持:linux grep -E,linux egrep,JS

+、()、{}、?、+、| 都不用\转义

非贪婪模式

支持:JS
* 、+ 、{}默认为贪婪模式,即尽可能匹配更多的字符
JS支持非贪婪模式:*? 、+? 、{}?,匹配最少的字符

环视(零宽断言)

支持:JS
作为匹配条件(断言),但不作为匹配串的一部分(零宽)
(?<=B)A : 匹配串得匹配A,而且匹配串前的片段得匹配B
(?<!B)A : 匹配串得匹配A,而且匹配串前的片段得不匹配B
A(?=B)  : 匹配串得匹配A,而且匹配串后的片段得匹配B
A(?!B)  : 匹配串得匹配A,而且匹配串后的片段得不匹配B

模式修正符
支持:linux sed,JS
/g 全行匹配多个,匹配串之间不会交叉,有/g则String.match返回一个数组
/i 不区分大小写
/m 多行匹配,JS默认为单行匹配,即把源串只有一个结束符,多行匹配则能匹配多个结束符$

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值