2023前端面试(JS专题)
目录
一、前言
二、问题
1,JS数据类型
2,== 与 === 的区别?
3,JS的宏任务和微任务?
4,实现Jsonp
5,JS作用域
6,JS作用域+this指向+原型笔试题(高频)
7, JS判断变量是不是数组,有哪些方法?
8, slice是干嘛的,splice是否会改变原数组,二者区别?
9,JS数组去重?
10,找出多维数组的最大值?
12,找出一个字符串出现次数最多的字符,出现了多少次?
13,字符串的方法?
14,new操作符具体做了什么?
15,闭包是什么?
16,原型链是什么?
17,js的继承有哪些方式?
18,call、apply、bind的区别?
19,sort原理了解吗?
20,深浅拷贝的理解?(高频)
21,本地存储方式的区别?
22,find和filter区别?
23,some和every区别?
24,合并多个对象?
一、前言
一般比较大一点的公司面试或笔试问题的重点都侧重于js这块,考验你js的功底扎不扎实。所以在准备面试的时候,js一定要复习好,而且要过好几遍,直至熟练回答为止,有的甚至需要手写几遍。毕竟机会都是给有准备的人的。下面给大家整理了一下面试中常问的js问题。大家可以查缺补漏。
二、问题
1,JS数据类型
基本数据类型 Number、String、Boolean、Null、Undefined、Symbol
引用数据类型 Object、Array、Date、Function、RegExp
这里面可以拓展的问题很多,一定要多去思考,比如:
- null和undefined的区别?(基本的大家都知道,但怎么回答的让面试官耳目一新呢?)
(1)设计历史:
之前看过相关文献,作者在设计js的时候,先有null后有undefined,因为借鉴了java的语言,null的数据类型时object,会被隐式转换成0,不容易发现错误;所以就设计了undefined,它是一个基本数据类型,转成数值为NaN;
(2)数据:
null已经声明赋值为空;引用数据类型;数值转换为0;
undefined已经声明未赋值;基本数据类型;数值转换为NaN(数值类型,不表示数字);
- symbol数据类型的特点?
symbol 是ES6引入了一种新的基本数据类型(原始数据类型),表示独一无二的值。
(1)Symbol的值是唯一的,用来解决命名冲突的问题;
(2)Symbol值不能与其他数据类型进行运算;
(3)Symbol定义得的对象的属性不能使用for…in 循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名;
- 两种数据类型的存放机制?
基本数据类型体积小,存放在栈里面;
引用数据类型体积大,存放在堆里面;
引用数据类型会有个指针放在栈里面,定位堆里面存放的引用数据;
- 如何判断这两种数据类型?
(1)typeof:查找基本数据类型,引用数据类型除了function,其他都为object;
(2)instanceof:查找引用数据类型;
原理:instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype, 返回true,不是返回false;
(3)Object.prototype.toString().call():所有数据类型;
原理:原型链和原型有关,首先toString()这个方法本来应该返回string的字符串形式,但是大多数情况会返回[object,xxxx]形式;因为js重写了某些数据类型的toString()方法;所以这时候我们找到原型上最原始的toSting()方法;call的作用就是转变this的指向;
- 数据类型如何转换?
(1)转为字符串:toString() / String() 不能用于null和undefined
(2)转为数值:Number() / parseInt() 转为整数,parseFloat 转为浮点数
(3)隐式转换:js是一门弱语言,运行期间,变量会根据运行环境自动类型转换;
举例:字符串数据+0/*1可以转换成数值;字符串+数值=字符串
(4)转为布尔值:false(0,null,undefined,'',NaN)
2,== 与 === 的区别?
==比较值
string == number || boolean || number都会隐式转换,通过valueOf()方法通常由js在后台自动转换
===比较值和数据类型,除了比较值,还比较类型
3,JS的宏任务和微任务?
(1)首先得解释一下JS的单线程:
js是单线程的语言,用途(浏览器的脚本语言,主要负责交互,动画,效果)决定了它必须是单线程的语言。单线程是指同一时间只能做一件事。如果能做多件事情的话,假如用户同时有两个操作,一个是删除节点,一个是新增节点,那到底应该选择是新增还是删除呢?所以js在设计的时候就必须是单线程的。
(2)其次解释一下JS代码的执行流程:
同步执行完==》事件循环;同步的任务都执行完了,才会执行事件循环的内容,进入事件循环有哪些:请求、定时器、事件。
(3)然后解释一下事件循环:
进入事件循环也得分哪个先哪个后呀?所以事件循环里面又分微任务和宏任务。
微任务:promise.then();
宏任务:setTimeOut;
执行顺序为:先执行微任务,在执行宏任务,宏任务里面还有微任务,先执行微任务,以此循环下去;记住关键,要执行宏任务的前提是清空了所有的微任务。
(4)最后总结一下代码的执行流程:
同步=》事件循环【微任务,宏任务】=》微任务=》宏任务=》微任务......;
4,实现Jsonp
srcipt标签引入
iframe
后端
配置请求头
可能会有拓展问题:
同源策略:域名,协议,端口号相同。
为什么限制:为了防止恶意ajax请求,修改DOM页面,随意获取cookie隐私数据等;
域名:www.baidu.com
端口:8080,3000
协议:https/http
5,JS作用域
全局作用域:代码在程序的任何地方都能被访问,window对象的内置属性都拥有全局作用域;
函数作用域:只有在固定的代码片段才能被访问;
好处:隔离变量,不同作用域下同名变量不会有冲突。
作用域链:一般情况下,变量取值会在创建这个变量的函数作用域中取值,如果没找到,就会像上级作用域查找,知道查到全局作用域,这个过程就叫作用域链;
除了函数外,js没有块级作用域;
比如:在函数里定义一个变量,在函数外打印这个变量,即使函数调用了,也没办法打印;
如果有笔试题,或者现场出题的话,这个就是高频题了,就需要重点理解了。
注意:
(1)声明的变量是用var还是没有写(就是window);
(2)js变量提升的机制【变量悬挂声明】;
(3)注意本层作用域有没有变量提升;
6,JS作用域+this指向+原型笔试题(高频)
构造函数:this指向的是实例对象,
全局函数:this指向window;
use strict:指向的是undefined;
绑定事件:this指的是被绑定事件的元素;
箭头函数:this和父级this指向相同;
考题一:
function foo(){getName = function(){console.log(1)};return this;
}
Foo.getName = function(){console.log(2)
}
Foo.prototype.getName = function(){console.log(3)
}
var getName = function(){console.log(4)
}
function getName(){console.log(5)
}
Foo.getName() //2
getName() //4
Foo().getName() //1
getName() //1
new Foo().getName() //3
考题二:
var o = {a:10,b:{fn:function(){console.log(this.a)console.log(this)} }
}
o.b.fn() //undefined b函数
考题三:
window.name = 'ByteDance'
function A(){this.name = 123;
}
A.prototype.getA = function(){console.log(this);return this.name+1;
}
let a = new A()
let funcA = function(){console.log(this)return this.name+1
}
funcA() //this指的是window; 'ByteDance1'
7, JS判断变量是不是数组,有哪些方法?
(1) Array.isArray(arr)
(2) arr instanceof Array【可写可不写,因为有bug】
(3) Object.prototype.toString.call(arr)
(4) Array.prototype.isPrototype(arr)
(5) arr.constructor.toString()
8, slice是干嘛的,splice是否会改变原数组,二者区别?
slice:选择截取部分内容,参数可以一个,两个,也可以是负数,返回新数组;
splice:会改变原数组;插入、删除、替换;返回删除的元素;
9,JS数组去重?
扩展运算符 + new set
循环
sort排序
代码演示:
(1) new Set
//Array.from(new set(arr))
//...new Set(arr)
var arr1 = [1,2,3,2,4,1];
function unique(arr){return [...new Set(arr)]
}
console.log(unique(arr1))(2) 循环
function unique3(arr){var brr = []for(var i=0; i<arr.length; i++){if(brr.indexOf(arr[i]) == -1){brr.push(arr[i])}}return brr}console.log(unique3(arr));(3) sort
function unique4(arr){arr = arr.sort()var brr = []for(var i=0;i<arr.length;i++){if(arr[1] !== arr[i-1]){brr.push(arr[i])}}return brr}console.log(unique4(arr));
10,找出多维数组的最大值?
Math.max(..item)
代码演示:
var arr = [[1,3,7,9],[22,77,90,78],[123,567,890,345],[1002,3004,3009,2890]]function fn(arr){var brr = []arr.forEach((item,index)=>{brr.push(Math.max(...item))})return brr}console.log(fn(arr));
11,给字符串新增方法实现功能?
addPrefix() 添加前缀
代码演示:
String.prototype.addPrefix = function (str){return str + this}console.log('Bryan'.addPrefix('Kobe'));
12,找出一个字符串出现次数最多的字符,出现了多少次?
var str = 'aaaabbbbssssxcccddddsdfscxxasa'var obj = {};for(var i=0; i<str.length; i++){var char = str.charAt(i)if(obj[char]){obj[char]++;}else{obj[char] = 1;}}console.log(obj);//统计出来最大值var max = 0;for(var key in obj){if(max < obj[key]){max = obj[key]}}//拿最大值去对比for(var key in obj){if(obj[key] == max){console.log('最多的字符是'+key);console.log('出现的次数是'+max);}}
13,字符串的方法?
方法 | 功能 |
---|---|
charAt() | 返回指定索引位置的字符 |
indexOf() | 返回字符串中检索指定字符第一次出现的位置 |
replace() | 替换与正则表达式匹配的字串 |
slice() | 提取字符串的片段,返回新的字符串 |
split() | 把字符串分隔为子字符串数组 |
substr() | 从起始索引号提取字符串中指定数目的字符 |
subString() | 提取字符串中两个指定的索引号之间的字符 |
toLowerCase() | 变小写 |
toUpperCase() | 变大写 |
toString() | 返回字符串对象值 |
trim() | 移除字符串首尾空白 |
valueOf() | 返回某个字符串对象的原始值 |
14,new操作符具体做了什么?
(1)创建了一个空对象;
(2)将空对象的原型,指向于构造函数的原型;
(3)将构造函数里的this指向空对象;
(4)将构造函数的属性和方法赋值给空对象;
(5)返回这个对象;
代码演示:
function Fun( name, age ){this.name = name;this.age = age;}function create( fn,...args ){//创建一个新对象var obj = {}//把对象的原型指向构造函数的原型Object.setPrototypeOf(obj,fn.prototype)//改变this的指向var result = fn.apply(obj.args)//对构造函数有返回值的处理判断return result instanceof Object ? result : obj;}console.log(create(Fun,18,'张三'));
15,闭包是什么?
(1)是什么:
闭包是一个函数内返回一个函数,外部函数能读取内部函数的变量;
(2)优点:
内部可以读取外部函数的变量,可以封装独有的方法和属性,保持内部的独立性;
(3)可以解决问题:
- 比如说要点击ul下面的每一项li,点击每项弹出每项的内容;
代码演示:
var lis = document.querySelectorAll('li');for(var i=0; i<lis.length; i++){(function(i){lis[i].onclick = function(){alert(i)}lis[i]=null})(i)}
- 防抖,柯里化,定时器等
(4)缺点:
变量会驻留在内存中,造成内存损耗问题;内存泄漏(IE)
解决:把闭包的函数设置为null;
16,原型链是什么?
这个问题经常会问,但千篇一律肯定没办法加分,所以需要说清楚,为什么会有原型,为什么会有原型链,在什么场景会用,方法是什么,原理是什么,按照这样的思路去说基本没问题。
我们知道创建对象的方式有三种,字面量,new,构造函数。前两个只能创建单个的对象,但构造函数可以把不同对象的共同属性和方法抽离出来,通过new实例化创建拥有共同属性和方法的不同对象。但是想一想,会出现什么问题呢?
由于js存储数据的方式是引用数据类型存储在堆里面,我们new出来的不同对象都拥有这一个相同的方法,但是都要在堆里面去申请不同的空间去存储,这样就会极大的浪费我们的内容空间。
所以这个时候我们就有了原型prototype。这样不同的对象可以通过原型去查找,节省内存空间,how nice!
也就是说原型可以解决:对象共享属性和共享方法。
总结简洁版(思路如下,自己整理能说明白即可):
(1)原型可以解决什么问题:对象共享属性和共享方法;
(2)谁有原型?函数拥有prototype,对象拥有:`__proto__`
(3)对象查找属性或者方法的顺序:
先在对象本身查找-->构造函数中查找-->对象的原型-->构造函数的原型中-->当前原型的原型;
(4)原型链的最顶端是Null;
17,js的继承有哪些方式?
不需要每个都讲,只需要讲到重点常用的几个即可;
(1)es6
class father{constructor(){this.age = 18}
}
class child extends father{constructor(){super()this.name = '张三'}
}
let Child = new child()
console.log(Child,Child.name,Child.age)
(2)原型链继承
child.prototype = new parent()
let Child = new child()
console.log(Child, Child.name, Child.age)
//继承的属性和方法在原型上
(3)构造函数继承:
function Father(){this.name = '张三'}function Son(){this.age = 20Father.call(this)}let o3 = new Son()console.log(o3);
(4)组合继承
function Father(name,age){this.name = namethis.age = age}function Son(name,age){Father.call(this,name,age)}const son = new Son('刘德华', 20)console.log(son);
18,call、apply、bind的区别?
(1)相同点:功能一致,都可以改变this指向;
(2)语法:函数.call(fn,name),函数.apply(fn,[...args]),函数.bind();
(3)区别:
- call,apply可以立即指向,bind不会立即指向,因为bind返回的是一个函数需要加入()执行;
- 参数不同,apply第二个参数是数组,call和bind有多个参数需要挨个写;
(4)使用场景:
- 找出最大值:
var arr = [1,2,4,5,78,21]
console.log(Math.max.apply(null,arr1))
- 用bind的情况
var btn = document.querySelector('btn')
var h1s = document.querySelector('h1s')
btn.onclick = function(){console.log(this.id)
}.bind(h1s) //h1s
19,sort原理了解吗?
之前的版本是插入和快排,现在是冒泡;
使用场景:
(1)升序:
var arr = [1,2,23,21,222,778]
let res = arr.sort(function(a,b){return a-b
})
console.log(res)
(2)降序:
var arr = [1,2,23,21,222,778]
let res = arr.sort(function(a,b){return b-a
})
console.log(res)
(3)排序对象中某属性值的顺序:
var obj = [{name:'张三',age:2},{name:'李四',age:29},{name:'王五',age:70}
]
function compare(age){return function (a,b){var val1 = a[age]var val2 = b[age]return val1-val2}
}
var arr = obj.sort(compare('age'))
console.log(arr)
20,深浅拷贝的理解?(高频)
首先什么情况会出现深浅拷贝呢?
假设我们有一个已经定义了属性和方法的对象,我们再创建一个新对象,然后用=号把已定义的对象赋值给新创建的空对象;
如果我们修改新对象里的某个属性值,打印原来已定义的对象时,你会发现它的值也发生变化了;
这种情况就是发生了浅拷贝。为什么呢?
这是因为js的数据存储方式是基本数据类型再栈里面,引用数据类型在堆里面,但引用数据的指针,也就是房间号在栈里面存着。如果我们用=号去赋值,就相当于把指针赋值给了另一个对象,也就是说这两个对象的指针都是一样的,所以你修改了任意一个对象的值另一个也会发生变化。
那如果不想出现上面的情况,我们就需要进行深拷贝了,也就是说要在堆里面重新申请一个新空间,指针也是不同的,这样就不会发生连锁反应了。
简洁版思路:
共同点:复制
(1)浅拷贝:只复制引用地址,而未复制真正的值;object.assign()
(2)深拷贝:是复制真正的值(不同的引用)
(3)方式:JSON.parse(JSON.Stringify) 递归形式;
21,本地存储方式的区别?
(1)数据存放有效期:
localStorage:始终有效,持久存储;
sessionStorage:浏览器关闭就没了;
cookie:只在设置的cookie过期时间之前有效,即使窗口或者浏览器关闭也有效,其他不可以设置时间;
(2)存储大小的限制:
cookie存储量不能超过4k;
localStorage、sessionStorage不能超过5M;
22,find和filter区别?
(1)区别一:filter返回新数组,find返回具体的内容;
(2)区别二:find匹配到第一个即返回,filter只要满足条件push到新数组里,返回新数组;
23,some和every区别?
some是只要满足一个条件就返回true;
every是都满足返回为true;
24,合并多个对象?
(1)方法一:Object.assign(a,b)
(2)方法二:obj = {...a,...b}
(3)方法三:循环
function extend(target,source){for(var obj in source){target[obj] = source[obj]}return target
}
console.log(extend(a,b))
2023前端面试(JS专题)相关推荐
- js 点击闭包_【新年跳槽必备】2020最新(前端原生JS专题)面试题 速领!
最近我把每周更新的面试题 发在我们的学习群里 大家似乎都很高冷哇 难道是默默的做题去了没说话 每期面试题都是Richard老师认真准备的 真的希望能帮到大家哦 本期是前端原生JS专题 A前端原生JS专 ...
- 2023前端面试整理合集
2023前端面试自我整理 1.讲讲cookies和localstorage,sessionstroage的区别? 区别:cookie它的大小只有4kb,而localstorage和sessionstr ...
- 前端面试 - JS总结(1) - 基础 (数据类型, 事件与函数, 原型链)
你不走出舒适圈,又怎么知道自己多坚强?! 前端面试 - JS总结(1) - 基础 (数据类型, 事件与函数, 原型链) 前端面试 - JS总结(2) - ES6 (let, 箭头函数, this) 前 ...
- 前端面试JS必备基础之深浅拷贝和this指向问题@莫成尘
一:js深拷贝 在JS中,数据类型分为基本数据类型和引用数据类型两种,对于基本数据类型来说,它的值直接存储在栈内存中,而对于引用类型来说,它在栈内存中仅仅存储了一个引用,而真正的数据存储在堆内存中.深 ...
- web前端面试 js部分
1/如何用原生js给一个按钮绑定过两个click事件 var obtn = document.getElementById('btn'); obtn.addEventListener('click', ...
- 2023前端面试总结含参考答案
文章目录 1. 父子组件生命周期的执行顺序: 2. 原型链: 3. promise的理解: 4. 数组循环,foreach,filter,map,reduce 5. 数组去重,set 6. 组件通信方 ...
- 前端面试——JS去除首尾空格代码
关于 JavaScript 里的 trim()/strip() 方法 在其他语言中常常用 trim()/strip() 方法脱去不必要的空格等元素. JavaScript 本身并不提供 trim() ...
- 前端面试日记(7)网易有道
没有什么能阻挡你成功,只要你稳稳当当,每一步都好好走下去. 注:在牛客平台投递简历处理很快.约的时间比较靠后.面试时常15min(不知道为啥如此迅速) 1. 自我介绍 2. 项目有哪些难点,如何解决? ...
- 前端面试:你应该了解的JS算法相关的知识
前端面试:你应该了解的JS算法相关的知识 时间复杂度 通常使用最差的时间复杂度来衡量一个算法的好坏. 常数时间 O(1) 代表这个操作和数据量没关系,是一个固定时间的操作,比如说四则运算. 对于一个算 ...
最新文章
- Spring之AOP由浅入深
- Python中单个下划线“ _”变量的用途是什么?
- JS 面向对象与原型
- SQL SERVER – Beginning of SQL Server Architecture – Terminology – Guest Post
- 【HDU 1276】士兵队列训练问题(两个队列模拟)
- WampServer修改端口及菜单Localhost
- 2016经典微小说:《轮回》
- linux内核 panic,linux 内核 panic
- 数学分析闭区间套定理_不能精确找到背驰点?利用区间套解决这难题
- springboot报错Table 'wechat.hibernate_sequence' doesn't exist
- malloc 初始化_glibc: malloc、calloc、realloc amp; free
- Solaris 10 的基本操作
- 小夜曲dsd使用foobar2000测试dsd输出
- WPS打不出英文引号
- 什么电子邮箱正式?企业工作邮箱大全,一般白领用什么邮箱账号?
- 优炫数据库携手兆芯发布数据库解决方案
- 手机有时触摸失灵解决方法
- VR插件:VR Interaction Framework 1.7(VRIF)(一)
- 【纯净版windows系统】U盘启动制作图文教程
- 小编推荐这款,超实用的SpringBoot 开源商城系统,挣钱不是太轻松!