前端面试题

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指向复原

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值