前端实习面经
本系列文章为本菜鸟记录自己的前端面试经验,也希望帮助到需要者。
文章目录
- 前端实习面经
- 公司
- 面试题
- 1.之前有用过`typescript`吗
- 2.项目中,前端动态路由怎么设计
- 3.watch和computed这两个api的区别
- 4.vue如何自定义一个指令
- 5.`v-model`是一个语法糖,说一下`v-model`是通过哪两个指令形成的
- 6.祖孙间通信的api:`provide/inject`
- 7.vue的扩展函数(`Vue.extend`)
- 8.vuex的介绍
- 9.使用过哪些css预处理机制
- 10.es6好用的api
- 10.箭头函数能作为构造函数吗
- 10.es6提供了class语法糖,是object原型链上实现的一个抽象出来的function,有使用class定义一个对象,或者利用class来做一些面向对象的api吗?
- 11.用过的生态库,比如`loadsh`,`echarts`
- 12.`promise`解决回调地狱,你使用过`promise`的哪些方法
- 13.场景题:后端给了一个接口,接口的返回结果是一个不确定长度的数组,这个数组存放的全是商品的id,但是并不知道给了多少个,现在就是要按照数组这个`id`的顺序,一个接一个的发出请求,请求商品的详情。第二个要求是要按照这个数组的顺序。第三个是不借助`promise`的`async/await`语法糖来实现。第四个要求是一旦请求发出以后我需要终止不再发出,一旦出错就停止
- 总结
公司
base上海,全能扫描王
面试题
1.之前有用过typescript
吗
本人还没有学过,面试官建议学习
2.项目中,前端动态路由怎么设计
3.watch和computed这两个api的区别
缓存
(1)computed
支持缓存,只有依赖的数据发生了变化,才会重新计算。并且是基于data
声明过,或者父组件传递过来的props
中的数据进行计算的。
(2)watch
不支持缓存,数据变化时,就会触发相应的操作异步监听
(1)computed
不支持异步监听,当computed
有异步操作时,无法监听数据的变化
(2)watch
支持异步监听computed
(1)如果一个属性是由其他属性计算而来的,这个属性依赖其他的属性,一般就会使用computed
(2)如果computed
属性的属性值是函数,那么默认使用get
方法,函数的返回值就是属性的属性值。在computed
中,属性有一个get
方法和一个set
方法,当数据发生变化时,会调用set
方法watch
监听函数必须是data中声明的或者父组件传递过来的props
中的数据,当发生变化时,会触发其他操作,函数有两个参数:
(1)immediate
:组件加载立即触发回调函数
(2)deep
:深度监听,发现数据内部的变化,在复杂数据类型中使用,例如数组中的对象发生变化。
4.vue如何自定义一个指令
- 自定义指令
我们所看到的v-开头的行内属性,都是指令,不同指令可以完成或实现不同的功能,对普通DOM元素进行底层操作,这时候就会用到自定义指令。除了核心功能默认内置的指令(
v-model
和v-show
),vue也允许自定义指令
- 指令使用的几种方式
//会实例化一个指令,但这个指令没有参数
`v-xxx`
// -- 将值传到指令中
`v-xxx="value"`
//将字符串传入到指令中,比如v-html="`<p>内容</p>`"
`v-xxx="'string'"`
//传参数,比如`v-bind:class="className"`
`v-xxx:arg="value"`
//使用修饰符
`v-xxx:arg.modifier="value"`
- 如何自定义指令
注册一个自定义组件有全局注册与局部注册
(1)全局注册
主要是通过Vue.directive
方法进行注册
//注册一个全局自定义指令 `v-focus`
Vue.directive('focus',{
//当被绑定的元素插入到DOM中时....
inserted:function(el){
//聚焦元素
el.focus() //页面加载完成之后自动让输入框获取到焦点的小功能
}
})
(2)局部注册
主要是通过在组件options选项中设置directive属性
directives:{
focus:{
//指令的定义
inserted:function(el){
el.focus() //页面加载完成之后自动让输入框获取到焦点的小功能
}
}
}
接着,可以在模板中任何元素上使用新的v-focus
<input v-focus/>
- 应用场景
还不是很理解,贴上链接
自定义指令讲解
5.v-model
是一个语法糖,说一下v-model
是通过哪两个指令形成的
v-model
的原理其实就是背后有两个操作:
v-bind
绑定value属性的值v-on
绑定input事件监听函数中,函数会获取最新的值到绑定的属性中
6.祖孙间通信的api:provide/inject
(平时只会说最简单的那几种组件通信)
- 这种方法是vue中的依赖注入,该方法用于父子组件之间的通信。这里说的父子也可以是祖孙,在层数很深的情况下,可以使用这种方法。
provide/inject
是vue提供的两个钩子,和data
、methods
是同级的,并且provide
和data
的书写形式是一样的。provide
钩子用来发送数据和方法inject
钩子用来接收数据和方法- 注意:依赖注入所提供的属性是非响应式的。
另外,整理了一下其他自己还不了解的通信(已了解:父子(props,$emit),全局(eventBus),vuex)
(1)父子
:ref/$refs
ref
:这个属性用在子组件上,它的引用就指向了子组件的实例,可以通过实例来访问组件的数据和方法.
(2)父子($parent/$children
)
$parent
可以让组件访问父组件的实例(访问的是上一级父组件的属性和方法)
$children
可以让组件访问子组件的实例,但是$children
并不能保证顺序,并且访问的数据也不是响应式的.
(3)祖孙通信(爷爷和孙子):$attrs/$listeners
$attrs
:继承所有的父组件属性(除了prop
传递的属性、class
和style
),一般用在自组件的子元素上
$listeners
:该属性是一个对象,里面包含了作用在这个组件上的所有监听器,可以配合v-on="$listeners"
将所有的时间监听器指向这个组件的某个特定的子元素。(相当于子组件继承父组件的事件)
7.vue的扩展函数(Vue.extend
)
暂时还不太理解,懂了再补上
8.vuex的介绍
比较简单,不做整理
9.使用过哪些css预处理机制
- 什么是css预处理
css预处理是一种新的编程语言,为css增加一些编程的特性,无需考虑兼容性问题。css预编译的工作原理是提供便捷的语法和特性提供开发者编写源代码,随后经过专门的编译工具将源码转化为css语法,是前端工程化的里程碑。- 为什么需要css预处理
是为了解决css的一些缺点- css有什么样的缺点
(1)语法不够强大,无法嵌套书写,开发中需要重复写很多遍选择器,造成代码冗余
(2)没有变量、样式复用的规则,难以维护,开发效率低- css预处理的优点
(1)提供样式复用的机制
(2)减少代码冗余,便于维护,开发效率高- css预处理的特点
(1)基于css的另一种编程语言
(2)通过中间工具编译成css
(3)增加一些css不具备的新特性
(4)提升css的文件组织- css预处能力
(1)嵌套一层级和约束
(2)变量和计算——减少重复冗余代码
(3)Mixin/Extend复用代码片段
(4)模块化——importCSS文件
(5)循环 适应于复杂有规律的样式- css三大主流预处理器:Sass、Less、stylus
详细记录见css预处理器
10.es6好用的api
箭头函数、模板字符串、、、、、
10.箭头函数能作为构造函数吗
不能
- 构造函数创建对象的过程
构造函数时通过new关键字来生成对象实例,生成对象实例的过程也是通过构造函数给实例绑定this的过程,而箭头函数没有自己的this,创建对象过程:
(1)new首先创建一个空对象
(2)将这个空对象的__proto__
指向构造函数的prototype
,从而继承原型上的方法。
(3)将this指向这个实例
(4)返回新的对象
而箭头函数不能作为构造函数的原因:箭头函数没有prototype
,也没有this
.所以不能通过new
关键字来调用箭头函数。- 补充:箭头函数与普通函数的区别
(1)写法更简洁
(2)没有this指向
(3)this来自上下文
(4)不能作为构造函数
10.es6提供了class语法糖,是object原型链上实现的一个抽象出来的function,有使用class定义一个对象,或者利用class来做一些面向对象的api吗?
- 关于
class
(1)定义:
class
(类)作为对象的模板被引入,可以通过class关键字定义类,它的本质是函数(function
),可以 看作一个语法糖,让对象的写法更加清晰,更像面向对象编程的语法。
(2)基本用法
匿名表达样式
<script>
class{
construct(name){
this.name = name;
}
}
</script>
命名类表达式
<script>
class Start{
constructor(name){
this.name = name;
}
}
</script>
(3)特殊点
不可重复声明
类声明后不会被提升(有暂时性死区)
<script>
class Start {
constructor(name){
this.name = name;
}
}
console.log(new Start("Betty")); // 输出 :Start {name: "Betty"}
</script>
类中的方法不需要function关键字
使用的时候必须使用new关键字(比如上面的代码输出那里,如果没有使用new就会报错)
(4)class下面的方法
constructor()
方法 是类的默认方法,创建类的实例化对象时被调用
<script>
class Start {
constructor(){
console.log("constructor已执行!");
}
}
new Start(); // 输出:constructor已执行!
</script>
static
静态方法static
只能修饰class
的方法,而不能修饰属性。静态方法不再实例化对象的方法中,里面不能有this
class Start {
static sum(name) {
console.log(name);
}
}
Start.sum("Betty"); // 输出 : Betty
}
原型方法 通过实例出来的对象可以,调用构造函数上面的方法
<script>
class Start {
sum(name) {
console.log(name);
}
}
let test = new Start();
test.sum("Betty"); // 输出:Betty
</script>
11.用过的生态库,比如loadsh
,echarts
12.promise
解决回调地狱,你使用过promise
的哪些方法
Promise.all
Promise.all([]).then(res=>{}).catch(err=>{})
该方法接收一个
Promise
数组,返回一个Promise
只有当该数组中的所有Promise
完成后才会由pending
状态变为resolve
执行then
里面的回调啊含糊。
若数组中有任意一个promise
被拒绝则会执行失败回调,catch
方法会捕获到首个被执行的reject
函数。
该方法获得的成功结果的数组里面的数据顺序和接收到的promise
数组的顺序是一致的。
Promise.any
Promise.any([]).then(res=>{}).catch(err=>{})
当传入的
promise
数组中有任意一个完成时就会终止,会忽略到所有被拒绝掉的promise
,直到第一个promise
完成。若传入的所有promise
都被拒绝则会执行拒绝回调。
promise.race
Promise.race([]).then(res => {}).catch(err => {});
当
promise
数组中任意一个promise
被拒绝或者成功,则会采用第一个promise
作为他的返回值。若为成功的执行then
,若失败则执行catch
。
Promise.allSettled
Promise.allSettled([]).then(results => {}).catch(err => {});
当给定的
promise
数组中的所有promise
被拒绝后会返回一个拒绝的promise
数组,与[]一一对应。
13.场景题:后端给了一个接口,接口的返回结果是一个不确定长度的数组,这个数组存放的全是商品的id,但是并不知道给了多少个,现在就是要按照数组这个id
的顺序,一个接一个的发出请求,请求商品的详情。第二个要求是要按照这个数组的顺序。第三个是不借助promise
的async/await
语法糖来实现。第四个要求是一旦请求发出以后我需要终止不再发出,一旦出错就停止
目前还不不太会这个,之后再做整理
面试官让我了解一下promise
的动态链式调用
总结
回顾录音发现存在以下问题:①基础知识不扎实,②很多明明会,却不知道该怎么说,③很多知识点只是了解怎么使用,却不知道具体原理。
但也感觉面试官并不耐烦,很多问题并没有刷到过,也不会引导你去回答问题。并且我在牛客上刷面经看到都是一些简单的八股文以及排序等算法题。问我的这些感觉我有些没怎么听过,就让我挺慌的,但是回顾的时候发现,其实很多并不难,说明基础真的不好。
另外,面试的时候,尽量少说自己忘记了,如果有所了解就应该说一点自己的理解以及相关,不要一上来就说自己忘了。