浏览器缓存机制浅析

2015/08/05 · HTML5 · 1
评论 ·
缓存

本文作者: 伯乐在线 –
韩子迟
。未经作者许可,禁止转载!
欢迎加入伯乐在线 专栏作者。

只有 90 年代的 Web 开发者才记得这些

2016/04/26 · 基础技术 ·
2 评论 ·
WEB

本文由 伯乐在线 –
dcscodelife
翻译,艾凌风
校稿。未经许可,禁止转载!
英文出处:holman。欢迎加入翻译组。

你曾经强行把 <blink> 标签放入
<marquee> 标签吗?如今皮克斯动画工作室获得了所有荣誉,但是在 90
年代这个做法则是电脑动画的伟大创举。通过组合两种标签,你成为了一个先驱者。一个创意无限的人。一个令所有人都崇拜的人。

在 90 年代,你曾经是一个网页开发者。

在当时,你知道自己是一个出色的人物。伴随你而来的是极其大量的技术创新,从那时候开始,我们还没来得及做出喜好,技术就已经开始复制开来了。

让我们先放下 jQuery,抛开非关系型数据库不谈:我们有更重要的事情要讨论。

JavaScript 面试中常见算法问题详解

2017/02/20 · JavaScript
· 1 评论 ·
算法

原文出处:
王下邀月熊_Chevalier   

JavaScript
面试中常见算法问题详解 翻译自
Interview Algorithm Questions in Javascript()
{…}
从属于笔者的 Web
前端入门与工程实践。下文提到的很多问题从算法角度并不一定要么困难,不过用
JavaScript 内置的 API 来完成还是需要一番考量的。

非HTTP协议定义的缓存机制

浏览器缓存机制,其实主要就是HTTP协议定义的缓存机制(如: Expires;
Cache-control等)。但是也有非HTTP协议定义的缓存机制,如使用HTML Meta
标签,Web开发者可以在HTML页面的<head>节点中加入<meta>标签,代码如下:

XHTML

<META HTTP-EQUIV=”Pragma” CONTENT=”no-cache”>

1
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">

上述代码的作用是告诉浏览器当前页面不被缓存,每次访问都需要去服务器拉取。使用上很简单,但只有部分浏览器可以支持,而且所有缓存代理服务器都不支持,因为代理不解析HTML内容本身。下面主要介绍HTTP协议定义的缓存机制

1×1.gif

1×1.gif
应该获得伟大的格莱美大奖。或者普利策新闻奖。或者类似三年级体育课上颁发的最佳进步奖。除了链式链表,它是计算机科学史上最重要的成就。它不是我们应得的未来,而是我们需要的未来(直到盒子模型彻底取代了它)。

如果你还没不熟悉我们的 1×1.gif 小把戏,请看下面:

图片 1

你能看到它吗,让我们放大一些:

图片 2

The 1×1.gif

这个 1×1.gif – 或者 spacer.gif,或者 transparent.gif –
仅仅是一个长宽都是一个像素的透明 GIF 图像。

JavaScript

<IMG SRC=”/1×1.gif” WIDTH=150 HEIGHT=250>

1
<IMG SRC="/1×1.gif" WIDTH=150 HEIGHT=250>

通过上面的代码,你可以把元素放置在页面的任何位置上。

JavaScript

<TABLE> <TR> <TD><IMG SRC=”1×1.gif” WIDTH=300>
<TD><FONT SIZE=42>Hello welcome to my
<MARQUEE>Internet Web Home</MARQUEE></FONT>
</TR> <TR> <TD BGCOLOR=RED><IMG
SRC=”/cgi/webcounter.cgi”> </TR> </TABLE>

1
2
3
4
5
6
7
8
9
<TABLE>
  <TR>
    <TD><IMG SRC="1×1.gif" WIDTH=300>
    <TD><FONT SIZE=42>Hello welcome to my <MARQUEE>Internet Web Home</MARQUEE></FONT>
  </TR>
  <TR>
    <TD BGCOLOR=RED><IMG SRC="/cgi/webcounter.cgi">
  </TR>
</TABLE>

1×1.gif
让你毫不费力地在页面的任何位放置元素。直到今天为止,它仍然是唯一的垂直居中元素的方法。

JavaScript

          

1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

图片对于你而言是不是太高级了?《HTML For Dummies》是不是直到第四章才介绍
<IMG> 标签?现在好了,你是幸运的:&nbsp; 标签来了!

你可以对自己说,“我知道所有 HTML
实体编码。这个弱不禁风的帅哥来这里干嘛的?”

听着,我亲爱的聪明的迷人的读者朋友,这是一个如今的年轻人没有给予足够尊重的创新:不断重复
&nbsp;。很像 1×1.gif 的小把戏,你能任意地扩展 &nbsp;
并用在任何你需要的地方:

JavaScript

PLEASE SIGN <BR>       MY GUESTBOOK
BELOW: <HR><HR>

1
2
3
PLEASE SIGN  <BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MY GUESTBOOK BELOW:
<HR><HR>

在 90 年代,如果我每写下一个 &nbsp;
就得到五美分,我就会有足够的钱支付来自美国在线的每月超支账单了。

JavaScript Specification

大话浏览器缓存

浏览器缓存一直是一个让人又爱又恨的存在,一方面极大地提升了用户体验,而另一方面有时会因为读取了缓存而展示了“错误”的东西,而在开发过程中千方百计地想把缓存禁掉。如果没听说过浏览器缓存或者不知道浏览器缓存的用处,可以先浏览一下这篇文章->Web缓存的作用与类型 。

那么浏览器缓存机制到底是如何工作的呢?核心就是把缓存的内容保存在了本地,而不用每次都向服务端发送相同的请求,设想下每次都打开相同的页面,而在第一次打开的同时,将下载的js、css、图片等“保存”在了本地,而之后的请求每次都在本地读取,效率是不是高了很多?真正的浏览器工作的时候并不是将完整的内容保存在本地,各种浏览器都有不同的方式,譬如firefox是一种类似innodb的方式存储的key
value 的模式,在地址栏中输入 about:cache
可以看见缓存的文件,chrome会把缓存的文件保存在一个叫User
Data的文件夹下。但是如果每次都读取缓存也会存在一定的问题,如果服务端的文件更新了呢?这时服务端就会和客户端约定一个有效期,譬如说服务端告诉客户端1天内我服务端的文件不会更新,你就放心地读取缓存吧,于是在这一天里每次遇到相同的请求客户端都开心地可以读取缓存里的文件。但是如果一天过去了,客户端又要读取该文件了,发现和服务端约定的有效期过了,于是就会向服务端发送请求,试图下载一个新的文件,但是很有可能服务端的文件其实并没有更新,其实还是可以读取缓存的。这时该怎么判断服务端的文件有没有更新呢?有两种方式,第一种在上一次服务端告诉客户端约定的有效期的同时,告诉客户端该文件最后修改的时间,当再次试图从服务端下载该文件的时候,check下该文件有没有更新(对比最后修改时间),如果没有,则读取缓存;第二种方式是在上一次服务端告诉客户端约定有效期的同时,同时告诉客户端该文件的版本号,当服务端文件更新的时候,改变版本号,再次发送请求的时候check一下版本号是否一致就行了,如一致,则可直接读取缓存。

而事实上真正的浏览器缓存机制大抵也是如此,接下来就可以分别对号入座了。

需要注意的是,浏览器会在第一次请求完服务器后得到响应,我们可以在服务器中设置这些响应,从而达到在以后的请求中尽量减少甚至不从服务器获取资源的目的。浏览器是依靠请求和响应中的的头信息来控制缓存的

点下划线,边界效应

在 HTML 快走到他的黄金时代的尾巴时,CSS
登场了,它带来了一个内容和样式分离的世界,从此我们也开始不停地处理灾难。

首当其冲地当然是用 CSS
来删除链接的下划线效果。一夜之间,整个因特网都陷入了这个方法所带来的泥泞之中,文本看起来像链接,链接看起来像文本。你不知道点哪里,但是黑暗并没有持续多久,因为我们发明了光标效果(你还没有活到你的鼠标有十二个火球尾巴的时候)。

高级技术的应用是如此引人注目,以至于几乎我们所有人都从一开始就使用
CSS。我甚至在 2000 年的一份 index.shtml(对,就是
SSI)文档中发现了证据:

JavaScript

<style type=”text/css”> <!– a:hover {text-decoration: none;
color: #000000} –> </style>

1
2
3
4
5
<style type="text/css">
<!–
a:hover {text-decoration: none; color: #000000}
–>
</style>

就是它了!当然,这是 CSS
的内嵌样式。这个样式使你的鼠标滑过链接时,删除链接的下划线并且链接的文字变黑。从此,交互式网站诞生了。

阐述下 JavaScript 中的变量提升

所谓提升,顾名思义即是 JavaScript
会将所有的声明提升到当前作用域的顶部。这也就意味着我们可以在某个变量声明前就使用该变量,不过虽然
JavaScript 会将声明提升到顶部,但是并不会执行真的初始化过程。

Expires与Cache-Control

Expires和Cache-Control就是服务端用来约定和客户端的有效时间的。

图片 3

比如如上一个响应头,Expires规定了缓存失效时间(Date为当前时间),而Cache-Control的max-age规定了缓存有效时间(2552s),理论上这两个值计算出的有效时间应该是相同的(上图好像不一致)。Expires是HTTP1.0的东西,而Cache-Control是HTTP1.1的,规定如果max-age和Expires同时存在,前者优先级高于后者。Cache-Control的参数可以设置很多值,譬如(参考浏览器缓存机制):

图片 4

DHTML 动态超文本标记语言

就在我们拥有了删除链接下划线的技术后,我们决定把它和一个强大功能结合起来,这个功能就是在页面加载的时候弹出一个消息框
alert("Welcome to my website!")。组合 CSS 和 JavaScript
的二者力量,我们得到了一个技术怪兽:DHTML。

DHTML,表示“分布式
HTML”,这是网页开发工具的最高成就。它将经受住时间的考验,它可以使我们实现很多效果,比如雪花从页面顶部飘落下来,或者创建可折叠的菜单,动态的图片地图,又或者除了使用语义标签
<div>,我们还可以自定义 <marquee> 标签。

DHTML 帮助 Web 开发从业余爱好发展到一个成熟的专业领域。类似 Dynamic
Drive 这样的网站使你可以仅仅通过复制粘贴一个 50
行的代码块,就可以解决任何问题,而不需要自己再思考创新的解决方法。实际上,
DHTML 就是那个年代的 Twitter Bootstrap 框架。

阐述下 use strict; 的作用

use strict; 顾名思义也就是 JavaScript
会在所谓严格模式下执行,其一个主要的优势在于能够强制开发者避免使用未声明的变量。对于老版本的浏览器或者执行引擎则会自动忽略该指令。

JavaScript

// Example of strict mode “use strict”; catchThemAll(); function
catchThemAll() { x = 3.14; // Error will be thrown return x * x; }

1
2
3
4
5
6
7
8
// Example of strict mode
"use strict";
 
catchThemAll();
function catchThemAll() {
  x = 3.14; // Error will be thrown
  return x * x;
}

Last-Modified/If-Modified-Since

而Last-Modified/If-Modified-Since就是上面说的当有效期过后,check服务端文件是否更新的第一种方式,要配合Cache-Control使用。比如第一次访问我的主页simplify
the
life,会请求一个jquery文件,响应头返回如下信息:

图片 5

然后我在主页按下ctrl+r刷新,因为ctrl+r会默认跳过max-age和Expires的检验直接去向服务器发送请求(下文再探讨各种刷新后如何读取缓存),我们看看请求截图:

图片 6

请求头中包含了If-Modified-Since项,而它的值和上次请求响应头中的Last-Modified一致,我们发现这个日期是在遥远的2013年,也就是说这个jquery文件自从2013年的那个日期后就没有再被修改过了。将If-Modified-Since的日期和服务端该文件的最后修改日期对比,如果相同,则响应HTTP304,从缓存读数据;如果不相同文件更新了,HTTP200,返回数据,同时通过响应头更新last-Modified的值(以备下次对比)。

像素字体

那个年代的电脑屏幕不是很大。我的意思是,虽然自从阴极射线管显示器 CRT
诞生后,显示器的尺寸的确很大,但是它们的分辨率不高。因此,为了充分利用像素,我们必须用
6 个像素点来表示任意字符。

图片 7

从字里行间我们可以看出,当面对着这些简单的不能再简单的字体,并且当意识到这些字体都是由像素构成的时候,Web
开发者们会渴望成为一个漫画家。所以你会在启动画面上看到那些奇怪的等距像素插图,这些开发者的时间和金钱如果投到那些新上市的互联网公司会产生更多的价值,而不是浪费在安装
Photoshop 软件上。

解释下什么是 Event Bubbling 以及如何避免

Event Bubbling
即指某个事件不仅会触发当前元素,还会以嵌套顺序传递到父元素中。直观而言就是对于某个子元素的点击事件同样会被父元素的点击事件处理器捕获。避免
Event Bubbling 的方式可以使用event.stopPropagation() 或者 IE 9
以下使用event.cancelBubble

ETag/If-None-Match

而ETag/If-None-Match则是上文大话中说的第二种check服务端文件是否更新的方式,也要配合Cache-Control使用。实际上ETag并不是文件的版本号,而是一串可以代表该文件唯一的字符串(Apache中,ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的。),当客户端发现和服务器约定的直接读取缓存的时间过了,就在请求中发送If-None-Match选项,值即为上次请求后响应头的ETag值,该值在服务端和服务端代表该文件唯一的字符串对比(如果服务端该文件改变了,该值就会变),如果相同,则相应HTTP304,客户端直接读取缓存,如果不相同,HTTP200,下载正确的数据,更新ETag值。

图片 8

看如上截图,与服务器约定的直接读取本地缓存的时间过了,就会向服务器发送新的请求,请求头中带If-None-Match项,该字符串值会在服务端进行匹配,很显然,并没有什么变化(看响应头的ETag值),于是响应HTTP304,直接读取缓存。或许你会发送该请求也有If-Modified-Since项,如果两者同时存在,If-None-Match优先,忽略If-Modified-Since。或许你会问为什么它优先?两者功能相似甚至相同,为什么要同时存在?HTTP1.1中ETag的出现主要是为了解决几个Last-Modified比较难解决的问题:

  1.  Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间
  2. 如果某些文件会被定期生成,但有时内容并没有任何变化(仅仅改变了时间),但Last-Modified却改变了,导致文件没法使用缓存
  3. 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形

按钮

我相信人们之所以讨厌IE浏览器,都是因为IE浏览器抛弃了当初那种最纯粹的样子

IE 4.0 是浏览器的完美化身。它拥有动态桌面。拥有通道
Channels。对,就是伟大的通道,这是最酷的技术,之前从来没有在市场上被使用过,一点都没有。总的来说,IE
4 太优秀了,无论你是否喜欢它,你都应该把它装到你的电脑上。

当你属于精英团体时,你深刻理解完美的价值,你有一种与生俱来的冲动,你想告诉每一个你遇到的人你的决定。你,也唯独只有你有必要庄严地做一个伟大的决定。比如决定你的客户使用什么浏览器浏览你的网站。

图片 9

这些按钮随处可见。就像军官衣服上的绶带:向人们宣告着他们为了如今的荣耀,曾经是如何努力战斗的故事。换句话说,无论你用哪一个编辑器(当然是
FrontPage 98),无论你的 Web 服务器是什么(傻瓜,当然是
GeoCities),无论是 Web
环的哪个部分(这个按钮无论如何都将提高你的网站排名)

我怀念这段美好的时光。如今我们在
Javascript上进行抽象,在抽象之上又进行抽象。我们甚至都不知道如何准确地进行计算。每当想起我们如何走到今天这一步,都令人十分吃惊。

让我们自豪地举起酒杯,帮我们一个忙:复制一堆 &nbsp;
到你的下一个代码提交中,让你的团队成员大吃一惊吧。

1 赞 收藏 2
评论

== 与 === 的区别是什么

=== 也就是所谓的严格比较,关键的区别在于===
会同时比较类型与值,而不是仅比较值。

JavaScript

// Example of comparators 0 == false; // true 0 === false; // false 2 ==
‘2’; // true 2 === ‘2’; // false

1
2
3
4
5
6
// Example of comparators
0 == false; // true
0 === false; // false
 
2 == ‘2’; // true
2 === ‘2’; // false

不能缓存的请求

当然并不是所有请求都能被缓存。

无法被浏览器缓存的请求:

  1. HTTP信息头中包含Cache-Control:no-cache,pragma:no-cache(HTTP1.0),或Cache-Control:max-age=0等告诉浏览器不用缓存的请求
  2. 需要根据Cookie,认证信息等决定输入内容的动态请求是不能被缓存的
  3. 经过HTTPS安全加密的请求(有人也经过测试发现,ie其实在头部加入Cache-Control:max-age信息,firefox在头部加入Cache-Control:Public之后,能够对HTTPS的资源进行缓存,参考《HTTPS的七个误解》)
  4. POST请求无法被缓存
  5. HTTP响应头中不包含Last-Modified/Etag,也不包含Cache-Control/Expires的请求无法被缓存

关于作者:dcscodelife

图片 10

简介还没来得及写 :)
个人主页 ·
我的文章 ·
10 ·
 

图片 11

解释下 null 与 undefined 的区别

JavaScript 中,null 是一个可以被分配的值,设置为 null
的变量意味着其无值。而 undefined
则代表着某个变量虽然声明了但是尚未进行过任何赋值。

用户行为与缓存

浏览器缓存过程还和用户行为有关,譬如上面提到的,打开我的主页simplify
the
life,有个jquery的请求,如果直接在地址栏按回车,响应HTTP200(from
cache),因为有效期还没过直接读取的缓存;如果ctrl+r进行刷新,则会相应HTTP304(Not
Modified),虽然还是读取的本地缓存,但是多了一次服务端的请求;而如果是ctrl+shift+r强刷,则会直接从服务器下载新的文件,响应HTTP200。

图片 12

通过上表我们可以看到,当用户在按F5进行刷新的时候,会忽略Expires/Cache-Control的设置,会再次发送请求去服务器请求,而Last-Modified/Etag还是有效的,服务器会根据情况判断返回304还是200;而当用户使用Ctrl+F5进行强制刷新的时候,只是所有的缓存机制都将失效,重新从服务器拉去资源。

更多可以参考浏览器缓存机制

解释下 Prototypal Inheritance 与 Classical Inheritance 的区别

在类继承中,类是不可变的,不同的语言中对于多继承的支持也不一样,有些语言中还支持接口、final、abstract
的概念。而原型继承则更为灵活,原型本身是可以可变的,并且对象可能继承自多个原型。

总结

盗图浏览器缓存机制,两张图很清晰

图片 13

 

 

图片 14

数组

发表评论

电子邮件地址不会被公开。 必填项已用*标注