1.BFC Block Formattingcontexts -块级格式化上下文
IFC-内敛格式化上下文
GFC-网格布局格式化上下文
FFC-弹性格式化上下文
核心概念:
BFC是一块独立的渲染区域 或者说 一个独立的容器
BFC中的元素如何布局也不会影响外界 反之亦然
用途:
1.清除浮动(高度塌陷,左浮动右不浮动重叠问题)
注:(左浮动右不浮动重叠问题)
2.解决外边距重叠问题
触发方式:
- 浮动元素:float除none以外的值
- 绝对定位元素:position(absolute、fixed)
- display为inline-block、table-cells、flex、inline-flex、table-caption
- overflow除了visible以外的值(hidden、auto、scroll)
满足其一即可
2.for和forEach的区别
1.循环和迭代
for主要对象为array,forach主要面向所有具备迭代属性的迭代器
2.打断
for中 return break continue 生效
forEach中不能使用这三个
打断迭代可以try{}catch{}
3.大小写转换
将"ni Hao A 我叫Yang qaq"字符串中的英文大小写转换
let str="NI hAO a 我叫yANG QAQ" let res =str.split('').map(item=>{ return item.toUpperCase() == item?item.toLowerCase() : item.toUpperCase() }).join('') console.log(res) //ni Hao A 我叫Yang qaq
4.call apply的性能高低
听说jQuery的源码中有句注释:
call方法的性能高于apply
虽然我没学过jQuery
所以我决定自己验证一下:
使用js自带的
console.time(name)
...
console.timeout(name)
可以得到中间部分代码花费时间
测试结果:数据量太少,没有测出来
还是看看大佬们的说法吧
结论:大型工程尽量用call,能提高一点性能是一点性能
call方法的性能高于apply
5.路由懒加载的简单原理
未进行路由懒加载打包时
会把组件注册打包到同一个js文件 一个文件注册几十个组件 首屏加载太慢
使用路由懒加载打包时
会分包打包 把组件注册打包到不同的js文件 使用到哪个组件再注册哪个
6.手写call apply bind
原理: 利用隐式绑定this实现显示绑定
实现call方法:
简易版本:
function fn(arg1,arg2){ console.log('fn执行了',this.name,arg1,arg2); return '我是返回值' } let thisarg={ name: 'Yang' } //实现myCall function myCall(fn,thisarg,...args){ thisarg.fnName = fn //核心:利用隐式绑定 const result= thisarg.fnName(...args) //执行隐式绑定函数并返回结果 delete thisarg.fn //销毁隐式绑定函数 return result //返回值 } let result=myCall(fn,thisarg,'1',"2") //fn执行了 Yang 1 2 console.log(result); //我是返回值
两个缺陷:
- 若已经有 thisarg.fn 存在,则起名冲突
- 与原生fn.call(thisarg , ...args)的形式不同
进阶版本:
使用Symbol创建独一无二的隐式绑定this函数
function myCall(fn,thisarg,...args){ let fnName=Symbol() thisarg[fnName]=fn const result = thisarg[fnName](...args) delete thisarg[fnName] return result }
究极版本:
在 Function原型 添加 myCall方法 并完成 fn.myCall( )形式的调用
Function.prototype.myCall=function(thisarg,...args){ let fnName=Symbol() thisarg[fnName]=this //this指向被调用的函数fn const result = thisarg[fnName](...args) delete thisarg[fnName] return result } let result=qaq.myCall(thisarg,'1',"2") //第一个参数用this代替 //fn执行了 Yang 1 2 console.log(result); //我是返回值
实现apply方法:
传入的参数必须为数组,然后使用扩展运算符拆分出来
Function.prototype.myApply=function(thisarg,args){ let fnName=Symbol() thisarg[fnName]=this //this指向被调用的函数fn const result = thisarg[fnName](...args) delete thisarg[fnName] return result }
实现bind方法:
与call方法不同
1.返回值为改变this指向后的可调用函数
2.改变this指向时传入的参数依然保留
3.函数被new时,this指向回到最初
Function.prototype.myBind=function(thisarg,...args1){ let fn= this if(new.target == undefined) { return function(...args2){ let fnName=Symbol() thisarg[fnName]=fn const result = thisarg[fnName](...args1,...args2) delete thisarg[fnName] return result } } else{ return fn() } } ------------------------------------------------------------- function say(arg1,arg2){ console.log(this.age,arg1,arg2) } let person={ age:3 } let bindSay = say.bind(person,"我叫",'Yang') bindSay() //3 '我叫' 'Yang' new bindSay() //undefined '我叫' 'Yang' //调用了new this指向复原