0
点赞
收藏
分享

微信扫一扫

前端经典面试题汇总


css 重绘与回流

重绘:当节点需要更改外观而不会影响布局。
回流:DOM结构的修改引发DOM几何尺寸变化的时候,发生回流。
常见的几何属性:有width、height、padding、margin、left、top、border 或者是DOM节点发生增减移动。

减少重绘和回流的方法:
使用css3新增属性:translate 替代top等方向值。
避免使用style,而是采用class。

箭头函数和普通函数的区别?

普通函数this:

this总是代表它的直接调用者。
在默认情况下,没找到直接调用者,this指的是window。
在严格模式下,没有直接调用者的函数中的this是undefined。
使用call,apply,bind绑定,this指的是绑定的对象。

箭头函数this :

在使用=> 定义函数的时候,this指的是定义时所在的对象,而不是使用时所在的对象;

不能用于构造函数,即不能使用new命令,否则会抛出错误;
不能使用arguments对象;
不能使用yield 命令。

let var const 区别

var 没有块级作用域,支持变量提升
let 有块级作用域,不支持变量提升。不允许重复声明,有暂时性死区。不能通过window.变量名进行访问。
const

实现一个new的伪代码

实现步骤:
1. 创建一个对象
2. 连接原型
3. 绑定this
4. 返回该对象

function _new(){
let obj = new Object();
let Con = [].shift.call(arguments);
obj.__proto__ = Con.apply(obj,arguments);
let result = Con.apply(obj,arguments);
return typeof result == 'object' ? result : obj;
}

实现防抖函数(debouce)

原理:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
防抖和节流本质是不一样的。防抖是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。

像百度搜索,就应该用防抖,当我连续不断输入时,不会发送请求;当我一段时间内不输入了,才会发送一次请求;如果小于这段时间继续输入的话,时间会重新计算,也不会发送请求。

手写简化版:

// func是用户传入需要防抖的函数
// wait是等待时间
const debouce = (func,wait = 50) => {
// 缓存一个定时器id
let timer = 0
// 这里返回的函数是每次用户实际调用的防抖函数
// 如果已经设定过定时器了就清空上一次的定时器
// 开启一个新的定时器,延迟执行用户传入的方法
return function(...args){
if(timer) clearTimeout(timer)
timer = setTimeout(()=>{
func,apply(this,args)
},wait)
}
}

使用场景:

按钮提交场景:防止多次提交按钮,只执行最后提交的一次。
服务端验证场景:表单验证需要服务端配合,只执行一次连续的输入事件的最后一次,还有搜索联想词功能类似。

实现节流函数(throttle)

原理:规定在一个单位时间内,只能触发一次函数,如果这个单位内触发多次函数,只有一次生效。
例,(连续不断都需要调用时间,设一时间间隔),像dom的拖拽,如果用防抖的话,就会出现卡顿的感觉,因为只在停止的时候执行了一次,这个时候就应该用节流,在一定时间内多次执行,会流畅很多。

手写简版:

// func是用户传入需要防抖的函数
// wait是等待时间
const throttle = (func,wait = 50) => {
// 上一次执行该函数的时间
let lastTime = 0
return function(...args){
// 当前时间
let now = +new Date()
// 将当前时间和上一次执行函数时间对比
// 如果差值大于设置的等待时间就执行函数
if(now - lastTime > wait){
lastTime = now
func.apply(this,args)
}
}
}
setInterval(
throttle(()=>{
console.log(1)
},500),
1
)

适用场景:

  • 拖拽场景:固定时间内只执行一次,防止超高频次触发位置变动。
  • 缩放场景:监控浏览器resize。
  • 动画场景:避免短时间内多次触发动画引起性能问题。

实现一个call

call 做了什么:

  • 将函数设为对象属性
  • 执行&删除这个函数
  • 指定this到函数并传入给定参数执行函数
  • 如果不传入参数,默认指向为window

// 模拟call bar.mycall(null)
// 实现一个call 方法:
// 原理: 利用context.xxx = self obj.xxx = func --> obj.xx()
Function.prototype.myCall = function(context = window,..args){
// this --> func context--> obj args --> 传递过来的参数
// 在context 上加一个唯一值不影响context上的属性
let key = Symbol('key')
context[key] = this; // context 为调用的上下文,this此处为函数,将这个函数作为context的方法
// let args = [...arguments].slice(1) // 第一个参数为obj所以删除,伪数组转为数组。
let result = context[key](...args);
delete context[key]; // 不删除会导致context 属性越来越多
return result;
}

用法:

// 用法: f.call(obj,args1)
function f(a,b){
console.log(a + b)
console.log(this.name)
}
let obj = {
name: 1
}
f.myCall(obj,1,2) // 如果不传入参数,则this指向window

实现apply方法

思路:利用this的上下文特性。


举报

相关推荐

0 条评论