`
jinhailion
  • 浏览: 46196 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

front-end job interview questions 补充

 
阅读更多
前端安全这里xss分为三种主要依据数据流向区分为dom based型、反射型、存储型。
https://www.jianshu.com/p/7826bf9e8efd 《xss攻击的三种类型》


【1】 == 和 ===
个人总结:
1. 三等比较时就是比较完全相等,除非有一方是NaN,即使NaN === NaN也是false,NaN只能用isNaN()来判断
2. 二等比较时
对象和对象比较,不转toString,直接比较指针地址
1) 当字符串和数字比较时,将字符串转换为数字再做比较
2) 当字符串和布尔类型做比较时,先将布尔类型转换为数字,true为1,false为0,再做比较
所以'1'==true 返回true,但'abc'==true 返回false。 'true' == true 返回false但'true' + true返回 'truetrue' (比较运算时,倾向于转换为数字做比较,+运算时如果包含字符串,那么先倾向于字符串转换并连接)
但当'abc'直接做为if条件或作为二元运算的条件时又是表示true的
(如何记忆,‘abc’和true,怎么也转换不成一样,所以不行。 if 条件是一个比较特殊的用法,他不是看里面东西和true是否相等,而是看truthy和falsy)
3) 比较的东西中有对象时,先调用对象的valueof、toString
比如 var obj = { ... };    obj == 'abc'
假如是对象和字符串比较,如果3等,当然false,如果2等,就要看对象的valueof和toString是否和字符串相同,相同就是true。 对象和数组的valueof都返回它们自己。经过实验如果valueof返回任何一个对象,那么就尝试用原对象的toString和'abc'进行比较。而不是用返回的对象的toString和abc比较。
const obj = {
    valueOf() {
        return 'abc'
    },
    toString() {
        return 'aaa'
    }
}

const obj2 = {
    valueOf() {
        return 'bbb'
    },
    toString() {
        return 'abc'
    }
}

const obj3 = {
    valueOf() {
       return new Date(); // 返回任意对象
    },
    toString() {
        return 'abc'
    }
}

console.log(obj == 'abc') // true
console.log(obj2 == 'abc') // false
console.log(obj3 == 'abc') // true (没有用new Date()的toString和'abc'比较,而是用了原对象的toString和'abc'进行了比较)

// 结论先比较valueOf,如果valueOf不是对象,则直接比较结果。如果valueOf的返回值是对象(无论什么对象),则再调用原对象的toString比较,而不是用返回的对象的toString比较


4)布尔值作运算时,比如true和字符串相加,true变为'true',比如 true + 'a' = 'truea'。 布尔值向加或布尔值和数字相加,true转为1,false转为0, 比如 true + 1 = 2。
这里就和比较运算时单纯转为数字不同了,比如 true + '1' 结果是'true1'而不是2,但如果true == '1' 结果就是true,是因为都转换为了数字
5)  ==比较时都趋向于将类型逐渐转换为数字类型进行比较,比如boolean和string比较,本质上就是分别转换成number类型进行比较。
整理了一些相关的东西,集中记忆
    console.log(typeof x);    // 'undefined'
    console.log(typeof 10);   // 'number'
    console.log(typeof 'abc'); // 'string'
    console.log(typeof true);  // 'boolean'

    console.log(typeof function () {});  // 'function'

    console.log(typeof [1, 'a', true]);  // 'object'
    console.log(typeof { a: 10, b: 20 });  // 'object'
    console.log(typeof null);  // 'object'
    console.log(typeof undefined); // 'undefined'
    typeof NaN // 'number'
    
    // undefined和null除了相互相等,同自身相等外同其他类型都不想等
    undefined === null // false
    undefined  == null // true
    undefined == false // false
    null == false // false

   // false、null、undefined、''、NaN、0 都是falsy的, 所以非他们都===true,其中null、undefined、NaN直接和false比肯定不等,剩下3个直接和false比较是相等的
   !null === true  // true
   !undefined === true // true

    Number(['']) == false // true, 数组为对象类型先通过valueOf和toString两次,转换为空字符串,然后Number('')转换为了0, false也转换为了0

注意,虽然type of null 结果为object,但null并不是object类型

【2】
https://www.cnblogs.com/chenjg/p/7126822.html
css的下载和解析不会阻塞dom树的加载,但会阻塞dom树的渲染(个人理解,不会阻塞domParser解析生成dom,但会阻塞最后的重排重绘)。css的加载会阻塞js的执行(这条我实验了,确实是,我放了多个版本的bootstrap cdn link,然后css后面的css很久才执行)。
正常情况下css和js下载都是阻塞式的,除非js用defer和async进行下载,才会异步和页面解析分开。css的下载和解析会阻塞js,js的下载和解析也会阻塞页面解析。基本上只有css的下载和解析都不会阻塞页面dom加载,但会阻塞渲染。所以解析完成前,页面看不到东西,在下面第二篇文章中有例子。
https://juejin.im/entry/5a7ad55ef265da4e81238da9 这篇的加载图画的很清楚。
https://juejin.im/entry/5a7ad55ef265da4e81238da 这篇也可参看,评论更出彩,应该主要看w3c的规范,而不是自己实验出一个规则来。

js如果不加defer或aysnc,下载和执行都会阻塞页面dom解析和渲染,所以放头部,会导致页面啥也看不到。

(htmlParser和cssParser都在渲染引擎线程中,js在js引擎线程中,两线程互斥,css的下载和解析会阻碍后续的dom渲染,但是不会阻碍后续dom的解析,应该htmlParser和domParser是并行的,可以看最经典的浏览器渲染图https://images2018.cnblogs.com/blog/1028513/201805/1028513-20180530154313816-1498972038.png)

看了两篇文章后的总结:
css的下载不会阻塞dom的解析,但会阻塞dom的渲染(第一篇文章有实际例子)
css的下载会不会阻塞js的下载(network里可以看到),但会阻塞js的执行
普通script的下载和执行都会阻塞html的解析和渲染,但如果用了defer和async后,在下载时不会阻塞html的解析和渲染,第二篇文章里的多色线图能说明这个问题(这个也可实验验证,比如我用第一篇文章的方式修改network中throttle的下载流量,当js没有下载完时,页面html是不会显示的)

【3】 用模块模式组织代码的好处。
利用了闭包,模块里的局部变量是私有的,外部无法修改。虽然模块可以通过引用的方式,以参数传递到其他引用该模块的模块中,但其他模块里要修改模块的私有的局部变量,只能通过该模块暴露出的方法来修改。可控。
比如
(function(){
   // dogModule
   var age = 18
   return {
     getAage(){}, 
     setAage(){} //其他模块想要修改age,只能通过setAge。
   }
})(otherModule)

如果是全都写在全局下的一堆object模块,那么直接用引用就可修改模块的属性了。所以要用上述的方法

【4】前面看了一个浏览器解析的过程 dom树+css规则树->渲染树->设置渲染树节点样式-》设置节点位置信息-》重拍-》重绘。
个人理解,可能domContentLoad就是dom树加载完后,load是全部完成后。
感觉说的不对,感觉DomContentLoaded事件是在页面全部渲染后触发,只是图片等资源未加载出来,但页面的位置都已经渲染好了。这里需要着权威的文章炎症。

个人理解,经过实验,页面底部放入script,不管是在body里还是在html外面,然后注册onload事件,然后底部js输出一些东西,无论如何onload都在底部js执行后。所以domContentLoaded只是dom渲染完,onLoad还包含页面脚本都执行完

【5】响应式和自适应的区别。
个人理解,自适应只是根据不同的手机尺寸给出界面元素比例上的大小。设计图是一套。
响应式应该又多套设计图,不同的尺寸页面的呈现会有区别,比如栅格就是其中一种,小尺寸手机没有再在一排按比例排列,而是直接分了多排排列

【6】popState
当通过点击浏览器回退或前进,或通过forword back go的方式去到某个历史栈中的url时window.onpopstate被出发,前提是单页,否则跳了。pop出的就是跳到的url的相关信息。
当初pushState放入的什么,这时就可以e.state拿到了。但注意pushState改变url的时候不触发。
http://blog.csdn.net/qq_37491585/article/details/70615480

经过实验发现点击浏览器后退按钮时,再打印history发现长度没有变化,且还能用前进按钮回去。说明对浏览器来说不存在出栈的操作,只是一个指针在栈上移动的操作,history.pushState时,放入栈顶一条记录,同时将指针指向第一条。后退或前进时指针下移或上移,不发生实际的栈pop,但会触发onpopstate,具体看这篇
https://segmentfault.com/a/1190000006052430 《History API与浏览器历史堆栈管理》

我做了个实验,先想页面pushState了2条,此时点返回到首个页面,此时打印history为3条。然后pushState1条,此时显示history为2条,说明后面的历史记录被冲掉了。所以pushState应该是在当前指针的前面放入一条,然后把当前指针移动到他,且去除栈顶的其他数据。

上面的文章也给出了总结:
当执行back操作时,history栈大小并不会改变(history.length不变),仅仅移动当前指针的位置;
若当前指针在history栈的中间位置(非栈顶),此时执行pushState会改变history栈的大小。
总结pushState的规律,可发现当前指针在history栈顶部时执行pushState,会增加history栈大小;若current指针不在栈顶则会在当前指针所在位置添加项。执行back操作并不修改history栈大小,因此可以通过back和forward在当前大小的history栈中自由移动。*

【7】amd和cmd的区别
https://www.zhihu.com/question/20351507
amd 依赖前置 requireJs
cmd 就近依赖 seaJs, 似乎更先进
gulp、grunt都没有使用这两种,不要胡说。

【8】同源理解
http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html
cookie、localStorage、sessionStorage、indexDb都必须在同源页面才可访问
cookie、iframe中如果一级域名不相同,但二级域名相同,都可以通过设置document.domain,使得两个域可以访问相互的cookie,使得当前页面和iframe窗口的页面可以互相访问对方的dom
当前页面和iframe窗口完全不同源可以通过url hash来互相访问。页面和iframe窗口之间都可以修改对方导航里的url。修改时不改动url,只添加hash数据。页面和iframe窗口里可通过hashChange事件监听变化,获取数据
window.name
postMessage 当前页面和窗口之间可以互相访问,通过postMessage发送信息,监听message事件可以相应

在做admin项目时,cookie写入的域名用了*.ajmide.com,导致用户访问xjm.ajmide.com时也会带上这个cookie文件。所以广告监播中就改为了写入adv.ajmide.com这样不和其他的cookie通用。
但这里说的不是这个问题,是不同域名的页面间互相访问对方页面设置的cookie的问题。通过用js设置document.domain = 'ajmide.com' 来实现。这样cookie或iframe就可以互相访问了。在完全不同域的情况下,hashchange的使用并非很简单,因为页面可以修改iframe里页面的hash,但iframe里但页面却不能操作不同域的父页面的hash,这需要一点技巧。(所以阮的说法其实过于简单,这里是存在问题的)
(个人理解,这种就是多个二级域名下发都是一个cookie,不存在互相访问问题了,而前面说的是不同二级域名cookie不同,比如map.baidu.com和tieba.baidu.com的cookie不同,此时要互相访问,设置相同的document.domain。如果都是下发的*.baidu.com,那么就是一个cookie了,大家操纵的一份数据)


【9】seo
seo那个例子中,那个点击的例子改为用js进行跳转更加贴切。
比如原页面里 localhost/index.html 运行js location.href='location/index.html#name=11' 页面的url改变了,但并未发起http请求刷新页面。 但如果location.href='location/index.html?name=11'页面就会刷新了,可以看到200请求。 在单页中,他的功能类似pushState了,可以不刷新修改url。同时可以监听hashchange事件及时获取到url的变化。类似onpopstate。只是onpopstate在pushState时不触发,后面前进后退时从history里读数据才触发

实际使用过程中一种是通过服务端渲染去做,一种是结合vue预渲染功能实际就是build时,相应的单页面路由路径下打出相应的一个html,以便用户点了这个路径可以访问。


【10】前端性能优化
react16性能优化,提到了polyfill.io
https://zhuanlan.zhihu.com/p/37148975

最新看到的一篇2018性能优化的翻译文章:
https://juejin.im/post/5a966bd16fb9a0635172a50a
《2018 前端性能优化清单》
treeshaking的启用,webpack4中应该默认就是使用了,但必须同时使用UglifyjsWebpackPlugin才能起作用,所以使用该插件,或者设置mode为production也会使用该插件

其中提到的scope hoisting
《webpack 的 scope hoisting 是什么》
https://segmentfault.com/a/1190000018220850
https://segmentfault.com/a/1190000012600832
简单的说就是webpack 会把引入的 js 文件“提升到”它的引入者顶部(注意不是整个代码入口的顶层,而是引入者的顶部)。如果不用就是一堆webpack模块,然后互相引用,如果用了,有一些简单的就能直接写到某个引用它的模块的内部,减少模块的定义。在webpack4中使用webpack.optimize.ModuleConcatenationPlugin来启用就可以了。它还是基于es6的import做的,对于commonjs的引入不支持。
https://www.cnblogs.com/tugenhua0707/p/9735894.html
因此 启用 Scope Hoisting的优点如下:
1. 代码体积会变小,因为函数声明语句会产生大量代码,但是第二个没有函数声明。
2. 代码在运行时因为创建的函数作用域减少了,所以内存开销就变小了。
和treeshaking一样,它也基于es6的静态语法分析,所以require是不支持的。对于采用了非 ES6 模块化语法的代码,Webpack 会降级处理不使用 Scope Hoisting 优化,需要在resolve上做特定配置不启用,否则这些代码也做作用域提升就不好了

intersection observer可以实现比如无限加载,图片懒加载等,如何结合react组件做懒加载呢?实际不一定需要动态引入,可以通过setState就完成了,区别就是这些要懒加载的代码是否分包了。用动态引入的化,react就是使用Loadable装饰以下组件,这个组件不光可以用在路由上,用在其他地方也行,在render出来时会动态引入。(动态引入和按需加载还是不同,这俩概念我理解区别就是事先是否加载一部分代码)
css contain我的理解,能够让使用的元素在重新渲染时不影响整个页面,而时整个页面所有节点都跟着重新渲染。对于第三方的小饰件,始终使用contain: strict;是很好的习惯。它能建立起一个边界,产生一个新的根布局;保证了它和它的子元素的DOM变化不会触发父元素重新布局、渲染等

关于service的文章,先从缓存问题思考开始,它和缓存什么区别 《浏览器缓存、CacheStorage、Web Worker 与 Service Worker》
https://juejin.im/entry/5a7a9fcf5188257a5c605369

关于前端缓存该采用何种策略进行设置,可以参考这篇
《前端缓存最佳实践》https://www.jianshu.com/p/7826bf9e8efd
我的总结: (原则是尽量采用强缓存,减少客户端的请求)
对于index.html采用协商缓存,这样一有变动,用户就需要更新。对于index.html中使用的script,采用强制缓存,如果有变动就通过打包工具修改js的文件名或为js后面添加参数,这样名称变了前端自然就不能命中强缓存。
关于webpack中hash变量的值是整个配置一份,不管多少个入口,所以其中一个文件发生了变化,hash就变了。(当然某些文件你可以不用hash命名,看自己的配置)。chunkhash是和入口相关,如果单入口chunkhash和hash没有区别了,多入口,不同入口的chunkhash不同。contenthash一般用在分离的css上,这是为了css修改后,js不需要修改hash值。所以 分离的css不用chunkhash值,用contenthash,js用chunkhash。理解一下,hash就是webpack中的变量。

pwa。
在页面中通过navigator.serviceworker.register('xx.js')注册一个serviceworker,xx.js中的代码里监听install事件做出处理, 注册的时候它会被调用。
https://juejin.im/post/5ae2f82f6fb9a07acd4d761e
这个xx.js就是一个缓存处理文件,里面可以监听fetch事件,即浏览器所有的请求会先经过这个事件,监听到后根据url,从serviceworkder cache里直接拿出缓存的东西返回给用户。即拦截了请求



1.加一点,dns-prefech;

CDN 如何应用到一个已有的网站上,cname到底怎么回事,看这篇。
https://juejin.im/entry/587c7a63128fe10057faf224 《面向前端的 CDN 原理介绍》
我的理解: 如果买了cdn,就有了一个cdn服务商的服务器的cname(也是一个服务器域名地址,它对应cdn服务商的中心服务器),配置域名时加上这个cname。如果浏览器请求dns解析一个网址时获取到有cname记录,浏览器就又会向这个cname域名地址进行dns查询,返回一个最近的边缘节点,然后浏览器再向这个边缘节点地址发送http请求,访问网页。

2.CDN个人理解,CDN用来吧请求转移到最近的服务器或机房。负载均衡则是另一件事情,是通过反向代理等方式,在一个机房部署多台服务器,当其中一台服务器等负载超负荷的时候,将请求转移到该机房到其他服务器上。
3.LazyLoad Images
这条策略实际上并不一定能减少 HTTP请求数,但是却能在某些条件下或者页面刚加载时减少 HTTP请求数。对于图片而言,在页面刚加载的时候可以只加载第一屏,当用户继续往后滚屏的时候才加载后续的图片。这样一来,假如用户只对第一屏的内容感兴趣时,那剩余的图片请求就都节省了
https://www.cnblogs.com/flyromance/p/5042187.html 《滚动加载图片(懒加载)实现原理》
先不设置图片的src属性,通过接口获取相关属性,然后滚动到某处时再通过js设置src
4. css, js, 图片等静态资源部署到独立域名的服务上,减少cookie传输,注意强调独立域名。
5. js相关优化
1) 减少reflow、repaint
2) 事件代理,减少绑定
3)访问querySelectors、getElementByClassName、getElementByTagName返回的htmlCollection对象时,先转换成数组,访问的性能好些。比如通过
var arr = [].slice.call(collection)、或es6的var arr = Array.from(collection)
4) 避免使用eval和Function传入字符串的脚本。脚本引擎都需要将源代码转换成可执行代码。这是很消耗资源的操作
5)减少作用域链的查找。
比如一个函数中总是使用作用域外的一个变量,尤其还在循环中多次使用它。可以考虑在函数内创建一个局部变量,把该作用域外的变量赋值给他,然后使用该局部变量。
6) 对于对象的属性的访问,没有对直接变量或局部变量的访问来的快。如果对属性的访问的次数超过一次,可以先赋给某变量再访问该变量
7) 对于几乎不更新的资源比如图片,通过expire设置较长时间的缓存。对于可能更新的资源用
etag、lastModified保证资源能及时更新。对于图片不使用tag、lastModified,减少网络谐商的次数。
7. CDN的理解,还是看那篇文章,讲的非常好
http://blog.csdn.net/mahoking/article/details/51472697
(CDN通常部署在网络运营商的机房,这个不知道是不是,不太理解)
新开cdn相关文章学习
8. css和js动画比较
js和css都可能阻塞主线程,当进行layout或paint时就会阻塞。css动画使用transform会启用合成线程不会阻塞主线程。css动画通常用key-frame配置帧,结合animation或者transform,transform。 tranform可以使用rotate、translate、scale(缩放)、skew(扭曲)。
transform是用来做静止的变形的,不是直接用来动画的,但animation里可以用它。
transition和animation是用来做动画的。transtion,其实是一个过度效果,所以给定一个元素要变动到的大小或位置、时间、效果,在元素变化的时候就会带这个transition效果,可以理解为增加一个变动的效果。
animation用来制定一个动画的时间,动画可以用keyframe来定义,里面有各段的静态效果,用tranform或其他的css都可以定义。

一种说法是transform和opacity就能使用合成线程度。还一种说法,要主动使用gpu需要使用translate3D,即使没有3d位移,也可以设置为 0 0 0
https://www.cnblogs.com/rubylouvre/p/3471490.html
-webkit-transform:transition3d(0,0,0)或-webkit-transform:translateZ(0);

9. 立即执行函数的用途
在模块化的时候,通常使用闭包来构成私有变量。但模块是通过执行一个立即执行函数返回的。因为如果单纯定义一个函数构成闭包,比如
function xx () { var _name='moduleName'; return {getName: function() {return _name}}}, 而不立即执行的话,就会在全局下神明出一个函数, 污染了全局。立即执行函数的话,就不会产生这个函数,一次执行就用掉了。
希望函数仅执行一遍,不在被调用,用立即执行函数。比如单例
10. 判断是否为质数。
首先检查入参是Number类型,且为整数
type of n 为 'number' 且 Number.isInteger(n) 为true
然后0和1不是,2是。剩下的大于2的质数都肯定是奇数。质数只能被自身和1整除。
偶数不能被2整除,所以偶数当然也就不能被其他偶数整除。
然后一次循环i,求于看http://www.jb51.net/article/85690.htm

https://www.cnblogs.com/dll-ft/p/5854485.html

11. 域名解析的过程,首先是加载浏览器域名解析的缓存,通常缓存的大小和时长都不大。然后看本地host是否有配,有就走这个,然后才走本机网络配置都dns服务器,比如windows里以前网不好都时候就经常配,原因有两个,不通都dns服务器ping值不同,另一方面就是解析出的cdn不同,这都会影响访问网站的速度。然后还有,看这篇https://zhidao.baidu.com/question/437513187.html

12. w3c, ecma 是制定规范的。ECMA定义的是js的变量语法等基础的规范,而W3C是针对浏览器API提出的规范。而mdn是mozilla的开者社区发展而来的html js css 的wiki 文档。
《从ecma到w3c》
https://www.cnblogs.com/zhangjuke/p/7291998.html

13. 了解TPS和QPS的区别,以及当前公司该值是怎样的 (面试就说万级的就行)

14. 高效css
https://juejin.im/entry/58fef780570c350058f0d71f
比如 .ctn #light 这个选择器,实际不是先找所有的.ctn,再找#light,而是从右向左,先找到#light,还要去看看它到父亲节点里有没有.ctn到,这一步是无效到。所以限定约少越好,不要写 body ul li .title 这种,应该直接定义再.title上一个清晰到class,比如  list-title,直接使用.list-title 减少不必要的搜索
https://juejin.im/entry/577b9426c4c9710066a14b34
为减少层级,可以采用BEM命名,比如 ul_li--lighten
《为什么浏览器读取css规则的顺序是从右到左》
https://www.cnblogs.com/linfengtingyu1/p/3491529.html
简单都说浏览器使用解析出的css规则,结合解析出的dom树生成渲染树的。依次遍历解析出的dom树中的每个节点,然后在css规则中查找匹配的规则。比如拿出一个dom节点后知道它的类型是span, 如果按照从左向右的方式找,所有的css都要找一遍。而如果从右向左,只要看所有css规则中最后都限定项是不是span就可以了,如果不匹配,左边的规则都不需要再看了,减少了大量的查找。最后找到该dom节点应该有的样式,放到渲染树上去。无论从左导游,从右到左都得一条条css规则查,只是从右的话如果不匹配开始就知道了,不需要再向左查了。

CSS选择器的解析是从右向左解析的。若从左向右的匹配,发现不符合规则,需要进行回溯,会损失很多性能。若从右向左匹配,先找到所有的最右节点,对于每一个节点,向上寻找其父节点直到找到根元素或满足条件的匹配规则,则结束这个分支的遍历。两种匹配规则的性能差别很大,是因为从右向左的匹配在第一步就筛选掉了大量的不符合条件的最右节点(叶子节点),而从左向右的匹配规则的性能都浪费在了失败的查找上面。
而在 CSS 解析完毕后,需要将解析的结果与 DOM Tree 的内容一起进行分析建立一棵 Render Tree,最终用来进行绘图。在建立 Render Tree 时(WebKit 中的「Attachment」过程),浏览器就要为每个 DOM Tree 中的元素根据 CSS 的解析结果(Style Rules)来
确定生成怎样的 Render Tree。

疑问是从右向左时怎么一下找到符合的叶子节点,可能是dom parser的结果中已经像map一样列出了所有节点,可以快速查找到.上面说的很清楚,这个过程是在为每个dom节点确定添加什么样式时做的,所以实际上在遍历每个dom节点时,看下当前节点是处在那个css的最右边的选择器里,就可以排出掉许多不符合的css了,然后。。。

15.  z-index的理解。
首先知道,relative和absolute都是相对父元素都,如果父元素是relative或absolute,那里面子元素的relative和absolute都是相对父元素的(我以前写的这句话是错误的,看mdn关于position属性的讲解,relative是相对原有所在位置进行相对移动的,不是相对父元素移动的,它不会脱离文档流)。

<head>
  <style>
    #ctn {
      margin: 100px;
      width: 200px;
      height: 200px;
      background: lavender;
      position: relative;
    }
    #ctn span:nth-child(2) {
      position: relative; // relative下只会相对当前自己的位置移动,改用absolute才会相对ctn移动
      left: 2px;
      background: red;
    }
  </style>
</head>
<body>
  <div id="ctn">
    <span>a</span><span>b</span><span>c</span>
  </div>
</body>


《CSS并不简单--z-index引发的思考》
https://juejin.im/post/59267aada22b9d005718acc0
如果是在相同的层叠上下文,按照层叠水平的规则来显示元素
如果是在不同的层叠上下文中,先找到共同的祖先层叠上下文,然后比较共同层叠上下文下这个两个元素所在的局部层叠上下文的层叠水平。
也就是说一个元素即使z-index特别大,但如果它的父元素和另一个同级素之间相比层级低,那么你这个z-index特别大的子元素也不会在那个父元素同级元素之上

absolute相对body定位,但如果父元素是非static的,则相对父元素定位。
可以看一下mdn关于position的讲解https://developer.mozilla.org/zh-CN/docs/Web/CSS/position
还多了一个sticky
https://juejin.im/post/5cde75636fb9a07ef562048a
在滚动的父元素中就像fixed的表现一样,只不过如果整个页面滚动这个可滚动的父元素也滚动了,那么它也会随之不见,自己写个例子就能明白
用在滚动中,当页面滚动到特定位置时,这个元素就不再和页面一起滚动了,呈现fix的效果

16. 调用栈其实就是执行上下文栈,作用域链就是自由变量在当前作用域未定义,依次向外层的作用域查找变量

17. Foo的那个面试题,最后一题不需要记忆执行优先级,只需知道new时一定要有括号,即
new xx() 所以分解new new Foo().getName(),现分解最外层变为 new (new Foo().getName)(), 然后里面的new再分解, new ((new Foo()).getName)()

18. location.replace和location.href的区别与使用场景。
location.replace会去除当前页面的历史记录,替换为要跳转到的页面。结果就是在跳到的页面点返回时,如果用了location.replace就不会回到前面的页面,而是前前个页面。这有什么用呢?比如当前页面要跳到第三方的授权页面做授权,授权完成后会去到某个页面。如果希望授权完成后点返回不会再看到这个第三方授权页面,那个第三方授权页面就应该用location.replace进行结果页跳转。简单的说就是希望返回的时候不回到当前页面了。
也有window.history.replaceState函数用来替换栈顶数据,

19. 最后那个一堆fun链式调用的面试题,实际考的就是闭包。前两个就能总结出规律了,第三个直接套用规律即可。

20. 每一个构造函数都有prototype对象属性,所以创建一个function Dog(){}时,Dog会有一个prototype,Dog.prototype不是指向{}的,Dog.prototype.__proto__才指向{}。即指向了Object函数的原型,而Object.prototype.__proto__则为null。


补充:
1. position absolute relative
https://www.jianshu.com/p/de316853060e
结论:
1)relative:生成相对定位的元素,相对于其正常位置进行定位(以前说相对与父元素定位是不准确的,比如如果父元素有padding,那么这个relative的相对值就不是相对父元素的左顶点的,而是相对padding后的位置)
2)absolute:生成绝对定位的元素,相对于static定位以外的第一个父元素进行定位
关于z-index,看下层叠上下文的概念,即stacking context,https://www.jianshu.com/p/bc13ef3f324d
总结一下:
html元素本身就是一个层叠上下文,其他的只要满足position为relative、absolute、fixed且z-index值是不为auto的任意正负数字或者0,都构成新的层叠上下文。
(要注意因为z-index默认为auto,因此随意写一个postion aboslute不构成层叠上下文)
1) 前提:boxes属于同一个stacking context,并且z-index相同
** 规则:按照box对应的element在文档树的顺序,后者比前者更靠近用户(back-to-front)**
(属于同一个层叠上下文,个人理解,表示可以不是同一dom层级,只要在一个层叠上下文里就行)
2) 前提:boxes属于同一个stacking context,并且z-index不同**
** 规则:z-index属性值大的box更靠近用户**
(有z-index值,这个字元素本身应该也是个层叠上下文,不考虑这个)
3)前提:boxes属于不同的stacking context,并且stacking contexts没有祖孙/父子关系
** 规则:boxes会向上沿着父box进行搜索,直到父boxes属于同一个stacking context为止,然后比较父boxes的z-index属性值,z-index属性值大的box更靠近用户。**
(举例,如果一个有z-index的absolute的东西外还包裹着absolute的东西,就要注意了,因为还一层层叠上下文在外面)
4)前提:boxes属于不同的stacking context,并且stacking contexts为祖孙/父子关系
** 规则:属于子stacking context的box必定更靠近用户
5)前提:boxes属于相同的stacking context,并且两者都是non-positioned element。**
** 规则:float:left|right的元素必定更靠近用户**

2. promise不可暂停的理解
应该是说多个then,其中一个结果出来了,希望下一个暂停做不到。只要夜了一长串then,
都会执行。除非改为在then回调里递归调用,其实就是回调嵌套才能终止。
但如果是generator就可以停下来,比如yield出结果后,判断不需要再继续了,就终止。原因是generator是在外部处理,可控是否执行下一个异步。promise没办法。

3.domContentload事件是在domParser解析出dom树后就触发了,此时还没有渲染完成
OM文档加载的步骤为

1,解析HTML结构。
2,DOM树构建完成。//DOMContentLoaded
3,加载外部脚本和样式表文件。
4,解析并执行脚本代码。
5,加载图片等外部文件。
6,页面加载完毕。//load
在第2步,会触发DOMContentLoaded事件。在第6步,触发load事件。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics