2023-JS面试题

225 阅读2分钟

原型和原型链

  1. 原型:每一个函数都有一个属性,这个属性叫prototype。prototype这个属性的值是一个对象,这个对象里面有一个Constructor属性,指向构造函数本身。
  2. 原型链:原型链的连接点是一个__proto__ 他是实例对象的属性。步骤:查找自身实例对象、查找实例对象的prototype、查找Object的prototype.Object的prototype就是原型链的顶端。
                Object.prototype.name = 555
		function Parent() {
			this.name = 33
		}
		Parent.prototype.name = 44
		function Child() {
			this.name=11
		}
		Child.prototype = {
			name: 222,
			__proto: new Parent()
		}
		let child = new Child()

数据类型

  1. 原型类型有七中:null、undefined、number、string、boolean、Symbol、Bigint。
  2. 引用数据类型:对象。

隐式转换

  1. Number([].valueOf().toString()) = 0 Number(!Boolean([])) = 0 所以返回true
  2. [] == 0 true Number([].valueOf().toString())
  3. ![] == 0 true !Boolean([]) === 0
  4. [] == ![] true [].valueOf().toString() = '' !Boolean([]) = false '' == false Number('') == Number(false) => true
  5. 关系运算符 将其他数据转换成数字
  6. 逻辑非 将其他数据类型用Boolean()转换 逻辑非:(![])
  7. Boolean返回false的值有:NaN undefined null '' false

什么是闭包

  1. 有权访问另外一个函数中局部变量的函数叫做闭包
  2. 适用场景:回调函数、自调用函数、防抖、节流等
  3. 闭包内存泄漏:

防抖节流

  1. 防抖:一定时间内没有触发事件,事件才会执行一次。一定时间内触发多次会重新延迟,执行最后一次
  2. 节流:若一个函数在一段时间内持续高频触发,节流后将使得该函数在这段时间内每隔固定时间才执行一次
  3. 总结:防抖和节流的区别在于,是否有定时任务、防抖是清除定时器重新执行,节流是return false 等待定时器自动清除;
/* 普通版本 */
function debounce(fn, wait) {
    let timer = null
    return function() {
        timer && clearInterval(timer)
        timer = setTimeout(() => fn.apply(null, arguments), wait)
    }
}

/* 立即执行 */
function debounce(fn, wait, immediate) {
    let timer = null
    return function() {
        timer && clearInterval(timer)
        if (immediate) {
            fn.apply(this, arguments)
            immediate = false
        }
        timer = setTimeout(() => {
            fn.apply(this, arguments)
            immediate = true
        }, wait)

    }
}

/* 合并版本 */
function debounce(fn, wait, immediate) {
    let timer = null
    return function() {
        timer && clearInterval(timer)
        if(immediate) {
            let callNow = !timer;
            timer = setTimeout(() => {
                timer = null;
                immediate = true
            }, wait)
            if(callNow) {
                fn.apply(this, arguments)
                immediate = false
            }
        } else {
            timer = setTimeout(() => {
                fn.apply(this, arguments)
                immediate = true
                timer = null;
            }, wait)
        }
    }
}

2.节流:

/* 非立即执行 */
function throttle(fn, wait) {
    let flag = true
    return function() {
        if(flag) {
            flag = false
            setTimeout(() => { 
                fn.apply(this, arguments);
                flag = true
            }, wait)
        }
    }
}

/* 立即执行 */
function throttle(fn, wait) {
    let flag = true
    return function() {
        if(flag) {
            flag = false;
            fn.apply(this, arguments)
            setTimeout(() => {
                flag = true
            }, wait)
        }
    }
}