前端面试题详解整理98|跨域,登录认证,深浅拷贝,垂直居中,const,var,let元素实现隐藏方式,

62 阅读11分钟

字节前端一面

自我介绍
为什么选择前端

基础知识:

1.var let const的区别

在JavaScript中,varletconst 是用于声明变量的关键字,它们之间有以下几个区别:

  1. 作用域

    • var 声明的变量存在变量提升,其作用域为其声明的函数体内或全局作用域(如果在函数外声明)。在ES6之前,var 没有块级作用域的概念。
    • letconst 声明的变量存在块级作用域,即作用域为当前块(花括号 {} 内部)。使用 letconst 声明的变量不会发生变量提升。
  2. 重复声明

    • 使用 var 声明的变量可以被重复声明,而不会报错,且会覆盖之前的值。
    • 使用 letconst 声明的变量在同一作用域内不允许重复声明,否则会报错。
  3. 赋值

    • varlet 声明的变量可以修改其值。
    • const 声明的变量在声明时必须初始化,并且一旦赋值后,就不能再被修改,否则会导致错误。
  4. 全局对象属性

    • 使用 var 声明的全局变量会成为全局对象的属性,而 letconst 声明的变量不会。
  5. 暂时性死区

    • 使用 letconst 声明的变量存在暂时性死区(Temporal Dead Zone,TDZ),即在变量声明之前访问会导致引用错误。
  6. 适用场景

    • 推荐优先使用 const,然后使用 let,尽量避免使用 var
    • 当变量需要重新赋值时,使用 let
    • 当变量不需要重新赋值,并且希望保持不变时,使用 const

综上所述,varletconst 在作用域、重复声明、赋值、全局对象属性等方面存在差异,根据不同的需求选择合适的关键字来声明变量。

2.可以修改const声明的对象的属性吗,为什么

在JavaScript中,使用 const 声明的变量是不可重新赋值的,但是对于对象(包括数组)来说,const 仅限制了变量引用的地址不可改变,而不限制对象本身的属性值的修改。

换句话说,使用 const 声明的对象可以修改其属性值,但不能重新赋值为另一个对象。这是因为 const 声明的变量本身指向的内存地址是不可变的,但对象本身并没有被冻结,其属性值仍然可以被修改。

举个例子:

const obj = { name: 'John', age: 30 };

// 可以修改对象的属性值
obj.age = 40;

console.log(obj); // 输出: { name: 'John', age: 40 }

// 但不能重新赋值为另一个对象
obj = { name: 'Alice', age: 25 }; // 报错:Assignment to constant variable.

总之,const 声明的对象的属性值是可以被修改的,但是不能重新赋值为另一个对象。

2.水平垂直居中的方式有哪些,手撕css代码

实现水平垂直居中的方式有多种,以下是几种常见的方式以及对应的CSS代码示例:

  1. 使用Flex布局
.container {
  display: flex;
  justify-content: center; /* 水平居中 */
  align-items: center; /* 垂直居中 */
}
  1. 使用绝对定位和transform属性
.container {
  position: relative;
}

.centered {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
  1. 使用Flex布局的伸缩性
.container {
  display: flex;
}

.centered {
  margin: auto; /* 垂直水平居中 */
}
  1. 使用网格布局
.container {
  display: grid;
  place-items: center; /* 水平垂直居中 */
}
  1. 使用表格布局
.container {
  display: table;
  width: 100%;
  height: 100%;
}

.centered {
  display: table-cell;
  text-align: center; /* 水平居中 */
  vertical-align: middle; /* 垂直居中 */
}

这些方法各有特点,可以根据实际需求和浏览器兼容性选择合适的方式来实现元素的水平垂直居中。

53.元素实现隐藏的方式有哪些,都有什么区别

在前端开发中,实现元素隐藏的方式有多种,主要包括CSS样式和JavaScript方法,它们各有不同的特点和适用场景。以下是常见的元素隐藏方式及其区别:

  1. CSS display 属性

    • display: none;:通过设置元素的 display 属性为 none,完全隐藏元素,并且不占据页面空间。隐藏后的元素对布局不产生任何影响,即使是包含了文档流中的其他元素。
    • 区别:display: none; 是完全隐藏元素,对布局影响最小,但隐藏后无法通过JavaScript直接访问该元素。
  2. CSS visibility 属性

    • visibility: hidden;:通过设置元素的 visibility 属性为 hidden,元素被隐藏但仍然占据页面空间。隐藏后的元素仍保留原有的布局,仅不可见。
    • 区别:visibility: hidden; 是隐藏元素但保留其原有的布局空间,可以通过JavaScript直接访问该元素,适用于需要在布局中占位但暂时不显示的情况。
  3. CSS opacity 属性

    • opacity: 0;:通过设置元素的 opacity 属性为 0,使元素完全透明,但仍然占据页面空间。
    • 区别:opacity: 0; 是通过设置元素的透明度实现的,元素仍然占据页面空间,并且保留其原有的布局,但可以通过JavaScript直接访问该元素。
  4. CSS clip 属性

    • clip: rect(0, 0, 0, 0);:通过设置元素的 clip 属性来剪切元素的显示区域,将元素的显示区域设置为一个空白区域,达到隐藏元素的效果。
    • 区别:clip 属性一般用于裁剪元素的显示区域,隐藏元素的效果不如 display: none;visibility: hidden; 直观,并且不常用于隐藏元素。
  5. JavaScript操作DOM

    • 通过JavaScript动态修改元素的 style 属性或者添加/移除元素的CSS类来控制元素的显示和隐藏。
    • 使用 JavaScript 操作 DOM 可以实现更复杂的隐藏逻辑,例如根据用户交互、条件判断等动态控制元素的显示和隐藏。

这些隐藏方式各有特点,根据实际需求选择合适的方式进行元素隐藏。

4.深浅拷贝区别,手撕深拷贝

浅拷贝和深拷贝是针对对象(包括数组、函数等)的复制操作而言的。它们的区别在于复制的程度,以及对于复杂对象内部的引用类型的处理方式。

  1. 浅拷贝(Shallow Copy)

    • 浅拷贝只复制了对象的第一层,对于对象内部的引用类型,复制的是其引用地址,而不是对象本身。换句话说,浅拷贝创建了一个新的对象,但是这个新对象的内部仍然包含了原始对象内部引用类型的引用。
    • 常见的浅拷贝方法有:Object.assign()、扩展运算符(...)、Array.prototype.slice()等。
  2. 深拷贝(Deep Copy)

    • 深拷贝会递归地复制对象的所有层级,包括对象内部的引用类型,而不仅仅是第一层。深拷贝生成的新对象与原始对象完全独立,互不影响。
    • 实现深拷贝的方法较为复杂,需要考虑对象的所有可能嵌套结构,确保每个对象都被正确地复制。常见的深拷贝方法有手动递归复制、JSON.parse(JSON.stringify(obj))、使用第三方库如lodash的深拷贝方法等。

以下是手撕实现一个简单的深拷贝的示例代码:

function deepCopy(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj; // 如果是基本类型或null,则直接返回
  }

  // 创建一个新的对象或数组,根据原始对象的类型决定
  const newObj = Array.isArray(obj) ? [] : {};

  // 递归地复制原始对象的每个属性或元素
  for (let key in obj) {
    if (Object.hasOwnProperty.call(obj, key)) {
      newObj[key] = deepCopy(obj[key]);
    }
  }

  return newObj;
}

这个实现方式通过递归地遍历对象的属性或数组的元素,对每个属性或元素进行深度复制,从而实现了一个简单的深拷贝函数。需要注意的是,这种简单的实现方式可能存在性能问题和循环引用的风险,实际项目中建议使用成熟的深拷贝库或者更复杂的手动实现方式来确保拷贝的准确性和性能。

5.跨域是什么引起的,用什么方法实现跨域

跨域是指在浏览器的同源策略下,一个网页的文档或脚本试图获取另一个网页的资源,但是两者的域名、端口、协议不同,因此被浏览器阻止的情况。同源策略是浏览器安全策略的一部分,其限制了一个源(协议 + 域名 + 端口)的文档或脚本如何与另一个源的资源进行交互。

跨域问题的主要原因是浏览器的同源策略,它限制了浏览器中不同源的页面间的交互。当页面尝试从一个源加载另一个源的资源时(例如通过 Ajax 请求或者动态创建 <script> 标签加载脚本),浏览器会拒绝这种行为,以防止恶意网站获取用户的敏感信息。

为了实现跨域请求,可以采用以下几种方法:

  1. JSONP

    • JSONP(JSON with Padding)是一种利用 <script> 标签的 GET 请求实现跨域数据传输的方法。通过在请求 URL 中指定一个回调函数名,服务器返回一个 JavaScript 函数调用,该函数包含需要的数据作为参数。
  2. CORS(跨域资源共享):

    • CORS 是一种允许服务器在响应中携带特定的 HTTP 头部,从而允许跨域请求的机制。当客户端发起跨域请求时,服务器可以通过设置 Access-Control-Allow-Origin 头部来指定允许访问的域名,从而实现跨域资源共享。
  3. 代理服务器

    • 可以在服务器端设置代理服务器,将客户端的请求转发到目标服务器,然后将响应返回给客户端。由于服务器间的通信不受同源策略的限制,因此可以通过代理服务器实现跨域请求。
  4. WebSocket

    • WebSocket 是一种在客户端和服务器之间建立持久连接的通信协议,它可以在浏览器中与不同源的服务器进行双向通信。由于 WebSocket 不受同源策略的限制,因此可以用于实现跨域通信。
  5. 跨域资源嵌入

    • 可以通过将资源嵌入到同一个域中的页面中来避免跨域问题,例如将跨域的图片、字体等资源先下载到本地服务器上,然后通过相对路径在同源页面中引用这些资源。

这些方法各有优缺点,具体选择取决于项目需求、技术栈和安全考虑。

6.nodejs有了解过吗(我说了解不多,就没多问)
7.除了react还用过什么框架

项目:
8.用户登录部分的功能是怎么实现的
用户登录功能的实现通常涉及以下几个步骤:

  1. 用户表单输入

    • 用户在登录页面输入用户名和密码。
  2. 表单验证

    • 在提交登录请求之前,需要对用户输入的用户名和密码进行验证,通常包括验证用户名是否存在、密码是否符合规范等。
  3. 发送登录请求

    • 将验证通过的用户名和密码发送到后端服务器进行验证。可以使用 AJAX、Fetch API 或者基于表单的传统提交方式发送请求。
  4. 后端验证

    • 后端服务器接收到登录请求后,需要验证用户名和密码的正确性。通常会查询数据库来验证用户的身份信息,并生成一个包含用户信息的认证凭据(例如 JSON Web Token)。
  5. 认证凭据返回

    • 如果用户名和密码验证成功,后端会生成一个认证凭据,并将其返回给前端。这个认证凭据通常包含用户的身份信息,以及用于后续请求验证的令牌。
  6. 前端存储认证凭据

    • 前端收到认证凭据后,通常会将其存储在客户端,例如使用浏览器的本地存储(LocalStorage 或者 SessionStorage)或者浏览器的 Cookie。
  7. 登录状态维护

    • 在用户成功登录后,前端通常会维护一个登录状态,以便在用户进行其他操作时知道用户的身份信息。
  8. 访问受限资源

    • 用户成功登录后,可以访问受限资源,例如用户个人信息、购物车、订单等。在访问受限资源时,前端通常会携带认证凭据,以便后端验证用户的身份。
  9. 处理登录失败

    • 如果登录失败(例如用户名或密码错误),前端通常会向用户显示相应的错误信息,让用户重新输入。

以上是用户登录功能的一般实现流程。具体实现细节会根据项目的需求和技术栈有所不同。