2023年度-JS高频面试题
前言
2023年了, 今年形势确实不好, 各种的面试等结果, 各种未回复, 博主一到无聊的时候,就会写一写博客, 就顺着这个就业问题出一篇面试题总结吧, 虽然网上的面试题也有很多, 但是也实在不知道该写一些什么, 我js比较差, 也想为自己整理整理.
-- 博主找了将近一个月工作了, 所以找不到工作就很郁闷, 无聊, 我也是普通人, 大多数人学历, 经验几乎都差不多. -- 学历低, 非本专业入行, 专业入行毫无经验甚至刚出培训班直接包3年假简历 -- 再加上近几年学计算机的人越来越多, 全国培训班已经输送200w+(老数据), 计算机就业问题已经形成不可逆转的死局. -- 结果就是几十几百个人抢一个工作岗位(你入职的几率跟大海捞针没区别). -- 找不到工作的比比皆是, 迫使某些同学狠心转行, 不过不能说转行是错误的, 我倒是觉得转行就目前形势而言是一种解脱. -- 在这里也劝各位想辞职的同学不要辞职, 如果你是1,2本, 硕士, 研究生, 你当我没说过. -- 反正现在的形势就是: 现在的初级要求就是以前的中级, 现在的中级就是以前的高级, 一眼望去3-5, 5-10, 本科, 本科以上. -- 当然, 我也不是制造恐慌, 只是聊一聊当前真实形式, 也不是说工作就一定找不到, 只是很难找. -- 也送各位正在努力找工作的同学们一句话: 拥有什么心态,就会看到什么风景, 祝大家前程似锦!
JS面试题(一定要认真看哦)
1. 什么是内存泄漏?
- 什么是内存泄漏?哪些方式会造成内存泄漏? 内存泄漏解决方式?
内存泄漏: 内存泄漏也称之为"存储泄露", 在空间中分配的内存, 在js进程结束后未被释放, 结果导致一直占用内存单元,直到程序结束 (说白了就是该内存空间使用完毕后未被回收). 造成内存泄漏的方式: 1.setTimeOut的第一个参数为字符串代码而并非函数的时候, 就会引发内存泄漏 2.闭包(函数嵌套函数),控制台日志,循环(在两个对象彼此引用且彼此保留时,就会产生一个循环) 3.再多我也不会了 内存泄漏解决方式: 1. global variables: 对未声明的变量的引用在全局对象内创建一个新变量,在浏览器中,全局对象就是window. 1.1):创建意外的全局变量. function foo(arg) { bar = 'text'; // 等同于 window.bar = 'text' } 1.2): 可以在JavaScript文件开头添加 "use strict"(严格模式), 在严格模式下解析JavaScript可以防止意外的全局变量. 1.3): 在使用完成后, 对其赋值为 null 或者重新分配.
2. 数组常用方法有哪些?
数组: ------------------------------------------------------------------------ 1.array.forEach((item) => {}) // forEach 循环遍历数组 ------------------------------------------------------------------------ 2.array.map(function(currentValue, index, arr), thisIndex) currentValue: 必须.当前元素的的值. index: 可选.当前元素的索引. arr: 可选.当前元素属于的数组对象. map()方法定义在JavaScript的Array中,它返回一个新的数组,新返回数组中的每个元素为原始数组的每一个元素分别调用map中的回调函数处理后的值。 例子: var arr1 = [1,2,3]; var newArr = arr1.map(function(value, index) { return value + 1; // newArr = [2,3,4] }) ------------------------------------------------------------------------ 3.array.concat(arr,arr2,arr3); //拼接数组,返回一个新的数组,对其他数组不产生影响 let arr = [...arr1, ...arr2, ...arr3] // 展开符拼接 ------------------------------------------------------------------------ 4.array.every(function(val, index) {}, arg) 数组的every方法: 检测每个元素是否都符合条件, 如果有一个不符合条件就是false 第二个参数用于替换回调函数中的this 例子: <script> let obj = {name: 's'}; let arr = [10,11,12,13]; let a = arr.every(function(val,index) { console.log(this); // window => obj return val >= 10; },obj) console.log(a); // true </script> ------------------------------------------------------------------------ 5.array.filter(function(val, index) {}) // 检查元素,符合条件的元素构成一个新的数组,不会改变原数组 例子: <script> let array = [2,3,4] let a = array.filter(function(val) { return val > 2; }) console.log(a); // a = [3,4] </script> ------------------------------------------------------------------------ 6.array.some(function(val, index) {}) // 检测数组里有没有符合条件的元素, 有一个就返回为true 可看every方法 ------------------------------------------------------------------------ 7.array.splice(index, num, arg1, arg2...) // splice方法从指定的元素删除元素或添加元素,会改变原来的数组 第一个参数: 从第几个开始删除 第二个参数: 删除几个 后面的参数: 添加的元素 例子: <script> let array = [2,3,4] let a = array.splice(0, 1, '新增1', '新增2') console.log(array); // ['新增1', '新增2', 3, 4] </script> ------------------------------------------------------------------------ 8.array.join(string) // 将数组所有元素再转成一个字符串, 返回一个新字符串 例子: <script> let array = [2,3,4] let as = array.join("-"); console.log(as); // 2-3-4 </script> ------------------------------------------------------------------------ 9.array.shift(), array.unshift(arg1,arg2...) // shift方法删除数组的第一个元素, unshift方法在数组的开头添加一个或多个元素 ------------------------------------------------------------------------ 10.array.toString() // 将数组元素转化为字符串并返回这个字符串 例子: <script> let array = [2,3,4] let as = array.toString(); console.log(as); // 2,3,4 </script> ------------------------------------------------------------------------ 11.let arr = array.pop() // 删除的是数组的最后一个元素,返回的是删除的那个元素, 修改原数组 ------------------------------------------------------------------------ 12.let arr = array.push(arg) // 往数组末尾新增元素, 修改原数组 ------------------------------------------------------------------------
3. 介绍一下原型以及原型链?
原型: 每个对象都会在内部初始化一个属性, 就是prototype(原型) 原型链: 当访问一个对象的某个属性时,会现在这个对象本身的属性上去查找,如果找不到,会去他的 __proto__ 隐式原型上查找 即它的构造函数的prototype, 如果还没找到就会再在构造函数的 prototype 的 __proto__ 中查找 这样一层一层向上查找就形成了一种链式结构,统称为"原型链"
4. 知不知道防抖和节流?
防抖: 一定周期内多次执行只能执行一次 节流: 一定周期内多次执行只能执行最后一次
5. 可以说一下this指向的问题吗?
'谁调用this就指向谁' 在js中, this的意思为: 这个,当前, 是一个指针型变量, 它动态指向当前函数的运行环境; 在不同的场景中调用同一个函数,this的指向也可能会发生变化,但是它永远指向其所在函数的真实调用者; 如果没有调用者,就指向全局对象window; // 在全局作用域下, this始终指向全局对象window, 无论是否是严格模式 console.log(this); window.console.log(this); // 当作为对象的方法被调用的时候, this指向当前对象 let obj = { name: '哈哈', skill: function() { name: '嘻嘻', console.log('对象this指针' + this.name); // this === skill } } obj.skill(); // 普通函数 function fn() { console.log(this); // 普通函数中this指向顶级对象window } // 定时器 setTimeOut(() => { console.log(this); // 定时器中的this永远指向window }) // 事件 document.querySelector('div').onclick=function() { console.log(this); // 事件当中this指向当前绑定的元素 } // 构造函数 function Fn(name) { // 在构造函数当中 this指向 被实例出来的对象 this.name = name console.log(this); } let name = new Fn('si');
6. 讲讲LocalStorage,SessionStorage,Cookie的区别(经典必问)
// cookie: 只有4kb左右, 一般用来保存登录信息 // localstorage 和 sessionstorage 可以达到 5M或更大, 用来本地存储 // sessionstorage 仅在窗口关闭前有效 // localstorage 始终有效 // cookie 只在设置的cookie过期时间内有效 //localstorage存取数据 let obj = [{ name: '张三', age: 14 },{ name: '李四', age: 15 }] // localStorage存数据 window.localStorage.setItem('localStorageObj', JSON.stringify(obj)); // localStorage取数据 let getLocalStorageData = JSON.parse(localStorage.getItem('localStorageObj')); getLocalStorageData.map(item => { console.log(item); })
7. 什么是闭包?
// 闭包: 一个函数内的另一个函数可以调用外部函数的变量, 称之为闭包 function fn1() { let a = 100; function fn2() { console.log(a + 1); } fn2(); } fn1();
8. 如何实现深拷贝浅拷贝?
浅拷贝: 1. Object.assign(target, obj); 2. 扩展运算符 let target = {...obj}; // 自己创建一个新的对象,来接受你要重新复制或引用的对象值。如果对象属性是基本的数据类型,复制的就是基本类型的值给新对象;但如果属性是引用数据类型,复制的就是内存中的地址,如果其中一个对象改变了这个内存中的地址,肯定会影响到另一个对象。 深拷贝: 3. JSON.stringify(); // 因为我只会这个... // 把一个对象序列化成为 JSON 的字符串,并将对象里面的内容转换成字符串,最后再用 JSON.parse() 的方法将JSON 字符串生成一个新的对象 let obj1 = { a:1, b:[1,2,3] } let str = JSON.stringify(obj1); let obj2 = JSON.parse(str); console.log(obj2); //{a:1,b:[1,2,3]} obj1.a = 2; obj1.b.push(4); console.log(obj1); //{a:2,b:[1,2,3,4]} console.log(obj2); //{a:1,b:[1,2,3]}
9. Ajax如何使用?
// 自己学着写的 1. 先创建XMLHhttpRequest对象 2. 使用open方法创建请求, 设置请求地址 3. 为xhr.onreadystatechange设置监听事件(成功,失败) 4. 使用send发送请求 ------------------------------------------------------------------- <body> <div> 账号<input type="text" name="userId" id="userId"> 密码<input type="password" name="password" id="password"> <button id="sendBtn">send</button> </div> <script> // 创建 XMLHTTPRequest 对象 let xhl = new XMLHttpRequest(); document.getElementById('sendBtn').onclick = function() { let userid = document.getElementById('userId').value; let password = document.getElementById('password').value; // 使用open方法创建请求, 设置请求地址 xhl.open('get','/register?userid='+userid+'&password='+password); // 为xhr.onreadystatechange 设置监听事件 xhl.onreadystatechange = function() { if (xhl.readyState == 4 && xhl.status == 200) { window.alert('请求为200'); } else { window.alert('请求未成功'); } } // 使用send方法发送请求 xhl.send(); xhl.onload = function () { window.alert(xhl.responseText) } } </script> </body>
10. 什么是作用域链?
一般情况使用的变量取值是在当前执行环境的作用域中查找,如果当前作用域没有查到这个值,就会向上级作用域查找,知道查找到全局作用域,这么一个查找的过程我们叫做作用域链 ----------------------------------------------------------------------------------------------------------------------------------------------------- 1、全局执行环境的变量对象始终都是作用域链上的最后一个对象 2、内部环境可以通过作用域链访问所有外部环境,但外部环境不能访问内部环境的任何变量和函数。 3、由于变量的查找是沿着作用域链来实现的,所以也称作用域链为变量查找的机制。 ———————————————————————————————————————————————————————————————————————————————————————————————————————————————— 版权声明:本文为CSDN博主「Suzy_Xie」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_40854368/article/details/120470934
11. 什么是跨域? 如何解决跨域?
跨域: 指的是浏览器不能执行其他网站的脚本. 它是由浏览器的同源策略造成的, 是浏览器对javascript施加的安全限制, 跨域限制访问,其实是浏览器的限制. 例如: a页面想获取b页面资源, 如果a、b页面的协议,域名,端口,子域名不同,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源. 同源策略: 是指协议, 域名, 端口都要相同, 其中有一个不同都会产生跨域; --------------------------------------------------------------------------------------------------------- 解决: 1. 不好意思博主不会 _(:з」∠)_
12. 了解过JS的垃圾回收吗?能详细讲讲吗?
1: GC–garbage collection ,js具有“自动”垃圾回收机制,即执行环境会负责管理代码执行过程中使用的内存 2: GC会定期(周期性的)找出那些不再继续使用的变量, 然后释放其内存 3: 不再使用的变量即生命周期结束的变量会被释放, 只能是局部变量, 全局变量的生命周期, 直到浏览器卸载页面才会结束 4: 闭包由于内部函数原因, 外部函数不能算结束, 无法释放内存 5: js的垃圾回收机制----采用的方式 --------------------------------------------------------------------------------------------------------- (1)标记清除法 解释: 当变量进入执行环境时,就将这个变量标记为“进入环境”, 当变量离开环境时会被标记“离开环境”, 离开环境的变量内存被释放 function f1(){ //被标记已进入执行环境 var a=1 var b=2 } f1() //执行完毕,a,b被标记离开执行环境,内存释放 --------------------------------------------------------------------------------------------------------- (2)引用计数法 解释: 跟踪记录每个值被引用的次数, 当某个值的引用次数变为0时, 说明没有方法在访问该值了, 则可将其占用的内存收回 function f1(){ //跟踪a的引用计数 var a={} //a的引用次数 0 var b=a //a的引用次数 1 var c=a //a的引用次数 2 var b={} //a的引用次数 1 var c=[] //a的引用次数 0 } --------------------------------------------------------------------------------------------------------- (3)手工 --直接置空, GC下次再运行时会删除这些值 a=null ———————————————————————————————————————————————————————————————————————————————————————————————————————————————— 版权声明:本文为CSDN博主「盐味气水」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_47433370/article/details/125944847
大家加油!!!!!_(:з」∠)_
书写不易,如果本期文章对您有帮助, 请点赞留下您的足迹,可以的话点个关注_(:з」∠)_, Thanks♪(・ω・)ノ