0做为一个特殊的符号,常常会跟浏览器打交道,在不一样的场景下,0表明的意思不尽相同,所以浏览器眼中的0不必定就是符合人们感官上的认识,那究竟浏览器会怎么对待它呢,今天咱们就来探究一下各类场景中0的含义及浏览器的处理方式。css
1.setTimeout
setTimeout在js中经常使用来推迟任务的执行,能够经过第二个参数设置延迟的毫秒数(若是不设置,默认为0),在一些代码中,能够看到delay=0的状况,以下:html
window.setTimeout(() => { ...... }, 0);
了解js的同窗应该知道,setTimeout的回调函数不会在定时器超时后当即执行,若是delay大于0,比较好理解,但delay是0的时候呢,浏览器会怎么对待呢,这里要分两种状况: 1.)timer嵌套 'Timers can be nested; after five such nested timers, however, the interval is forced to be at least four milliseconds.'
也就是setTimeout嵌套超过5层的,而且延迟不到4ms,才会变成4ms,一样适用于setInterval,所以在这种状况下,delay=0其实会被设置成4; 2.)timer没有嵌套 在没有嵌套状况下,对于chrome来讲,delay=0也会设置成1; 说完浏览器的处理方式以后,咱们来看看网上搬过来的一个例子吧:node
setTimeout(()=>{console.log(5)},5) setTimeout(()=>{console.log(4)},4) setTimeout(()=>{console.log(3)},3) setTimeout(()=>{console.log(2)},2) setTimeout(()=>{console.log(1)},1) setTimeout(()=>{console.log(0)},0)
chrome打印结果:1 0 2 3 4 5; firefox打印结果:0 1 2 3 4 5; edge打印结果:1 2 0 3 4 5; qq浏览器打印结果:1 0 2 3 4 5; 360浏览器打印结果:1 0 2 3 4 5; 从上面的打印结果来看,firefox是符合代码预期的,edge打印与chrome稍有不一样,应该是edge处理delay=0状况稍有不一样(设置成了2),qq和360浏览器跟chrome保持一致。 0ms定时器 在MDN文档上,还说到一种实现0ms延时的定时器的实现方案,大致思路是自定义一个setZeroTimeout
方法,经过 postMessage
来触发定时回调的执行,具体可看 https://dbaron.org/log/20100309-faster-timeouts ; node的setTimeout 说完浏览器中的setTimeout,咱们再来看看nodejs中的是否同样呢,能够经过nodejs的源代码窥探一二:git
// https://github.com/nodejs/node/blob/master/lib/internal/timers.js function Timeout(callback, after, args, isRepeat, isRefed) { after *= 1; // Coalesce to number or NaN if (!(after >= 1 && after <= TIMEOUT_MAX)) { // const TIMEOUT_MAX = 2 ** 31 - 1; if (after > TIMEOUT_MAX) { process.emitWarning(`${after} does not fit into` +' a 32-bit signed integer.' + '\nTimeout duration was set t 1.', 'TimeoutOverflowWarning'); } after = 1; // Schedule on next tick, follows browser behavior }
看过源代码后,就知道node的处理策略了:若是delay=0,会设置为1,注释也说得很清楚了,是为了遵循浏览器的行为。es6
2.+0&-0
虽然不多用到,可是js中确是存在+0和-0的,那么有什么区别呢:github
+0 === -0; // true +0 === 0; // true -0 === 0; // true
能够看到,经过全等比较,+0,-0和0都是相等的,那是否就能够认为这三者就是同样的呢,还不能这么轻易下结论,有时候颇有必要区分三者,那么如何判断呢,es6新增了一个方法Object.is(value1, value2),能够用来判断,具体效果以下:chrome
Object.is(0, -0); // false Object.is(+0, -0); // false Object.is(+0, 0); // true
这里还须要说明的一点就是+0和0其实就是同样的,由于+0等效Number(0),所以Object.is(+0, 0)是符合预期的,这里顺带说一下Object.is的比较逻辑,根据MDN文档描述, Object.is()
方法判断两个值是否为同一个值。若是知足如下条件则两个值相等:浏览器
与==
运算不一样。 ==
运算符在判断相等前对两边的变量(若是它们不是同一类型) 进行强制转换 (这种行为的结果会将 "" == false
判断为 true
), 而 Object.is
不会强制转换两边的值。 与===
运算也不相同。 ===
运算符 (也包括 ==
运算符) 将数字 -0
和 +0
视为相等 ,而将Number.NaN
与NaN
视为不相等.ide
最后来看下如何生成-0和+0吧:函数
1/-Infinity; // -0 0*-1; // -0 1/+Infinity; // +0 0*+1;// +0
3. +[]
因为存在类型转换,所以在判断相等时,会有这样的状况:
'' == 0; // true [] == 0; // true +[] == 0; // true
这里咱们说一下+[]的状况,很容易理解,+至关于Number([]),最终会转换成0,这没什么大不了,若是是下面这段代码呢:
(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[+!+[]+[!+[]+!+[]+!+[]]]+[+!+[]]+([+[]]+![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[!+[]+!+[]+[+[]]]
其实表明的就是alert(1)
, http://www.jsfuck.com/ 这个奇葩网站专门干这事的,原理就是使用的类型转换,把咱们熟悉的代码变成了这样,真是骚操做。
4.font-size
font-size在css中使用频繁,浏览器一般会默认设置成14px或者16px。若是设置成0呢?
.foo { font-size: 0; } <span class="foo">foo</span>
文字真的就没有了,这符合预期,但若是设置的值小于12(非负),各浏览器处理稍有不一样,chrome/edge浏览器会设置最小字体为12px,firefox严格按照给定的值来显示。 font-size:0的用处 在布局过程当中,常常会生成空白字符,例如:
<div class="box1"> <span>a</span> <span>b</span> </div> <div class="box2"> <img src="xxx.jpg"> </div>
box1和box2高度实际上是略高于实际的内容的,并且box1的两个span中间有间隙,没有紧挨着,由于空白字符的缘由,引用css规范说明:On a block container element whose content is composed of inline-level elements, 'line-height' specifies the minimal height of line boxes within the element. The minimum height consists of a minimum height above the baseline and a minimum depth below it, exactly as if each line box starts with a zero-width inline box with the element's font and line height properties. We call that imaginary box a "strut.",大意就是一个块级容器元素内容区域由inline-level元素组成的;而这些linline-level元素被放在每一行的line-box里面,line-box高度是由它全部子元素的高度计算得出的。浏览器会计算这一行里每一个子元素的高度,再得出 line-box 的高度(具体来讲就是从子元素的最高点到最低点的高度)。默认状况下,一个 line-box 老是有足够的高度来容纳它的子元素,而每个行框能够想象为默认会有一个宽度为0的空白节点,字体大小和行高会影响该节点,具体规范可查看 https://www.w3.org/TR/CSS2/visudet.html#line-height。 说完规范后,再来分析一下box1和box2的效果,为了便于理解,下面的代码手动加入了一个[x]
符号,表明strut:
<div class="box1"> <span>a</span> <span>b</span> [x] </div> <div class="box2"> <img src="xxx.jpg">[x] </div>
box1的两个span发生了换行,至关于中间有个空格,所以会有间隙,若是span不换行,那么中间的空隙也就没有了。因为存在[x]
,并且vertical-align:baseline的缘故,span/img和[x]
的baseline对齐以后,[x]
处于baseline如下的部分会撑开整个line-box的高度,所以会外部块级容器的高度会略高一些,说得不清楚,咱们仍是上一张图来讲明吧: 粉色的线是图片的baseline,红色的线是strut的baseline,对齐以后strut的baseline下面还有一部分高度,box的最终高度就是img的顶部到strut底部之间的距离。分析完成因后,终于可使用font-size:0来解决问题了,在box上设置font-size:0后,strut就至关于没有了,所以就不存在高度撑开的问题了,固然这里还能够改变img的vertical-align属性来修复这个问题,好比img{ vertical-align:bottom; }那么img的粉色线就跟strut的底部对齐了,也就不会撑开容器高度了,这里说了box2,box1原理差很少,这里涉及到vertical-align的知识了,可查阅https://www.w3.org/TR/CSS2/visudet.html#vertical-align 进行了解。
5.width&height
width和height也是能够设置成0的,效果也是符合咱们预期的,但若是咱们的意图是想经过设置0把元素隐藏的话,通常状况下会采用以下方案:
.visually-hidden { clip: rect(0 0 0 0); clip-path: inset(50%); height: 1px; width: 1px; overflow: hidden; position: absolute; white-space: nowrap; }
有些屏幕阅读器会忽略width和height等于0的元素,所以这里特地设置成1px,固然关于元素的隐藏还有不少实现方案,有兴趣可参考【1】;
6.line-height
line-height及行高,原意是baseline之间的高度,在css中就是一行的高度。默认状况下,line-height是跟具体字体定义相关联的,通常都是font-size的1.x倍,若是设置成0,在不一样类型元素上的状况是不同的,可分为以下三种状况: 1.)非置换行类元素 line-height定义的是最终参与计算line-box(行盒)的高度的值,而不会影响non-replaced inline element(非置换行类元素)的实际高度;
<style> .foo { line-height:0; } </style> <div> <span class="foo">a</span> // class为foo的span高度不会受样式影响 </div>
2.)行类块级元素 会影响元素高度,若是line-height设置为0,那么该元素高度就变成了0,若是设置了height,那么height将会起做用; 3.)块级元素 当块级元素包含inline-level(display:inline|inline-block)元素时, 行高定义的每个line-box(行盒)的最小高度,此外height也能影响块级元素的最终高度,height比line-height有更高优先级,当没有height状况下,line-height起做用; 上面提到了line-box,若是有不了解的同窗,能够看一下文末的连接【2】;
7.transform
transform经常使用来作样式变化和动画,在有时候,会设置成以下形式:
transform: translateZ(0);
这实际上是为了启用GPU加速渲染,元素会单独在一个绘制层(Layer)里进行绘制,而不会对其余层产生影响,所以也就少了不少计算和合成的功能,并且不会阻塞主线程,动画会更加流畅,固然元素设置太多会致使性能下降,由于须要内存的维护。
参考资料:
【1】https://css-tricks.com/comparing-various-ways-to-hide-things-in-css/ 【2】https://www.w3.org/TR/CSS2/visuren.html#line-box