记录不全,中间有点懒了,多面试多自己经历总结吧
1、杭州公司一
1、防抖与节流(防抖是回城,节流是技能冷却)
防抖是重新开始
`防抖`指连续触发事件但是在设定时间内`只执行最后一次`
列如:设定一个函数完成需要1000ms,但在500ms时又触发此事件,则会重新开始
(列如:游戏回城、搜索框搜索输入、文本编辑器实时保存)
function debounce(func, delay) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
节流是不被打断
`节流`是指连续触发事件但是`在设定的一段时间内只执行一次函数`
列如:设定1000毫秒执行,那你在1000毫秒触发在多次,也只在100毫秒后执行一次
(列如:高频事件、快速点击,鼠标滑动,resize事件、scroll事件)
function throttle(fn, interval) {
let lastTime = 0;
return function() {
const now = Date.now();
if (now - lastTime >= interval) {
fn.apply(this, arguments);
lastTime = now;
}
};
}
2、图片懒加载
- 懒加载的原理为基于视口(viewport)的概念,即用户当前在屏幕上可见的区域。当页面加载时,只有视口内的资源会被立即加载,而视口外的资源则会被延迟加载。当用户滚动页面或触发其他交互行为时,视口外的资源才会根据需要被加载。
- 懒加载带来的好处:减轻服务器的压力,提升用户体验
3、手写定时器
在JavaScript中,定时器主要有两种:setTimeout(一次性定时器)和setInterval(循环定时器)。
setTimeout示例:
// 延迟一定时间后执行一次
const timer = setTimeout(() => {
console.log('这段代码将在3秒后执行');
}, 3000);
// 清除定时器
// clearTimeout(timer);
setInterval示例:
// 每隔一定时间重复执行
const interval = setInterval(() => {
console.log('这段代码每隔1秒执行一次');
}, 1000);
// 清除定时器
// clearInterval(interval);
4、组件复用,组件传参
组件复用:通过将组件拆分为可复用的模块,可以在多个地方调用同一组件,减少代码冗余。
- 列如:UI(按钮组件),表单组件等
组件传参方式(以Vue为例):
-
Props(父传子) :
<!-- 父组件 --> <ChildComponent :message="parentMessage" /> <!-- 子组件 --> <script> export default { props: ['message'] } </script> -
自定义事件(子传父) :
<!-- 子组件 --> <button @click="$emit('notify', data)">通知父组件</button> <!-- 父组件 --> <ChildComponent @notify="handleNotify" /> -
Provide/Inject(跨层级组件) :
// 祖先组件 provide() { return { theme: 'dark' }; } // 后代组件 inject: ['theme'] -
Vuex/Pinia(状态管理) :全局共享数据。
5、js基础类型,怎么判断函数是对象类型
JS基础类型(原始类型) :
number、string、boolean、null、undefined、symbol、bigint
引用类型:
object(包括数组、函数、日期等)
判断是否为对象类型方法
-
typeof检查typeof func === 'function' // true -
instanceof检查func instanceof Function // true func instanceof Object // true -
构造函数检查
func.constructor === Function // true -
原型检查
Object.getPrototypeOf(func) === Function.prototype // true -
toString 检查
Object.prototype.toString.call(func) === '[object Function]' // true -
函数特有方法检查
'call' in func // true
提示:函数是特殊的对象,所以既是 Function 也是 Object 的实例
6、css动画实现方法
-
transition(过渡) :
.box { transition: all 0.3s ease; } .box:hover { transform: scale(1.1); } -
animation + @keyframes:
@keyframes slide { from { transform: translateX(0); } to { transform: translateX(100px); } } .box { animation: slide 2s infinite alternate; } -
JavaScript控制动画:
element.animate([{ opacity: 0 }, { opacity: 1 }], { duration: 1000 });
7、二次封装请求函数
以Axios为例:
import axios from 'axios';
const http = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000,
});
// 请求拦截
http.interceptors.request.use(config => {
config.headers.Authorization = 'Bearer token';
return config;
});
// 响应拦截
http.interceptors.response.use(
response => response.data,
error => {
console.error('请求出错:', error);
return Promise.reject(error);
}
);
// 封装GET/POST
export const get = (url, params) => http.get(url, { params });
export const post = (url, data) => http.post(url, data);
8、事件循环,宏队列,微队列
事件循环(Event Loop) :
JavaScript是单线程的,通过事件循环处理异步任务。先执行微任务在执行宏任务
-
宏任务(MacroTask) :
setTimeout、setInterval、I/O、UI渲染等。- 每次事件循环执行一个宏任务。
-
微任务(MicroTask) :
Promise.then、MutationObserver、process.nextTick(Node.js)。
执行顺序:
宏任务 → 微任务(全部)→ 渲染 → 下一个宏任务。
9、computed、watch监听器
computed:
- 计算属性,基于依赖缓存,只有依赖变化时才重新计算。
- 适用于派生数据(如过滤列表)。
computed: {
fullName() {
return this.firstName + ' ' + this.lastName;
}
}
watch:
- 监听数据变化,执行副作用(如请求数据)。
- 支持异步。
watch: {
count(newVal, oldVal) {
console.log('count变化了', newVal);
}
}
10、前端Promise
Promise:处理异步操作的对象,解决回调地狱。
三种状态:pending、fulfilled、rejected。
示例:
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('数据加载成功');
// reject('出错啦!');
}, 1000);
});
};
fetchData()
.then(data => console.log(data))
.catch(err => console.error(err));
常用方法:
Promise.all:全部成功才返回。Promise.race:第一个完成的结果。
11、对nodejs的见解
- 基于Chrome V8引擎的JavaScript运行时,支持服务端开发。
- 特点:
- 非阻塞I/O、事件驱动(适合高并发场景,如聊天应用)。
- 单线程(通过事件循环+子进程利用多核CPU)。
- 应用场景:
- API服务、SSR、工具链开发(Webpack)、实时应用(WebSocket)。
- 缺点:
- 不适合CPU密集型任务(如图像处理)。
12、性能优化的方法
前端性能优化:
- 加载优化:
- 压缩资源(JS/CSS/图片)。
- 使用CDN加速静态资源。
- 懒加载/路由懒加载。
- 渲染优化:
- 减少重绘回流(使用
transform代替top/left)。 - 虚拟列表(长列表优化)。
- 减少重绘回流(使用
- 代码优化:
- 防抖/节流(频繁事件处理)。
- 使用Web Worker处理耗时任务。
- 缓存策略:
- HTTP缓存(强缓存/协商缓存)。
- Service Worker离线缓存。
- 工具优化:
- Webpack分包(
splitChunks)。 - 按需引入组件(如lodash的
import throttle from 'lodash/throttle')。
- Webpack分包(
13、pinia的使用
1. 安装 Pinia
yarn add pinia
2. 创建并挂载 Pinia
在 main.js 或 main.ts 中初始化:
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
const app = createApp(App);
app.use(createPinia()); // 启用 Pinia
app.mount('#app');
3. 定义 Store
在 stores 目录下创建 counterStore.js(或 .ts):
import { defineStore } from 'pinia';
// 定义并导出 Store(名称唯一)
export const useCounterStore = defineStore('counter', {
// 状态(数据)
state: () => ({
count: 0,
}),
// 计算属性(类似 computed)
getters: {
doubleCount: (state) => state.count * 2,
},
// 方法(修改状态)
actions: {
increment() {
this.count++;
},
},
});
4. 在组件中使用 Store
<template>
<div>
<p>Count: {{ counter.count }}</p>
<p>Double: {{ counter.doubleCount }}</p>
<button @click="counter.increment()">+1</button>
</div>
</template>
<script setup>
import { useCounterStore } from '@/stores/counter';
const counter = useCounterStore(); // 获取 Store 实例
</script>
5. 核心特性
(1)修改状态
- 直接修改:
counter.count = 10; - 通过
$patch批量修改:counter.$patch({ count: counter.count + 1 }); - 调用 Action(推荐):
counter.increment();
(2)重置状态
counter.$reset(); // 恢复初始状态
(3)订阅状态变化
counter.$subscribe((mutation, state) => {
console.log('状态变化了:', state.count);
});
6. 组合式 API 写法(推荐)
Pinia 支持 setup() 风格:
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
export const useUserStore = defineStore('user', () => {
const name = ref('Alice');
const age = ref(25);
const isAdult = computed(() => age.value >= 18);
function growUp() {
age.value++;
}
return { name, age, isAdult, growUp };
});
14、Vue中的 $ 方法
在 Options API 中,$ 主要用于访问 Vue 实例、全局方法 和 插件注入的属性。
1. 实例属性 & 方法
| 方法/属性 | 作用 | 示例 |
|---|---|---|
$data | 访问 data 对象 | this.$data.count |
$props | 访问 props | this.$props.message |
$refs | 获取模板 ref 注册的 DOM/组件 | this.$refs.myInput |
$el | 组件根 DOM 元素 | this.$el |
$parent | 父组件实例 | this.$parent.value |
$root | 根组件实例(通常是 App.vue) | this.$root.globalData |
$children | 子组件列表(不推荐,建议用 $refs) | this.$children[0] |
2. 全局工具方法
| 方法 | 作用 | 示例 |
|---|---|---|
$nextTick | DOM 更新后执行回调 | this.$nextTick(() => {}) |
$forceUpdate | 强制重新渲染组件(慎用) | this.$forceUpdate() |
$watch | 动态监听数据变化 | this.$watch('count', callback) |
$set | 响应式添加新属性(Vue 2 专用) | this.$set(obj, 'key', value) |
$delete | 响应式删除属性(Vue 2 专用) | this.$delete(obj, 'key') |
3. 路由相关(Vue Router)
| 方法 | 作用 | 示例 |
|---|---|---|
$route | 当前路由信息(路径、参数等) | this.$route.params.id |
$router | 路由跳转方法 | this.$router.push('/') |
4. 状态管理(Vuex)
| 方法 | 作用 | 示例 |
|---|---|---|
$store | 访问 Vuex 的 state/actions | this.$store.state.count |
5. 事件总线(Event Bus)
| 方法 | 作用 | 示例 |
|---|---|---|
$emit | 触发自定义事件 | this.$emit('event') |
$on | 监听事件(全局事件总线) | this.$on('event', callback) |
$off | 取消监听事件 | this.$off('event') |
15、Vue 3 中的 $ 方法
在 Vue 3 中,部分 $ 方法仍然可用,但 Composition API(<script setup>)推荐使用替代方式。
1. Options API(兼容 Vue 2 写法)
Vue 3 仍然支持 Vue 2 的 $ 方法,如:
this.$refs.myDiv;
this.$router.push('/');
this.$store.state.count;
2. Composition API(推荐写法)
在 <script setup> 中,$ 方法被替代为 函数式调用:
Vue 2 ($) | Vue 3 (Composition API) | 示例 |
|---|---|---|
this.$refs | ref() + 模板 ref | const myDiv = ref(null) |
this.$nextTick | import { nextTick } from 'vue' | await nextTick() |
this.$route | useRoute() | const route = useRoute() |
this.$router | useRouter() | const router = useRouter() |
this.$store | useStore()(Pinia) | const store = useStore() |
this.$emit | defineEmits() | const emit = defineEmits() |
示例对比
Vue 2(Options API) :
export default {
mounted() {
console.log(this.$refs.myDiv);
this.$nextTick(() => {
console.log('DOM 更新完成');
});
}
}
Vue 3(Composition API) :
<script setup>
import { ref, nextTick } from 'vue';
const myDiv = ref(null);
nextTick(() => {
console.log('DOM 更新完成');
});
</script>
<template>
<div ref="myDiv"></div>
</template>
关键区别总结
| 特性 | Vue 2 | Vue 3 (Composition API) |
|---|---|---|
$refs | this.$refs.myDiv | const myDiv = ref(null) |
$nextTick | this.$nextTick() | import { nextTick } |
$route | this.$route | useRoute() |
$router | this.$router | useRouter() |
$store | this.$store(Vuex) | useStore()(Pinia) |
$emit | this.$emit('event') | const emit = defineEmits() |
$set/$delete | 必需(Vue 2 响应式限制) | 不需要(Vue 3 自动响应式) |
总结
- Vue 2 的
$方法在 Vue 3 Options API 中仍然可用,但推荐迁移到 Composition API。 - Vue 3 Composition API 使用 函数式调用(如
useRouter()、ref())替代$方法。 - Pinia 替代 Vuex,不再依赖
$store,而是useStore()。 - Vue 3 自动响应式,无需
$set/$delete。
迁移建议:
- 新项目直接用 Vue 3 + Composition API + Pinia。
2、北京公司二
1、窗口适配
### 视口设置(viewport)
### 媒体查询(Media Queries)
### 弹性布局(Flexbox)
### 相对单位
- 使用vmin,rem、em、vw、vh等相对单位而非固定像素
# Vue移动端 / PC端适配解决方案:
postcss-px-to-viewport
配置生效后,原有的代码中
px在编译阶段被自动实时转换成vw视口单位,
2、原型链挂函数
function Person(name) {
this.name = name;
}
// 在原型上挂载方法
Person.prototype.sayHello = function() {
console.log(`Hello, my name is ${this.name}`);
};
const person = new Person('Alice');
person.sayHello(); // Hello, my name is Alice
3、function和箭头函数的区别
4、图片懒加载
this的指向不同,箭头函数的this指向父级
3、杭州公司三
1、图片懒加载
2、axios,axios传文件,
3、...展开运算符,深拷贝浅拷贝
4、本地存储
5、vue和react的区别
4、浙江公司四
1、重排和重绘
2、怎么触发跨域,跨越的概念
3、数组去重
4、虚拟dom
5、北京公司五
1、HR面自我介绍
6、北京小程序公司
1、元素居中,数组排序
7、深圳公司
1、服务端渲染
服务端渲染(SSR) 是指由服务器(Node.js、PHP、Java 等)生成完整的 HTML 页面,并直接返回给浏览器渲染,而不是由浏览器通过 JavaScript 动态生成内容。
2、选项式和组合式
3、跨域
跨域是指在浏览器中,当一个网页试图请求另一个不同源(协议、域名或端口不同)的资源时,浏览器会阻止该请求。这是由于浏览器的同源策略(Same Origin Policy)限制,旨在保护用户的安全,防止恶意网站窃取数据
8、杭州公司入职
经历八轮拷打最终入职250¥/D