文章目录
- 原生JS
-
- (1)什么是`JavaScript`?
- (2) 简单介绍一下`JS`基本类型
- (3) 字符串如何转换成布尔类型?
- (4) 数值类型是如何转换布尔类型
- (5) 字符串是如何转换成数值的?
- (6) 都了解过哪些运算符?
- (7) `||`和`??`运算符区别是什么?
- (8) 给变量赋值的方式有哪些?
- (9) 变量的命名有什么规范?
- (10) 你了解过预解析吗?
- (11) let、var、const区别?
- (12) 谈谈你对命名空间和作用域的理解?
- (13) 简单谈一下作用域链?
- (14) 都有哪些作用域?
- (15) 你是怎么理解if-else的?
- (16) continue和break的区别?
- (17) 如何跳出forEach()循环?
- (18) 数组中常见的函数
- (19)观察代码,筛选符合条件的数据
- (20) 观察代码,按照需求转换合理的数据
- (21) 数组中数据剔重
- (22) Array.of()和new Array()
- (23) 数组如何深拷贝?
- (24) NaN == NaN的结果?
- (25)null和undefined的区别?
- (26) 请说明常见的字符串的操作函数
- (27) 请说明Math中常用的操作函数
- (28) 请说明Date中常用的操作函数
- (29)请简述bind、call、apply三个函数的区别
- (30)如何获取数组中的最大值
- (31)如何判断一个变量的类型?
- (32)简述函数形式参数和实际参数区别
- (33) 常见函数声明方式
- (34) 简述一下函数的预解析
- (35) 观察下面的代码说明输出结果以及为什么
- (36) 观察下面的代码,说明输出结果以及为什么
- (37) 简述什么是匿名函数
- (38) 说说你对函数递归的理解
- (39) 什么是自执行函数
- (40) 什么是闭包?项目中如何使用?
- (41) 什么是回调函数?
- (42) 说说对全局污染的理解
- (43)简单说说你是怎么理解BOM
- (44) 你是怎么解决浏览器兼容性问题
- (45) 获取页面标签节点有几种方式
- (46)你是怎么理解DOM
- (47) 如何操作标签节点
- (48) 如何操作标签属性
- (49) 如何操作标签内容
- (50) 如何操作标签样式
- (51) 什么是面向对象
- (52)你是怎么理解原生JS面向对象
- (53)原生JS中怎么实现继承关系
- (54)原生JS中怎么实现继承关系
- (55) 什么是Ajax
- (56) 异步请求底层实现有哪些
- (57) 原生JS Ajax实现步骤
- (58) 什么是跨域?如何解决跨域?
- JS高级
-
- (1) 什么是Promise
- (2) Promise有几种状态
- (3) Promise有哪些执行方法
- (4) 如何同时执行多个异步任务
- (5) aysnc和await
- (6) 回流reflow、重绘repaint
- (7) new一个对象的过程
- (8) 常驻内存、内存泄漏、内存溢出
- (9) 防抖、节流
- (10) 函数柯里化
- (11) 常见排序算法
- (12) JS实现冒泡排序
- (13) 什么是JS事件循环
- (14) 宏任务、微任务,简述执行顺序
- (15) 简述JS垃圾回收机制
- (16) eval的作用
- (17) 本地存储有哪些方式,说说它们的区别
- (18) 栈内存和堆内存
- (19) 栈和队列
- (20) 数组和链表
- (22) 写一个单例模式
- ES6
- Git 基础
- Git高级
- Node.js
- vue2.x
-
- (1) 什么是Vue
- (2) Vue的两个核心
- (3) 简述常见的指令及其含义
- (4) v-if和v-show的区别
- (5) v-for中key的作用
- (6) Vue实例 el 选项的作用
- (7) Vue实例 data选项的作用
- (8) Vue实例 methods选项的作用
- (9) Vue实例 watch选项的作用
- (10) Vue实例 computed选项的作用
- (11) Vue实例 filters选项的作用
- (12) Vue实例 components选项的作用
- (13) Vue实例 name选项的作用
- (14) Vue实例 常见生命周期
- (15) created()、mounted()区别
- (16) 组件页面加载的时候触发哪些生命周期钩子
- (17) 监听器和普通函数的区别
- (18) 计算属性和普通函数的区别
- (19) 如何监听对象的属性
- (20) 如何让监听器开始时立即调用
- (21) 计算属性名称可以和data中的数据重名吗
- (22) 简述父子组件传值的方式
- (23) 什么是插槽,插槽的作用
- (24) 什么是边界传值/操作
- (25) 什么是代理注入传值
- (26) 如何理解Vue单向数据流
- (27) Vue组件的data为什么必须是函数
- (28) 怎么实现组件的缓存
- (29) 组件缓存对应的生命周期有哪些
- (30) Vue如何给标签/组件绑定事件
- (31) 常见的事件修饰符及其作用
- (32) 常见的按键修饰符及其作用
- (33) 常见的系统修饰符及其作用
- (34) 什么是混入mixin,有什么作用
- (35) 如何设置通用样式,如何设置组件样式
- (36) 什么是路由
- (37) 项目中vue-router版本对应关系
- (38) Vue项目中怎么配置路由
- (39) 编程式导航常用的方法
- (40) vue-router如何实现页面跳转
- (41) 如何实现导航高亮
- (42)路由重定向和别名的区别
- (43) 路由路径是如何匹配的,出现冲突如何解决
- (44) 什么是命名路由,有什么作用
- (45) 什么是命名视图,有什么作用
- (46) 路由如何传递查询字符串参数
- (47) 路由如何传递动态路径参数
- (48)` $route`、`$router`的区别
- (49) 如何实现路由嵌套
- (50) 什么是路由元数据
- (51) 如何监听页面滚动行为
- (52) 什么是导航守卫
- (53) 常见的导航守卫
- (54) 导航守卫、拦截器的区别
- (55) Vuex中的5个核心属性
- (56) Vuex解决了哪些问题
- (57) 简述Vuex中数据传递流程
- (58) mutations和actions区别
- (59) 辅助函数mapState/mapMutations/mapActions/mapGetters
- (60) Vuex模块化开发的构建
- (61) Vuex模块中namespaced的作用
- (62) 什么是axios
- (63) jQuery、axios的区别
- (64) axios的请求配置
- (65) axios的响应数据
- (66) axios拦截器
- (67) 如何取消请求
- (68) 用过的视图组件库有哪些
- (69) 项目中如何添加element-ui
- vue高级
-
- (1) 什么是MVVM
- (2) MVVM和MVC的区别
- (3) 什么是SPA,优缺点是什么
- (4) 什么是虚拟DOM
- (5) 虚拟DOM如何提高优化效率
- (6) v-model的底层实现原理
- (7) 数据双向绑定底层实现原理
- (8) nextTick()底层实现原理
- (9) Object.defineProperty()和Proxy()区别
- (10) 简述自定义组件的封装过程
- (11) 为什么需要避免v-if和v-for一起使用
- (12) vue-loader的作用
- (13) 如何触发Vue的强制更新
- (14) 数组哪些操作可以触发页面更新,哪些不可以,有什么解决方案
- (15) 父子组件嵌套时各自生命周期执行顺序
- (16) 父组件如何操作子组件DOM数据
- (17) 什么是组件递归调用
- (18) Vue页面渲染如何保留模板中的注释
- (19) Vue2.0兼容IE那个版本
- (20) Vue为什么首页加载缓慢
- (21) 如何做首屏加载优化
- (22) Vuex中strict属性的作用
- (23) 为什么mutations中不能做异步操作
- (24) 什么是SSR,优缺点是什么
- (25) Vue2、Vue3区别
- (26) 项目中如何管理导入依赖,说说自动导入的优缺点
- (27) 数组列表渲染,如果只更新单个数据,数组是否会重新渲染
- (28) 简单阐述一些Vue页面加载过程
- (29) 说明一下你理解的diff算法
- (30) 你都用过哪些代码检查工具
- <font color = Orange>## ***···以上来自博主老师的总结,我只是知识的搬运工***
原生JS
(1)什么是JavaScript
?
JavaScript是一个弱类型的、支持面向过程和面向对象编程的,主要工作在浏览器一侧给网页提供动态功能的、解释型的编程语言;
在发展过程中JavaScript也可以基于Node环境开发服务端应用,是很多前后端框架的底层实现技术!
(2) 简单介绍一下JS
基本类型
原生JS中基本类型包括
字符串String
数值类型Number、
布尔类型Boolean
空值类型Null、
未声明类型Undefined
ES6中提供了新的唯一值类型Symbol
拓展
面试官可能会追问:
Object
算不算基本类型? | 还有其他的吗?原生JS中面向对象编程的理念是一切皆对象,有些资料里面也会把Object当成基本类型对待
(3) 字符串如何转换成布尔类型?
字符串可以和
布尔类型
进行转换,空字符串
转换结果是false
,非空字符串
转换结果是true
在项目中一般对字符串的有效值判断直接放在if
条件中进行隐式
判断
const response = getListJson()
// 获取接口字符串数据
if(response.data) {
// data存储的字符串格式的json数据
…有效数据
} else {
… 无效数据,提示错误
}
(4) 数值类型是如何转换布尔类型
数值可以转换成布尔类型,0的转换结果是false,非0转换结果true
项目中大部分场景中主要做非0判断,可以直接将数值放在if条件中进行隐式判断,或者可以和逻辑运算符结合起来进行默认值赋值处理
const price = goodsPrice || 1
一部分场景中0也属于有效数据,可以借助??运算符进行赋值和判断处理
const price = goodsPrice ?? 1
(5) 字符串是如何转换成数值的?
其他问法:parseInt('111', 2)
转换结果是什么?
数值可以是字符串形式的,所以字符串类型的数字可以转换成数值
parseInt()
可以将字符串数字转换成整数
parseFloat()
可以将字符串数字转换成浮点数
如果字符串包含字母和数字,数字开头的话转换结果截取数字部分;如果字母开头转换结果NaN
parseInt()
转换的时候可以指定进制单位,如parseInt('111', 2)
当成2进制转换结果是7
(6) 都了解过哪些运算符?
原生JS常用的运算符
赋值运算符
、算术运算符
、比较运算符
、逻辑运算符
、三元/三目运算符
一些算法结构中为了提高性能会用到位运算符
(7) ||
和??
运算符区别是什么?
常规声明变量的时候如果没有赋值就会默认存储undefined
变量默认值赋值一般出现在函数或者数据处理流程中,使用||和??进行默认值赋值
||
赋值时会将空字符串和0
这样的数据当成无效数据,赋值指定默认数据
??
赋值时只会判断null和undefined
当成无效数据,赋值指定默认数据
(8) 给变量赋值的方式有哪些?
其他问法:你项目中是怎么给变量做初始化处理的?10%概率
变量的声明和赋值方式有不同的形式
- 标准方式可以直接声明变量并且赋值数据,
let a = 12; let a = 10, b = 12;
- 也可以先声明变量
(let a;)
,需要的时候赋值数据(a=11)
,赋值数据之前变量中存储的是undefined
- 如果需要多个相同数据的变量,可以进行连续赋值,
let a = b = c = 1
(9) 变量的命名有什么规范?
其他问法:你们项目组变量是什么命名的? 5%概率
变量语法规则是
字母
、数字
、下划线
、$符号
组成,数字
不能开头
我们项目中要求变量尽量做到使用英文单词做到见名知意,使用小驼峰命名法进行命名处理
(10) 你了解过预解析吗?
其他问法:你知道什么是变量提升吗? 70%概率
原生JS中使用var声明的变量,存在预解析处理操作
声明的变量在当前作用域中会将变量的声明部分提前到最前面,赋值部分保留在原位置
,也被称为变量声明提升
主要作用就是为了保障当前作用域中使用这个变量不会报错,提高代码的容错性
(11) let、var、const区别?
其他问法:原生JS中var声明变量和ES6中let、const声明变量有什么区别?80%概率
var
声明变量是原生JS中的声明方式,主要区分声明全局变量
和局部变量
,存在变量预解析
let
和const
都是ES6中提供的用于声明变量和常量的方式,是对var
的补充
let
声明的变量存在块级作用域、不能重复声明,没有变量预解析
const
主要用于声明常量
(12) 谈谈你对命名空间和作用域的理解?
其他问法:命名空间和作用域的区别?80%概率
命名空间是包含了当前作用域范围中的所有
变量
、函数
、类型
等数据的空间!
(所有数据)
作用域是某个变量、某个函数或者某个数据可以被访问的范围!
(单个数据)
(13) 简单谈一下作用域链?
其他问法:一个变量是怎么被访问到的?50%概率
每个变量可以被访问的范围是它的作用域,原生JS中
不同的作用域之间形成作用域链
变量的访问顺序是按照作用域链的过程被访问,首先读取当前作用域中的变量,如果没有该变量的声明就会继续访问上一级作用域,如果所有作用域中都没有访问到该变量就会报错提示变量没有定义!
(14) 都有哪些作用域?
其他问法:什么是作用域链 ?50%概率
每个变量可以被访问的范围是它的作用域,原生JS中不同的作用域之间形成作用域链
从大到小依次是环境作用域、系统作用域、全局作用域、局部作用域、嵌套/[闭包]作用域
(15) 你是怎么理解if-else的?
其他问法:你项目中如果出现了大量条件分支,你是怎么使用if-else的? 10%概率
项目中如果出现的分支并不是很多,可以直接使用
if-else
的多分支结构进行判断处理即可,我自己的项目中一般要求6个分支以内使用多分支结构
如果分支数量比较庞大,为了提高代码的可读性,同时降低代码的重复率可以借助数组或者对象和if双分支结构进行语法优化
const role = “会员” // 游客、管理员
if(role === “会员”) {…}
else if(role === “管理员”){…}
else if(role === “游客”) {…}
else {…}
const level = {“青铜1”: […], “青铜2”: […], …, “王者22星”: […]}
const info = level[“王者11星”]
if(info){
…
} else {
…
}
(16) continue和break的区别?
continue
和break
都可以出现在循环结构中
continue
终止本次循环直接开始下一次循环
break
直接跳出循环
break还可以出现在switch-case中用于结束一个分支
(17) 如何跳出forEach()循环?
其他问法:forEach()
循环结构可以使用break
吗? 10%概率
break
只能跳出循环结构
forEach()是一个函数无法使用break完成跳出循环的操作
forEach()`函数参数是一个闭包函数,也不能使用return跳出循环
forEach()满足跳出循环的条件时抛出异常,外部代码中使用
try-catch
捕获异常的方式跳出循环
let jobs = [“需求工程师”, “开发工程师”,…]// 1、无法跳出
jobs.forEach(item => {
…
break; 无法跳出循环,报错~break无法使用在switch和循环结构之外的其他地方
return; 无法跳出循环,只会结束本次循环闭包函数直接开始下一次循环,不会报错
})
// 2、跳出
try{
jobs.forEach(item => {
…
if(满足条件) {
throw new Error(“自定义错误”)
}
})
} catch(e) {
捕获错误,代码继续向下执行
}
(18) 数组中常见的函数
其他问法:请说出至少5个数组的操作函数,65%概率
push() / pop()
unshift() / shift()
forEach() / map() / filter()
indexOf()/lastIndexOf()
find()/findLast()
findIndex()/findLastIndex()
include()
startsWith()/endsWith()
match()/search()
reverse() / sort()
…
(19)观察代码,筛选符合条件的数据
const accounts = [“admin”, “manager”, “tom123”, “jerry”, “shuke_123”]
// 需求:保留账号长度在6~18位的账号
//考察:filter()
accounts = accounts.filter(item => { return item.length >= 6 && item.length <= 18 })
(20) 观察代码,按照需求转换合理的数据
const accounts = [“admin”, “manager”, “tom123”, “jerry”, “shuke_123”]
// 需求:将上述账号统一加上部门前缀-dept
// 考察:map()
accounts = accounts.map(item => { return dept${item} })
(21) 数组中数据剔重
其他问法:请将数组中重复的数据剔重 ;65%概率(笔试题)
const accounts = [“admin”, “manager”, “admin”, “jerry”, “jerry”]
// 需求:将上述代码中的重复数据剔除
// 考察:代码逻辑思考能力、新技术点掌握能力
let newAccounts = new Set(accounts)
// ES6 Set类型
accounts = Array.from(newAccounts)
// ES6 Array.from()类型转换
xxxxxxxxxx // 使用普通for循环,可以|(除非要求使用底层代码实现)否则不推荐
function uniqueArr(arr) {
let newArr = []
for(var i = 0; i < arr.length ; i++) {
if(!newArr.includes(item)) {
newArr.push(item)
}
}
return newArr