目录
CSS
-
opacity: 0
、visibility: hidden
、display: none
这三者有什么区别?-
opacity: 0
:
- 设置元素的透明度为 0,元素仍然存在于页面中,占据空间,但完全透明,用户不可见,且仍可操作。
-
visibility: hidden
:
- 隐藏元素,但元素仍占据空间,无法看到,但可以接受 JavaScript 操作(如点击事件)。它不同于
display: none
,不会影响页面布局。
- 隐藏元素,但元素仍占据空间,无法看到,但可以接受 JavaScript 操作(如点击事件)。它不同于
-
display: none
:
- 完全移除元素,元素不再占据页面布局空间,也不可见。浏览器会将其完全忽略,任何与之相关的事件也不会被触发。
-
ES6
-
请简述 ES6 中 Symbol 类型的作用。
Symbol
是 ES6 新增的一种原始数据类型,表示独一无二的值。它常用于创建对象属性的唯一标识符,避免属性名冲突。Symbol
是不可变的、不可重复的。
const symbol1 = Symbol('description'); const symbol2 = Symbol('description'); console.log(symbol1 === symbol2); // false
-
ES6 中
WeakMap
的实际用途是什么? 和Map
有什么不同?-
WeakMap
与Map
类似,用于存储键值对,但它的键是 弱引用,即当键不再被使用时,垃圾回收器会自动清理相关的键值对,避免内存泄漏。 -
与
Map
的区别:
WeakMap
的键必须是对象,且键值对会在对象被垃圾回收时自动删除。Map
的键可以是任意类型。
let obj = {}; let weakmap = new WeakMap(); weakmap.set(obj, 'value'); obj = null; // obj 被垃圾回收,weakmap 中的条目也会被清除
-
-
Promise 有几种状态?
- Pending(等待):Promise 处于初始状态,操作尚未完成。
- Fulfilled(已完成):操作成功完成,并返回结果。
- Rejected(已拒绝):操作失败,返回错误。
let promise = new Promise((resolve, reject) => { // Some async operation resolve('Success'); });
-
请使用解构赋值,实现两个变量值的交换。
let a = 5; let b = 10; [a, b] = [b, a]; console.log(a, b); // 10 5
综合
-
webpack 中 loader 和 plugin 的区别是什么?
-
Loader
:
- 用于处理文件的转换,允许 Webpack 处理非 JavaScript 文件(如
.css
,.scss
,.html
等)。它会在 Webpack 构建过程中转换文件,通常是在模块编译阶段使用。 - 示例:
babel-loader
(将 ES6 转换为 ES5)、style-loader
(将 CSS 嵌入 JS 文件)。
- 用于处理文件的转换,允许 Webpack 处理非 JavaScript 文件(如
-
Plugin
:
- 用于扩展 Webpack 的功能,通常在构建完成之后运行,处理代码压缩、资源优化等。
- 示例:
HtmlWebpackPlugin
(生成 HTML 文件并自动引入打包后的文件)、UglifyJsPlugin
(压缩 JS 文件)。
-
-
简述下 SASS 和 LESS 的相似与不同点。
-
相似点
:
- SASS 和 LESS 都是 CSS 预处理器,允许使用变量、嵌套规则、混入(mixin)等功能,增强 CSS 的可维护性和可读性。
-
不同点
:
- 语法:SASS 支持两种语法:一种是带有大括号的语法(
.scss
),另一种是没有大括号和分号的语法(.sass
)。LESS 只有一种语法。 - 功能:SASS 提供了更多高级功能,如控制指令(如
@if
,@for
)等。
- 语法:SASS 支持两种语法:一种是带有大括号的语法(
-
-
简述下常用的排序算法有哪几种,各自的原理是什么?
- 冒泡排序(Bubble Sort):通过多次比较相邻元素,逐步将较大的元素“冒泡”到数组的末端。
- 选择排序(Selection Sort):每次选择未排序部分中的最小值,与当前元素交换位置。
- 插入排序(Insertion Sort):通过遍历数组,将每个元素插入到已排序的部分中。
- 快速排序(Quick Sort):选择一个基准元素,将数组分成两部分,一部分小于基准,一部分大于基准,然后递归排序。
- 归并排序(Merge Sort):通过分治法,将数组分成两部分,分别排序,然后合并。
TypeScript
-
TS 中如何在从子类调用到父类的构造函数?
- 使用
super()
来调用父类的构造函数。
class Animal { constructor(public name: string) {} } class Dog extends Animal { constructor(name: string) { super(name); // 调用父类的构造函数 } }
- 使用
-
简述下 Omit 类型。
Omit<T, K>
用于从类型T
中排除掉键K
,生成一个新类型。
type Person = { name: string; age: number; gender: string; }; type PersonWithoutAge = Omit<Person, 'age'>; // { name: string, gender: string }
-
什么是装饰器,它有什么用,如何使用?
- 装饰器是 ES7 提案中的一个特性,用于对类、方法、属性等进行修改和扩展。它允许你通过注解的方式对代码进行增强。
- 装饰器可以用于:
- 类装饰器:修改类的行为。
- 方法装饰器:修改方法的行为。
- 属性装饰器:修改属性的行为。
- 使用方法:
function log(target: any, propertyName: string) { console.log(`${propertyName} is called`); } class Person { @log sayHello() { console.log('Hello'); } }
-
any
和unknown
类型有什么区别?any
:表示任意类型,可以赋值给任何类型的变量,且编译时不会报错。unknown
:也表示任意类型,但在使用unknown
类型之前,必须进行类型检查。
let a: any = 5; let b: unknown = 5; a = "string"; // 正常 b = "string"; // 正常 // b.toUpperCase(); // 编译报错,需要类型检查
-
type
关键字的作用是什么?type
用于定义类型别名,允许你为一种类型创建一个别名,可以是基本类型、联合类型、交叉类型、函数类型等。
type StringOrNumber = string | number; type Person = { name: string, age: number };
Vue
-
Vue 组件间如何通信?
- 父子组件通信:父组件通过
props
向子组件传递数据,子组件通过$emit
向父组件传递事件。 - 兄弟组件通信:通过一个公共的父组件或使用 Vuex。
- 跨组件通信:使用 Vuex 或事件总线(
bus
)来实现。 - 自定义事件:子组件通过
$emit
向父组件发送事件,父组件通过监听事件处理数据。
<child-component @change="handleChange" />
- 父子组件通信:父组件通过
2. Vue 中 key 值的作用是什么?
key
是 Vue 在虚拟 DOM 中用于 唯一标识 每个节点的属性,可以帮助 Vue 高效更新 DOM。- 在
v-for
列表渲染中,key
主要用于优化 Diff 算法,避免不必要的重新渲染,提高性能。 - 如果不设置
key
,Vue 可能会复用元素,导致意想不到的 UI 问题。
示例:
<li v-for="item in list" :key="item.id">{{ item.name }}</li>
- 这里
key="item.id"
确保 Vue 在更新列表时能正确识别每个li
。
3. Vue 组件中的 data 为什么是一个函数?
- 在 Vue 组件中,
data
必须是 返回对象的函数,而不是直接写一个对象。 - 这样可以保证每个组件实例都有自己独立的数据,防止数据共享导致的意外修改。
示例:
export default {
data() {
return {
message: "Hello Vue",
};
},
};
如果 data
是一个对象,而不是函数,则所有组件实例共享同一个 data
,导致数据互相影响。
JavaScript
1. 什么是防抖和节流?有什么区别?
- 防抖(Debounce):如果在
n
毫秒内再次触发事件,则重新计时,只有当n
毫秒内没有触发事件,才执行。 - 节流(Throttle):规定
n
毫秒内最多执行一次事件处理函数。
示例:
// 防抖
function debounce(fn, delay) {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
// 节流
function throttle(fn, delay) {
let lastTime = 0;
return function (...args) {
let now = Date.now();
if (now - lastTime > delay) {
fn.apply(this, args);
lastTime = now;
}
};
}
2. call
和 apply
的区别是什么?
-
call
和apply
作用相同,都是用于修改函数的this
指向,并立即执行。 -
区别
:
call(thisArg, arg1, arg2, ...)
传递参数时,参数列表 形式。apply(thisArg, [arg1, arg2, ...])
传递参数时,数组 形式。
示例:
function greet(name, age) {
console.log(`Hello ${name}, you are ${age} years old`);
}
greet.call(null, "Alice", 25);
greet.apply(null, ["Alice", 25]);
3. for...in
和 Object.keys()
的区别是什么?
-
for...in
:
- 遍历对象的 可枚举属性(包括原型链上的可枚举属性)。
-
Object.keys()
:
- 返回对象自身的 可枚举属性(不包括原型链上的属性)。
示例:
const obj = { a: 1, b: 2 };
Object.prototype.c = 3;
for (let key in obj) {
console.log(key); // a, b, c
}
console.log(Object.keys(obj)); // ["a", "b"]
4. ===
和 ==
的区别
==
(宽松相等):会进行 类型转换,然后比较值是否相等。===
(严格相等):不会进行类型转换,必须值和类型都相等。
示例:
console.log(1 == "1"); // true (类型转换)
console.log(1 === "1"); // false (不同类型)
5. 如何判断一个对象是否为数组?
方法 1:Array.isArray()
(推荐)
console.log(Array.isArray([])); // true
console.log(Array.isArray({})); // false
方法 2:instanceof
console.log([] instanceof Array); // true
6. 代码输出结果
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
输出:
0
1
2
解析:
let
具有块级作用域,每次循环i
都是一个新的变量,不会影响下一个循环。
7. 代码输出结果
console.log(+true);
输出:
1
解析:
+true
等价于Number(true)
,true
转换为1
。
8. 代码输出结果
const promise = new Promise((resolve, reject) => {
console.log(1);
resolve();
console.log(2);
});
promise.then(() => {
console.log(3);
console.log(4);
});
输出:
1
2
3
4
解析:
console.log(1)
立即执行。resolve()
不会阻止 后面的console.log(2)
。promise.then()
是微任务,等同步代码执行完后再执行console.log(3)
和console.log(4)
。
总结
- Vue 的
key
用于优化 DOM 更新,data
需返回对象以保证实例独立性。 - 防抖 延迟执行,节流 限制频率。
call
和apply
作用相同,参数传递方式不同。===
不进行类型转换,==
进行类型转换。setTimeout
结合let
形成块级作用域,按顺序输出0, 1, 2
。+true
的结果是1
,因为true
转换为Number
。Promise
的.then()
是微任务,先执行同步代码再执行微任务。
希望这些答案对你有所帮助!🚀
问题解析与解答
9. 代码输出的结果
const promise = new Promise((resolve, reject) => (
resolve("success1");
reject("error");
resolve("success2");
));
promise
.then((res) => {
console.log("then:", res);
})
.catch((err) => {
console.log("catch:", err);
});
错误
new Praise
这个类不存在,应该是new Promise
。reject('error")
双引号错误,应该是reject("error")
。resolve("success1")
之后reject("error")
和resolve("success2")
不会执行,因为Promise
状态只会改变一次。
最终执行
const promise = new Promise((resolve, reject) => {
resolve("success1"); // 先执行 resolve
reject("error"); // 不会执行
resolve("success2"); // 不会执行
});
promise
.then((res) => {
console.log("then:", res);
})
.catch((err) => {
console.log("catch:", err);
});
输出
then: success1
- 原因:Promise 状态一旦改变就不会再变,
resolve("success1")
使Promise
进入fulfilled
状态,后续的reject("error")
和resolve("success2")
都不会执行。
10. 用 Promise 实现红绿黄灯交替亮灯
需求:
- 红灯 亮 3 秒
- 绿灯 亮 1 秒
- 黄灯 亮 2 秒
- 循环执行
代码实现
function red() {
console.log("red");
}
function green() {
console.log("green");
}
function yellow() {
console.log("yellow");
}
function delay(time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
function light() {
Promise.resolve()
.then(() => {
red();
return delay(3000);
})
.then(() => {
green();
return delay(1000);
})
.then(() => {
yellow();
return delay(2000);
})
.then(light); // 递归调用,形成循环
}
light();
输出
red
(3秒后)
green
(1秒后)
yellow
(2秒后)
(red 3s → green 1s → yellow 2s 循环)
解释:
delay(time)
返回一个Promise
,在time
毫秒后resolve
。light()
依次执行red()
→green()
→yellow()
,并递归调用自身,使灯不断循环亮起。
11. 实现一个数组去重的方法
方法 1:使用 Set
(推荐)
function uniqueArray(arr) {
return [...new Set(arr)];
}
console.log(uniqueArray([1, 2, 3, 3, 2, 1])); // [1, 2, 3]
Set
是 ES6 提供的无重复值集合,利用Set
直接去重。
方法 2:使用 filter()
function uniqueArray(arr) {
return arr.filter((item, index) => arr.indexOf(item) === index);
}
console.log(uniqueArray([1, 2, 3, 3, 2, 1])); // [1, 2, 3]
indexOf(item)
返回第一次出现的位置,如果当前位置index
和indexOf(item)
相等,说明是第一次出现,保留该值。
方法 3:使用 reduce()
function uniqueArray(arr) {
return arr.reduce((acc, cur) => {
if (!acc.includes(cur)) acc.push(cur);
return acc;
}, []);
}
console.log(uniqueArray([1, 2, 3, 3, 2, 1])); // [1, 2, 3]
reduce
逐步累加非重复元素。
总结
题目 | 关键点 | 代码示例 |
---|---|---|
Promise 状态问题 | Promise 状态一旦改变,不会再次变化 | 只执行第一个 resolve("success1") |
灯光交替亮起 | Promise + 递归调用 实现循环 | then(light) 递归执行 |
数组去重 | Set 最简洁,filter() 和 reduce() 可替代 | new Set(arr) |
总结
大家喜欢的话,给个👍,点个关注!给大家分享更多计算机专业学生的求学之路!
版权声明:
发现你走远了@mzh原创作品,转载必须标注原文链接
Copyright 2024 mzh
Crated:2024-3-1