该厂注册资本为1000万。
1. 项目经历
- 项目基本描述
基本介绍——外包——校企合作 - 项目做了哪些
答:UI做页面、公共组件、增删改查
2. 基础
1. div横向布局
- display: inline-block;
- float
- flex
- grid(grid-template-columns: auto auto;)
2. 页面有头有脚有侧边栏,怎么刚好高度合适
答:calc(100vh - )
3. 元素隐藏方法
4. ES6新增特性
-
块级作用域:引入了 let 和 const 关键字,可以声明块级作用域的变量和常量,替代了原来只有函数作用域和全局作用域的限制。
-
箭头函数:使用箭头(=>)定义函数,简化了函数的声明和使用,并且自动绑定了当前上下文的 this。
-
模板字符串:使用反引号(``)包裹字符串,可以在字符串中插入变量和表达式,更加灵活方便。
-
解构赋值:可以从数组或对象中提取值,快速创建变量或给变量赋值。
-
默认参数:函数的参数可以设置默认值,当调用函数时不传递该参数时,将使用默认值。
-
扩展运算符:使用三个点(…)可以将数组或对象进行展开,方便地进行合并或拷贝。
-
类和模块:引入了 class 关键字,可以使用面向对象编程的方式定义类和继承。同时,也支持模块化的导入和导出。
-
Promise:用于处理异步操作的对象,提供了更好的异步编程方式,避免了回调地狱。
-
简化对象字面量语法:可以在定义对象时省略冒号和函数关键字,简化了对象的书写。
-
简化迭代器和生成器:引入了新的迭代器和生成器协议,使得迭代和生成序列更加简单和可控。
-
模块化导入/导出:使用 import 和 export 关键字可以进行模块的导入和导出,方便模块化开发和代码复用。
-
Map 和 Set 数据结构:引入了 Map 和 Set 两种新的数据结构,提供了更灵活和高效的数据存储方式。
5. 闭包用处
- redux-dispatch
- 封装私有变量:通过闭包可以创建私有变量,只能在闭包内部访问,外部无法直接修改。这样可以保护数据的安全性。
function createCounter() {
let count = 0;
return {
increment: function() {
count++;
},
getCount: function() {
return count;
}
};
}
let counter = createCounter();
counter.increment();
console.log(counter.getCount()); // 输出 1
- 延迟执行函数:通过闭包可以延迟执行函数,即将函数作为返回值返回,从而实现在未来的某个时间点执行。
function delayExecution() {
setTimeout(function() {
console.log('延迟执行');
}, 2000);
}
delayExecution(); // 2秒后输出 "延迟执行"
- 函数记忆化:通过闭包可以缓存函数的计算结果,避免重复计算,提高性能。
function memoize(func) {
let cache = {};
return function(...args) {
let key = JSON.stringify(args);
if (cache[key]) {
return cache[key];
} else {
let result = func(...args);
cache[key] = result;
return result;
}
};
}
function expensiveCalculation(n) {
console.log('正在计算...');
return n * 2;
}
let memoizedCalculation = memoize(expensiveCalculation);
console.log(memoizedCalculation(5)); // 输出 "正在计算..." 和 10
console.log(memoizedCalculation(5)); // 只输出 10,不再进行计算
6. 比较Promise和async await。如何用Promise实现一个睡眠函数sleep?
角度:async await清晰易维护,Promise便于控制状态(resolve-fulfilled,reject,pending),有catch和finally,有all、allsettled等。
- Promise主要用于处理异步操作,它返回一个Promise对象,表示一个最终可能完成(并得到结果)的操作。Promise有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。一旦Promise的状态从pending变为fulfilled或rejected,它就不会再改变。Promise提供了then()和catch()方法来处理异步操作的结果或错误。
- 例如:使用fetch()、axios函数发起网络请求,返回一个Promise对象。然后使用then()方法处理返回的数据,如果数据解析成功,则输出数据;如果解析失败,则进入catch()方法处理错误。
- Async/await则是基于Promise实现的语法糖,它使异步代码的写法更加简洁易读。使用async关键字声明一个函数是异步的,然后在函数内部使用await关键字等待一个Promise对象解析完成。await只能在async函数内部使用。await关键字等待Promise对象解析完成。在try-catch块中处理异步操作的结果或错误,使得代码更加简洁易读。
- 睡眠函数:
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
7. 说说跨域,项目里有遇到过吗,怎么样能避免跨域,html哪些标签和属性是允许跨域的
- 什么是跨域? 出现原因及解决方法
- 允许跨域的标签:script、link、img、video、audio、frame、iframe、embed等具有src属性的标签,以及object(data属性)、applet(code属性)和css中的@font-face。
允许跨域的属性:img标签的src属性、link标签的ref属性以及script标签的src属性都不受同源策略限制。
主要用于引入外部资源,如样式表、脚本文件、图片等。需要注意的是,虽然这些标签和属性允许跨域,但浏览器的同源策略仍然会对请求进行限制。例如,浏览器只对XHR(XMLHttpRequest)请求有同源限制。
8.说说cookie、sessionStorage、localStorage的区别和应用场景。以及cookie有哪些属性?
- Cookie是一种服务器端存储数据的方式,它可以存储一些小量的数据在用户的浏览器上,并且数据可以在浏览器与服务器之间传递。它可以用来保存用户的登录状态,实现“记住我”功能等。但需要注意的是,由于Cookie存储空间较小,且有一定的数据类型限制(通常为文本格式),因此不能用来存储大量的数据。此外,用户可以通过设置浏览器来拒绝Cookie,因此使用Cookie需要考虑到兼容性和安全性。通常用于存储一些小量的数据,如用户登录状态、购物车信息等。
举例:例如,当用户登录一个网站时,可以将用户的登录状态存储在Cookie中,这样在下一次访问该网站时,就可以通过读取Cookie中的数据来判断用户是否已经登录,从而实现“记住我”功能。 - sessionStorage用于在同一个浏览器窗口/标签页的生命周期中存储数据。即使用户关闭了页面或刷新了页面,存储的数据也不会丢失。它通常用于存储临时数据,如表单数据、网页状态等。
举例:例如,当用户在一个表单中填写了信息并提交后,可以将表单数据存储在sessionStorage中,这样在用户刷新页面或返回表单时,可以重新读取存储的数据,保持表单的状态。 - localStorage与sessionStorage类似,但localStorage中的数据是永久保存的,即使用户关闭了浏览器或清空了浏览器数据,存储的数据也不会丢失。localStorage通常用于存储长期或永久性的数据,如用户的个性化设置、配置信息等。
举例:例如,一个天气预报应用可以将用户的城市设置为存储在localStorage中,这样即使在用户关闭浏览器后再次打开应用时,也可以根据用户的设置显示相应的天气信息。 - sessionStorage和localStorage都是Web存储的方式,它们允许在用户的浏览器上存储大量数据,且数据不会随着刷新或关闭浏览器而消失。不同的是,sessionStorage的数据在页面会话期间有效,而localStorage的数据则是长期保存的。因此,sessionStorage通常用于在同一个页面会话期间保存数据,比如用户填写的表单信息、临时缓存的网页内容等。而localStorage则通常用于长期保存用户的个性化设置、保存用户登录状态等。
- Cookie的属性,主要有以下几种:
- 名称:用于标识Cookie的标识符。
- 值:与Cookie关联的值,可以是任何字符串。
- 域:指定可以访问Cookie的域名。
- 路径:指定Cookie在服务器上的路径。
- 过期时间:设置Cookie的有效期。如果未设置,则会在浏览器关闭时过期。
- 安全标志:用于控制Cookie的安全性。如果设置了安全标志,则只有使用HTTPS协议才能访问该Cookie。
- HttpOnly标志:用于防止JavaScript访问Cookie,增加安全性。
9. 了解过TypeScript吗?有什么优点?
角度:
- 写代码时用IDE(Vscode)直接类型检查,减少运行时错误,并提高代码质量和可维护性。
- 类型推断。自动推断出变量和表达式的类型,减少了显式声明和类型转换的必要性。
- 易维护。
- 避免空指针导致的白屏。
3. 算法题
1.输出链表倒数第n个节点的值
要输出链表倒数第n个节点的值,可以使用双指针法来解决该问题。首先,定义两个指针,一个快指针和一个慢指针,初始时都指向链表的头节点。然后,将快指针向后移动n个节点。接下来,同时移动快指针和慢指针,直到快指针到达链表的末尾。此时,慢指针所指向的节点就是倒数第n个节点。
以下是代码示例:
function ListNode(val) {
this.val = val;
this.next = null;
}
function getNthFromEnd(head, n) {
let fast = head;
let slow = head;
// 将快指针向后移动n个节点
for (let i = 0; i < n; i++) {
if (fast === null) {
return null; // 链表长度不足n,返回null
}
fast = fast.next;
}
// 同时移动快指针和慢指针
while (fast !== null) {
fast = fast.next;
slow = slow.next;
}
return slow.val; // 返回倒数第n个节点的值
}
使用示例:
// 创建链表:1 -> 2 -> 3 -> 4 -> 5
let head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4);
head.next.next.next.next = new ListNode(5);
let n = 2; // 倒数第2个节点
console.log(getNthFromEnd(head, n)); // 输出 4
注意:此代码假设n大于0且小于等于链表的长度。如果链表的长度不足n,则返回null。
2. 找出数组中出现次数最多的数字
可以使用一个对象来记录每个数字出现的次数,然后遍历这个对象找出出现次数最多的数字。
function findMostFrequent(arr) {
let count = {};
let maxCount = 0;
let mostFrequent;
for (let num of arr) {
if (!count[num]) {
count[num] = 1;
} else {
count[num]++;
}
if (count[num] > maxCount) {
maxCount = count[num];
mostFrequent = num;
}
}
return mostFrequent;
}
let arr = [1, 2, 3, 2, 4, 1, 5, 2, 6, 2];
console.log(findMostFrequent(arr)); // 输出 2
4. 反问
Vue3、支付宝小程序、antd……