周五面试题复盘
短期项目面试题
3-15号面试题复盘(问题都在目录中,答案点击相应的目录查看即可)
css怎么实现垂直居中
- Flexbox居中
使用CSS Flexbox布局可以轻松实现水平和垂直居中
.container{
display: flex;
justify-content: center;/*水平居中*/
align-items:center;/*垂直居中*/
}
<div class="container">
<div class="content">内容</div>
</div>
- Grid居中
CSS Grid也是提供了简单的居中方式
.container{
display: grid;
place-items: center; /*水平垂直居中*/
}
<div class="container">
<div class="content">内容</div>
</div>
- 绝对定位和transform
使用绝对定位和CSS transfrom 属性可以实现居中,但需要知道子元素的宽度和高度
.container{
position: relative;
}
.content{
position:absolute;
top: 50%;
left: 50%;
transform:translate(-50% , -50%); /*水平垂直居中*/
}
<div class="container">
<div class="content" style="width:200px; height:100px;">内容</div>
</div>
- text-align和line-height
对于行内元素或单行文本,可以使用text-align和line-height属性实现水平和垂直居中
.container{
text-align:center; /*水平居中*/
line-height: 200px; /*假设容器高度为200px*/
height:200px;/*垂直居中*/
overflow: hidden; /*隐藏溢出的部分*/
}
<div class="container">
<div class="content">内容</div>
</div>
- table-cell
使用表格单元格布局可以实现居中,但是这种方式比较古老, 且在现代布局中使用较少
.container{
display: table-cell;
text-align: center; /*水平垂直居中*/
vertical-align: middle;
}
<div class="container">
<div class="content">内容</div>
</div>
- 其他方法
还有一些其他方式,如使用padding或border来调整元素位置,但这些方法通常不如上述方法灵活和通用。
选择哪种居中方法取决于具体的布局需求和兼容性要求。flexbox和Grid是现代布局中推荐的居中方法,因为它们提供了强大的布局能力,且易于理解和维护。
跨域怎么实现
跨域(Cross-Origin Resource Sharing, CORS)是浏览器中的一种安全举止,他限制了不同源(协议、域名、端口)之间的资源共享。为了实现跨域请求,可以采取以下几种常见方法:
1. CORS头部设置
服务器可以通过设置http响应头来允许跨域请求。以下是一些重要的cors头部:
- Access-Control-Allow-Origin:指定哪些源可以访问资源。可以设置为具体某个域名,或者*表示允许任何源。
- Access-Control-Allow-Methods:指定允许的http方法(如GET,POST,PUT,DELETE等)
- Access-Control-Allow-Headers:指定允许的http请求头
- Access-Control-Allow-Credentials:设置true时,允许携带认证信息(如cookies)
2. JSONP
JSONP(JSON with Padding)是一种利用
<script>
标签不受同源策略限制的特定性来实现跨域请求的技术。服务器返回的响应是一个函数调用,包裹着请求的数据。
3. 代理服务器
在服务器设置一个代理服务器,所有的客户端请求先发送到代理服务器,由代理服务器转发请求到目标服务器,并将响应返回给客户端。这样,客户端和代理服务器之间不会有跨域问题。
4.跨域资源共享(CORS)插件
在浏览器中按装CORS插件,如Chrome的CORS插件,可以临时绕过CORS限制,用于开发和测试。
5. WebSockets
对于实时通信,可以使用WebSockets协议,它不受同源策略的限制
6. postMessage API
这是HTML5中引入的一种安全的跨域通信方式,可以用于不同源之间的窗口通信,或者在不同的iframe之间传递消息。
7. Document.domain
如果两个页面的主域相同(例如 example.com和example2.com),可以通过设置document.domain='example.com’来实现跨域访问。
8. 用户代理脚本
用户可以在浏览器中按装脚本来修改http请求,添加必要的CORS头部,从而绕过跨域限制,这种方式需要用户手动参与。
实际应用实例
假设你需要从example.com发起一个跨域请求到api.example2.com,你可以在api.example2.com的服务器上设置CORS头部:
Access-Control-Allow-Origin:http://example.com
Access-Control-Allow-Methods: GET,POST,OPTIONS,DELETE
Access-Control-Allow-Headers: Content-Type
Access=Control-Allow-Credentials:true
在客户端,你可以直接发起AJAX请求:
fetch('http://api.example2.com/data',{
method:'GET',
headers:{
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error',error));
Cookie,Session,LocalStorage的区别是什么
Cookie 、Session、和localStorage是web开发中常用的客户端存储技术,他们用于在用户和服务器之间保持状态或数据,尽管他们的目的相似,但是它们在存储位置、生命周期、容量和使用场景方面有所不同:
Cookie:
- 存储位置: 存储在客户端浏览器中,
- 生命周期: 可以设置过期时间,过期自动删除;如果没有设置过期时间,那么在浏览器回话结束时(用户关闭浏览器)删除。
- 容量限制: 大小限制在4kb左右
- 安全性: 敏感信息(如密码)不应存储在cookie中,因为它们可以被客户脚本(如JavaScript)访问
- 跨域: cookie可以设置为与域名相关联,也可以设置为路径相关联,但默认情况下,cookie至于创建它的域相关联
- 使用场景: 主要用于会话管理、个性化设置、跟踪用户等。
Session:
1. 存储位置: Session可以存储在客户端(作为Cookie,通常是SessionID)或者服务器端
2. 生命周期: session的生命周期通常用于与用户的浏览器会话相关联,但也可以设置特定的过期时间
3. 容量限制: 没有固定的容量限制,取决于服务器的配置和资源
4. 安全性: session本身存储在服务器端,相对安全,但是传输过程中的session id 需要保护,可以防止会话劫持。
5. 跨域: session id 通常通过cookie存储在客户端,因此受cookie的跨域策略影响。
6. **使用场景:**用于服务器端会话管理,如登录验证、购物车管理等。
LocalStorage
1. **存储位置:**存储在客户端浏览器中,特定某个域名
2. 生命周期: 数据持久存在,直到被明确删除或浏览器清除数据。
3. 容量限制: 容量限制大约为5mb
4. 安全性: :虽然数据只存储在客户端,但它们可以被任何同源JavaScript代码访问,因此敏感信息谨慎存储。
5. **跨域:**使用localstorage是同源的,不同域名之间不能访问彼此的localstorage数据。
6. 使用场景: 用于存储不敏感的的本地数据,如用户偏好设置、离线应用的数据存储等。
总结对比:
- Cookie适用于需要在服务器和客户端之间共享的小型数据,如会话管理
Session适用于服务器端的会话管理,可以存储更大的数据量,但需要服务器资源
LocalStorage适用于客户端的持久化数据存储,不需要跨域共享,且不涉及服务器端的存储。
节流中重绘的出发条件
节流(Throttling)是一种优化技术,用于控制时间触发的频率。在前端开发中,尤其是在处理窗口缩放、滚动时间或高频触发的事件(如resize、scroll)时,节流可以减少不必要的计算和重绘,从而提高性能。
节流的重绘出发条件通常基于以下几个原则:
- 时间间隔: 节流函数会设置一个最小时间间隔,只有当两次触发的时间间隔超过这个设定值时,事件处理函数也只会每100毫秒执行一次。
2.**请求动画帧(RequestAnimationFrame)😗*在某些情况下,开发者可能会选择使用requestAnimationFrame来作为节流的触发条件。这意味着事件处理函数会在浏览器的下次重绘之前执行,这样可以确保事件处理函数的执行与浏览器的渲染周期同步。
3.**事件完成:**在某些节流实现中,事件处理函数会在事件停止触发后的最后一个事件间隔后执行。例如,如果用户停止滚动,节流函数会在最后一次事件滚动后的设定时间间隔后执行处理函数。
4.**条件触发:**有时候,截留函数会根据特定的条件来决定是否执行事件处理函数。例如,只有当滚动距离超过一定阈值时,才会触发重绘。
以下时一个简单的节流函数实现示例,使用时间间隔作为触发条件:
function throttle(func,delay){
let inThrottle;
return function(){
const context = this;
const args = arguments;
if (!inThrottle){
func.apply(context.args);
inThrottle = true;
setTimeout(()=> inThrottle = false,delay);
}
};
}
//使用
window.addEventListener('scroll',throttle(handleScroll,100));
在这个例子中,handleScroll函数会在滚动事件触发后的100毫秒内只执行一次,如果用户在100毫秒内连续滚动,handleScroll函数会等到滚动停止100毫秒后才会执行。
通过这种方式,节流可以有效的控制事件处理函数的执行频率,减少不必要的重绘和计算,从而优化页面的性能。
箭头函数和普通函数的区别
箭头函数(Arrow functions)是ES6引入的一种新的函数语法,它提供了一种更简洁的方式来编写函数表达式。箭头函数与普通函数(也成为传统函数或方法)在语法和功能上有一些显著的区别:
语法区别:
- **箭头函数:**使用=>语法,更短的函数声明方式。
const myFunction = (param1,param2)=> {
//函数体
return param1 + param2;
};
- **普通函数:**使用function关键字和圆括号包围参数。
function myFunction(param1,param2){
//函数体
return param1 + param2;
}
功能区别:
- this绑定:
- 箭头函数不绑定自己的this,他们会捕获其所有上下文的this值,作为自己的this值。
- 普通函数有自己的this绑定,this的值取决于函数的调用方式。 - arguments对象:
- 箭头函数没有自己的arguments对象。
- 普通函数有自己的argument对象,包含了函数调用时传入的所有参数。 - super关键字:
- 箭头函数蹦年使用super关键字。
- 普通函数可以正常使用super关键字,尤其时在构造函数中。 - new关键字和构造函数:
- 箭头函数不能使用new关键字,不能作为构造函数
- 普通函数可以使用new关键字创建实例,可以作为构造函数。 - 原型属性:
- 箭头函数没有prototype属性。
- 普通函数没有prototype属性,可以添加方法 - 方法定义:
- 箭头函数不能使用prototype方法定义
- 普通函数可以通过prototype方法定义方法 - 生成方法:
- 箭头函数不能作为Generator函数使用, 不能使用yield关键字
- 普通函数可以作为Generator函数,使用yield关键字。
使用场景:
- 当你需要要给没有自己this绑定的函数时,获取需要一个更简洁的函数表达式时,箭头函数时一个好选择。
- 当你需要使用new关键字、arguments对象、super关键字或者需要定义可枚举的属性时,应该使用普通函数。
for…in 和 for…of的区别
for…in 和 for…of是JavaScript中遍历集合(如数组、对象、Map、Set等)的两种不同的循环结构。它们在语法和使用场景上有一些关键的区别:
for…in循环:
- 遍历对象属性:
for…in 用于遍历一个对象的所有可枚举属性(包括原型链上的属性)。const obj = {a:1,b:2}; for (const key in obj){ console.log(key);//输出: ’a‘,'b' }
- 返回键名:
for…in 循环变量得到的是对象属性的键名(key),而不是属性值。 - 不保证顺序:
for…in 不保证属性的遍历顺序,通常按照插入顺序,但依赖于具体JavaScript引擎的实现。 - 不适用于迭代数组:
for…in 循环不适用于数组,因为它会遍历数组的所有属性,包括可能的原型链上的属性,导致循环次数不可预测。
for…of循环:
- 迭代器协议:
for…of用于遍历实现了迭代器协议的对象,如数组、Map、Set、字符串等。const arr = [1,2,3]; for(const value of arr){ console.log(value);//输出:1,2,3 }
- 返回值:
for…of 循环变量得到的是集合中的当前值。 - 保证顺序:
for…of 循环保证按照插入顺序遍历集合中的元素。 - 适用于数组:
for…of循环是为数组设计的,可以安全的用于数组的遍历。
总结:
- 如果你需要遍历一个对象的所有属性,使用 for…in
- 如果你需要遍历一个集合的元素,特别是数组,使用for…of
- for…of是更现代的语法,适用于ES6迭代器协议,通常推荐用于数组和其他可迭代对象的遍历。
- for…in由于其限制和不稳定性,通常不推荐用于数组的遍历,但在遍历对象属性时仍然有用。
在使用for…in时,需要注意对象属性的枚举顺序可能会受到原型链的影响,因此在需要确定顺序的情况下,可能需要额外的逻辑来处理。而for…of则提供了一种更简洁、更安全的方式来遍历集合。