闭包
找到的是同一地址中父级函数中对应变量最终的值
1 | function a() { |
变量提升
在非严格模式下,JavaScript中存在变量提升的特点。
- 原因
JavaScript的工作原理是先编译再执行,在编译过程中,解释器会把所有声明“移动”到所在作用域的最上面,而赋值或其他逻辑会留在原地,这就是变量提升。
例如
1 | foo(); |
在编译后将被理解为下面的形式
1 | function foo(){ |
2.函数优先
在提升过程中,函数声明将首先提升,然后才是变量。只有函数声明( function a(){} )才会被提升,函数表达式( var a = function b(){} )不会提升。如果存在相同的声明,相同的变量声明将被忽略;相同的函数声明,后面的将会覆盖前面的。
例如
1 | foo(); // 1 |
将被理解为
1 | function foo(){ |
session,token,cokkies
知乎高赞的一篇文章,写的很不错。
Session
session 从字面上讲,就是会话。这个就类似于你和一个人交谈,你怎么知道当前和你交谈的是张三而不是李四呢?对方肯定有某种特征(长相等)表明他就是张三。
session 也是类似的道理,服务器要知道当前发请求给自己的是谁。为了做这种区分,服务器就要给每个客户端分配不同的“身份标识”,然后客户端每次向服务器发请求的时候,都带上这个“身份标识”,服务器就知道这个请求来自于谁了。至于客户端怎么保存这个“身份标识”,可以有很多种方式,对于浏览器客户端,大家都默认采用 cookie 的方式。
服务器使用session把用户的信息临时保存在了服务器上,用户离开网站后session会被销毁。这种用户信息存储方式相对cookie来说更安全,可是session有一个缺陷:如果web服务器做了负载均衡,那么下一个操作请求到了另一台服务器的时候session会丢失。
tokens
Cookie
cookie 是一个非常具体的东西,指的就是浏览器里面能永久存储的一种数据,仅仅是浏览器实现的一种数据存储功能。
cookie由服务器生成,发送给浏览器,浏览器把cookie以kv形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该cookie发送给服务器。由于cookie是存在客户端上的,所以浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的cookie数量是有限的。
CSS选择器权重
!important Infinity(正无穷)
行间样式 1000
id 100
class|属性|伪类 10
标签|伪元素 1
通用选择器(*) |子选择器(>)|相邻选择器(+)|同胞选择器(~) 0
权值可以相加
span的权值为 = id选择器100+类选择器10+元素选择器1 = 111
权值相同时
由于HTML代码的执行特点时从上往下执行,因此在权值相同的情况下,后面的选择器会覆盖前面的选择器相同的属性
权值不同时
两种选择器覆盖了同一属性,此时权重高的选择器生效。
权值跃迁
权值跃迁讨论的问题是,当有11个元素选择器和1个类选择器同时选中同一元素时,哪个选择器的样式会生效。
结论是:权级高的选择器的样式会生效。
理解方式1
因为权值不能跃迁,也就意味着无论有多少个0级的选择器,生效的仍然是1级选择器,因 为选择器的权级无法跃迁。
理解方式2
CSS里面的进制并不是10进制,而是256进制,所以10个低级选择器并不能等于1个高级选择器
eventloop
setTimeout, setInterval, setImmediate 属于 macro-tasks
Promise, MutantObserver 属于 micro-tasks
举例:去窗口办理业务
正常 task
- 同志你好,这是我的资料
- 好的,我现在处理。处理完了,请下一位
Promise
- 同志你好,这是我资料
- 你这资料这没填对,你这样,你填完后重新排到队尾好吧,咱们别阻碍别人的业务
- 好的好的,谢谢
setTimeout
- 同志你好,这是我资料
- 你的证件带了吗?
- 哎!我忘家了,我现在回去拿!
- 哎 …,你回去拿哈,回来了重新叫号重新排队
- 好的好的,不好意思同志
所以 Promise 的优先级会高于 setTimeout。micro-tasks 列队结束后会(通常)会触发一次 update rendering。整个流程差不多是:
- 有没有 macrotask 任务?有就来一个
- 有没有 microtask 任务?有就把这个列队的任务全弄完
- 弄完了,需要更新视图(update rendering)吗?需要就更新
上代码!
上面的执行结果是2,1。
从规范上来讲,setTimeout有一个4ms的最短时间,也就是说不管你设定多少,反正最少都要间隔4ms才运行里面的回调。而Promise的异步没有这个问题。
从具体实现上来说,这两个的异步队列不一样,Promise所在的那个异步队列优先级要高一些。具体讲解看第二个例子:
执行结果1,2,3,5,4
为什么执行这样的结果?
1、创建Promise实例是同步执行的。所以先输出1,2,3,这三行代码都是同步执行。
2、promise.then和setTimeout都是异步执行,会先执行谁呢?
setTimeout异步会放到异步队列中等待执行。
promise.then异步会放到microtask queue中。microtask队列中的内容经常是为了需要直接在当前脚本执行完后立即发生的事,所以当同步脚本执行完之后,就调用microtask队列中的内容,然后把异步队列中的setTimeout放入执行栈中执行,所以最终结果是先执行promise.then异步,然后再执行setTimeout异步。
这是由于:
Promise 的回调函数属于异步任务,会在同步任务之后执行。
但是,Promise 的回调函数不是正常的异步任务,而是微任务(microtask)。它们的区别在于,正常任务追加到下一轮事件循环,微任务追加到本轮事件循环。这意味着,微任务的执行时间一定早于正常任务。
注意:目前microtask队列中常用的就是promise.then。
1 | setTimeout(() => { |
执行结果3,4,5,6,7
- 本文作者: Raphael_Li
- 本文链接: https://lifei-2019.github.io/interview1/
- 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!