JavaScript面试题
1.闭包
闭包是什么?
闭包一个函数和词法环境的引用捆绑在一起,这样的组合就是闭包(closure)。
(一个函数A,return出去函数B,被return出去的函数B,能够在外部访问函数A内部的变量)
代码演示:
function A(){
let a = 1;
return function B(){
return a
}
}
console.log(A()())
闭包形成的原理:作用域链,当前作用域可以访问上级作用域中的变量。
优点:1.内部函数B可以访问到外部函数A的局部变量
2.能够让函数作用域中的变量在函数执行结束之后不被销毁
缺点:1.变量会保存在内存中,不被垃圾回收,造成内存损耗问题。
解决方法:把闭包的函数设置为null
2.内存泄露。
2.js的数据类型有哪些,区别是什么?
基本数据类型:Number、String、Boolean、BigInt、Symbol、Null、Undefined
引用数据类型:Object(普通对象,数组,正则,日期,Math数学函数...)
区别:内存中的存储方式不同。
1.基本数据类型:直接存储在栈中的简单数据段,占据空间小,属于被频繁使用的数据。
2.引用数据类型:存储在堆内存中,在栈中存储了该堆的指针,占据空间大。
注:BigInt和Symbol是ES6所提出来的
3.防抖与节流区别?
共同点:都是为了减少函数的执行次数,提升性能。
1.防抖:把多次函数执行,合并成一次执行。
给定一个间隔时间,当两次函数执行的间隔时间大于了给定的间隔时间,就执行一次函数。
使用场景:商品搜索、数据实时查询...
代码演示:
function debounce(fn, delay){
let timer = null;
return function(){
if (timer) clearTimeout(timer)
timer = setTimeout(function(){
fn.apply(this, [...arguments])
},delay)
}
}
2.节流:减少函数执行的频率。
规定一个单位时间,在单位时间内触发一个事件回调,触发时超过间隔时间则执行,否则不执行。
使用场景:比如我们的移动端,在一段时间内成百上千次的执行同一个方法。
代码演示:
function throttle(fn, gapTime){
let lastTime = null;
return function(){
let nowTime = new Date();
if(nowTime-lastTime>gapTime && !lastTime){
fn.apply(this, arguments);
lastTime = nowTime;
}
}
}
4.JavaScript的浅拷贝和深拷贝
注意:深浅拷贝只针对引用类型(Object),基本类型这种就是普通的赋值操作不是拷贝
共同点:复制
判断深浅拷贝的方法:是否是同一个地址
1.浅拷贝:只是复制了对应的地址,而未复制真正的值
方法1:
var arr1 = ['a','b','c','d'];
var arr2 = arr1;
方法2:
var obj1 = {a:1,b:2}
var obj2 = Object.assign(obj1);
2.深拷贝:是复制真正的值 (不同引用)
方法1:利用JSON进行深拷贝
var obj3 = { a:1,b:2 }
var obj4 = JSON.parse(JSON.stringify(obj3));
方法2:利用递归的方法进行深拷贝
function copyObj(obj){
var newObj = obj.constructor === Array ? []:{};
for( let keys in obj ){
if(obj.hasOwnProperty(keys)){
if( obj[keys] && typeof obj[keys] === "object" ){
newObj[keys] = copyObj(obj[keys])
}else{
newObj[keys] = obj[keys]
}
}
}
return newObj
}
5. == 与 === 的区别
1.==是非严格意义上的相等:比较的是值相等
2.===是严格意义上的相等:及比较数据类型同时也比较值
6. map与forEach的区别?
1.forEach: 可以通过在函数体内部使用索引修改数组元素,默认无返回值,其结果是undefined。
代码演示:
array.forEach(function(currentValue, index, arr), thisValue)
2.map: 不管数组元素是undefined或者null,都会return出一个length和原数组一致的新数组,有返回值。用法和forEach基本相同。
7.this指向
1.this总是指向函数的直接调用者。
2.如果有new关键字,this指向new出来的对象。
3.在事件中,this指向触发这个事件的对象。
8.原型以及原型链
1.谁有原型
函数拥有:prototype
对象拥有:__proto__
2.对象查找属性或者方法的顺序
先在对象本身查找 --> 构造函数中查找 --> 对象的原型 --> 构造函数的原型中 --> 当前原型的原型中查找 --> ... --> null(侧面说明了原型链)
3.原型链:就是把原型串联起来