基本信息
文件名称:JS常见面试题及答案(贴近实战版).docx
文件大小:28 KB
总页数:7 页
更新时间:2025-09-25
总字数:约4.29千字
文档摘要

JS常见面试题及答案(贴近实战版)

1.说下原型和原型链,实际开发中哪里用到?

答案:

原型是JS对象的“模板”,每个对象(除null)都有__proto__(隐式原型),指向其构造函数的prototype(显式原型)。原型链就是对象通过__proto__逐层向上查找属性的链条,直到Object.prototype.__proto__(值为null)。

实际用例:

实现继承:比如封装组件时,让自定义弹窗构造函数的prototype指向Object.create(基础弹窗.prototype),复用基础弹窗的“关闭”“显示”方法;

共享方法:数组的map、filter方法都存在Array.prototype上,所有数组实例通过原型链调用,避免每个数组都复制一份方法,节省内存。

注意:不要直接修改__proto__,性能差且不推荐,推荐用Object.create或class(ES6语法糖,本质还是原型)。

2.闭包是什么?用它的时候要注意什么?

答案:

闭包就是“函数嵌套函数,内层函数引用外层函数的变量,且内层函数被外部访问”,这时外层函数的变量不会被GC(垃圾回收)回收,能一直被内层函数使用。

实际例子:

写防抖函数时用闭包存定时器ID,避免每次调用防抖函数都重新创建定时器:

functiondebounce(fn,delay){

lettimer=null;//闭包保存timer,不会被回收

returnfunction(){

clearTimeout(timer);

timer=setTimeout(()=fn.apply(this,arguments),delay);

};

}

constinputDebounce=debounce(handleInput,300);

注意点:

内存泄漏:如果闭包引用的变量是大对象(比如DOM元素),且闭包一直存在(比如没清除的定时器、全局变量引用),会导致内存占着不放,要及时销毁(比如清除定时器、解除全局引用);

不要过度使用:比如循环里创建闭包(早期var变量提升问题),现在用let块级作用域能避免,但仍需注意没必要的闭包会增加内存开销。

3.this指向怎么判断?举几个常见场景

答案:

this指向“调用函数的对象”,不是定义时的对象,核心看“谁调用”,分5种常见场景:

全局调用(非严格模式):this指向window(浏览器)/global(Node),严格模式下是undefined;

例:functionfn(){console.log(this)}fn()→非严格模式输出window。

对象方法调用:this指向调用方法的对象;

例:constobj={name:a,say(){console.log(this.name)}}obj.say()→输出a。

call/apply/bind:this指向第一个参数(传null/undefined时,非严格模式指向window);

例:obj.say.call({name:b})→输出b。

构造函数(new):this指向新创建的实例;

例:functionPerson(name){this.name=name}constp=newPerson(c)→p.name是c。

箭头函数:没有自己的this,继承外层“非箭头函数”的this(跟定义位置有关,不是调用位置);

例:constobj={fn:()={console.log(this)}}obj.fn()→输出window(因为fn是箭头函数,继承外层全局的this)。

实际坑点:Vue组件methods里的this指向组件实例,就是因为Vue内部用call把this绑定到了实例上。

4.0.1+0.2为什么不等于0.3?怎么解决?

答案:

因为JS用“二进制浮点数”存储数字,而0.1和0.2转成二进制后是无限循环的,浏览器会截取前53位(JS能精确表示的最大位数),导致精度丢失,所以相加后是0.30000000000000004,不是0.3。

解决方法(实际开发常用):

转成整数计算:比如涉及金额时,把元转成分(乘以100),计算后再转回去;

例:(0.1*10+0.2*10)/10=0.3。

用toFixed(注意四舍五入坑):需要先判断小数位数,比如(0.1+0.2).toFixed(1)→输出0.3(但1.335.toFi