问题1 web beacon和gif埋点比优点
web beacon(网络信标)Navigator.sendBeacon(url,data)
相较于图片的src,这种方式的更有优势:
- 不会和主要业务代码抢占资源,而是在浏览器空闲时去做发送;
- 并且在页面卸载时也能保证请求成功发送,不阻塞页面刷新和跳转;
问题2 JS原生错误
除了try catch中捕获住的错误,我们还需要上报没有被捕获住的错误——通过error事件和unhandledrejection事件去监听。
error
error事件是用来监听DOM操作错误DOMException和JS错误告警的,具体来说,JS错误分为下面8类:
- InternalError: 内部错误,比如如递归爆栈;
- RangeError: 范围错误,比如new Array(-1);
- EvalError: 使用eval()时错误;
- ReferenceError: 引用错误,比如使用未定义变量;
- SyntaxError: 语法错误,比如var a = ;
- TypeError: 类型错误,比如[1,2].split('.');
- URIError: 给 encodeURI或 decodeURl()传递的参数无效,比如decodeURI('%2')
- Error: 上面7种错误的基类,通常是开发者抛出
unhandledrejection
Promise内部抛出的错误是无法被error捕获到的,这时需要用unhandledrejection事件。
问题3 CMS和ESM区别
CMS
- 对于基本数据类型,属于复制。即会被模块缓存。同时,在另一个模块可以对该模块输出的变量重新赋值。
- 对于复杂数据类型,属于浅拷贝。
- 当使用require命令加载某个模块时,就会运行整个模块的代码。
- 当使用require命令加载同一个模块时,不会再执行该模块,而是取到缓存之中的值。也就是说,CommonJS模块无论加载多少次,都只会在第一次加载时运行一次,以后再加载,就返回第一次运行的结果,除非手动清除系统缓存。
- 循环加载时,属于加载时执行。即脚本代码在require的时候,就会全部执行。一旦出现某个模块被"循环加载",就只输出已经执行的部分,还未执行的部分不会输出。
ESM
- ES6模块中的值属于【动态只读引用】。
- 对于只读来说,即不允许修改引入变量的值,import的变量是只读的,不论是基本数据类型还是复杂数据类型。当模块遇到import命令时,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。
- 对于动态来说,原始值发生变化,import加载的值也会发生变化。不论是基本数据类型还是复杂数据类型。
- 循环加载时,ES6模块是动态引用。只要两个模块之间存在某个引用,代码就能够执行。
问题4 Git操作
git reflog
可以查看所有分支的所有操作记录(包括已经被删除的 commit 记录和 reset 的操作)
$ git reflog
8c5356b (HEAD -> lyf) HEAD@{0}: reset: moving to 8c5356b
1bc7bfe HEAD@{1}: commit: 7777
62fd481 HEAD@{2}: reset: moving to 62fd481db485264c8d94656abe2897a194ce1237
8c5356b (HEAD -> lyf) HEAD@{3}: commit: 6666
8d0669f HEAD@{4}: commit: 5555
git rebase
- git rebase 的目的也是将一个分支的更改并入到另外一个分支中去。
- rebase 会把你当前分支的 commit 放到公共分支的最后面,所以叫变基,即变换分支的参考基点。就好像你从公共分支又重新拉出来这个分支一样。
- 而 merge 会把公共分支和你当前的 commit 合并在一起,形成一个新的 commit 提交
- git merge 优点是分支代码合并后不破坏原分支代码的提交记录,缺点是会产生额外的提交记录并进行两条分支的合并
- git rebase 优点是可以将对象分支的提交记录续到目标分支上,形成线性提交历史记录,review时更加直观
- 不能在一个共享的分支上进行git rebase操作。因为往后放的这些 commit 都是新的,这样其他从这个公共分支拉出去的人,都需要再重新merge,导致提交记录混乱
- 合代码到公共分支上时用git merge
- 合代码到个人分支时用git rebase,形成线性提交历史记录
git cherry-pick
cherry-pick指令移植提交的实质是:先将需要移植的提交复制一份,再拼接到master分支上,简称先复制,再拼接;
git cherry-pick 的使用场景就是将一个分支中的部分的提交合并到其他分支。想要合并某些内容,但又不想包含整个分支。这时用cherry-pick来合并单次提交
git cherry-pick <hashA> <hashB> // 合并两个提交
git cherry-pick <hashA>..<hashB> // 合并从A到B两个提交中到所有提交,但不包含A
git cherry-pick <hashA>^..<hashB> // 合并从A到B两个提交中到所有提交,包含A
问题5 async实现原理
将 Generator 函数和自动执行器,包装在一个函数里
function spawn(genF) {
return new Promise(function(resolve, reject) {
const gen = genF();
function step(nextF) {
let next;
try {
next = nextF();
} catch (e) {
return reject(e);
}
if (next.done) {
return resolve(next.value);
}
Promise.resolve(next.value).then(
function(v) {
step(function() {
return gen.next(v);
});
},
function(e) {
step(function() {
return gen.throw(e);
});
}
);
}
step(function() {
return gen.next(undefined);
});
});
}
问题6 react-router原理
能够实现history路由跳转不刷新页面得益与H5提供的pushState(),replaceState()等方法,这些方法都是也可以改变路由状态(路径),但不作页面跳转
react-router-dom是react的路由,它帮助我们在项目中实现单页面应用,它提供给我们两种路由一种基于hash段实现的HashRouter,一种基于H5Api实现的BrowserRouter。
BrowserRouter组件主要做的是将当前的路径往下传,并监听popstate
事件,所以我们要用Consumer, Provider跨组件通信
- Router组件主要做的是通过BrowserRouter传过来的当前值,与Route通过props传进来的path对比,然后决定是否执行props传进来的render函数
- Link组件主要做的是,拿到prop,传进来的to,通过PushState()改变路由状态,然后拿到BrowserRouter传过来的onChangeView手动刷新视图
hashRouter监听hashchange
。其余的和BrowserRouter差不多
问题7 解决高度坍塌
父元素的高度,都是由内部未浮动子元素的高度撑起的。
子元素浮动,还会对父元素造成影响。
如果子元素浮动起来,就不占用普通文档流的位置。父元素高度
就会失去支撑,也称为高度坍塌。
即使有部分元素留在普通文档流布局中支撑着父元素,如果浮动
起来的元素高度高于留下的元素。那么浮动元素的高度会超出父
元素边框,用户体验同样不好!
方案1
为父元素设置overflow:hidden
属性。
原理: CSS中的overflow :hidden
属性会强制要求父元素必须包裹住所有内部浮动的元素,以及所有元素的margin范围。
缺点:如果刚好父元素有些超范围的子元素内容需要显示(比如,个别position定位的子菜单项),不想隐藏,就会发生冲突。
方案2
在父元素内的结尾追加一个空子元素(块级元素),并设置空子元素清除浮动影响clear:both
原理: 利用clear:both
属性和父元素必须包含非浮动的元素两个原理
缺点: 无端多出一个无意义的看不见的空元素,影响选择器和查找元素。
方案3
方案三: 设置父元素也浮动。
原理: 浮动属性也会强制父元素扩大到包含所有浮动的内部元素。
缺点:会产生新的浮动影响。比如,父元素浮动,导致父元素之后平级的页脚div上移,被父元素挡住了
解决: 设置父元素之后的平级元素清除浮动clear:both
方案4
完美解决: 为父元素末尾伪元素设置clear:both。
优点: 既不会影响显示隐藏,又不会影响查找元素,又不会产生新的浮动问题
问题:个别浏览器,display:table
,可能带默认高度
保险起见: 再加一个属性height:0px
父元素::after{ content:""; display:table; clear:both; height:0 }
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。