美团春招面试

  1. js数据类型有哪些?基本数据类型和引用数据类型的区别?
  2. js作用域有哪些?
  3. 深拷贝和浅拷贝的区别?如何对数组进行深拷贝?
  4. 什么数据存在对象中,什么数据存在prototype中
  5. 如何判断A是不是B的实例
  6. this的指向?如何改变this的指向?
  7. 什么是原型链?原型链的终点?Function.prototype指向哪?
  8. 异步编程的方法
  9. 说一下promise
  10. promise如果后面有多个.then怎么传值
  11. async await怎么捕获异常?
  12. async await的底层原理?generator的原理?
  13. http状态码
  14. 协商缓存的过程?协商缓存具体存在哪里?
  15. 浏览器本地存储的方式?cookie,localStorage,sessionStorage区别?它们会把数据存在哪?受不受同源策略制约?
  16. cookie常用的属性有哪些?
  17. vue2和vue3的区别?
  18. Object.defineProperty如何监听数组?为什么无法获取数组的变化?
  19. vue为什么要用data包裹属性
  20. vue生命周期?组件间生命周期的顺序?
  21. 如何实现界面的切换?如何定义路由?
  22. vuex是做什么的?vue组件间通信的方式有哪些?React组件间通信的方式有哪些?
  23. git常用命令?回滚怎么写?
  24. webpack是干什么的?
  25. webpack能处理什么类型的文件?不能处理什么类型的文件?
  26. 算法题:移动零

js数据类型有哪些?基本数据类型和引用数据类型的区别?

JS数据类型可以分为基本数据类型和引用数据类型。

其中基本数据类型包括:字符串(string)、数字(number)、布尔值(boolean)、空(null)、未定义(undefined),symbol(符号) 而引用数据类型则包括:对象(Object)

区别在于存储方式和赋值方式。基本数据类型的值直接存储在变量内,存在栈中,而引用数据类型的值存储的是该对象的内存地址。存在堆中

js作用域有哪些?

全局作用域:指的是定义在代码块外部、函数外部或者是模块外部的变量、函数等,它们拥有全局作用域。

局部作用域:指的是定义在代码块、函数或者是模块内部的变量、函数等,它们拥有局部作用域。

在ES6规范下,还引入了块级作用域的概念。块级作用域可以用花括号包裹一段代码,在这段代码内部定义的变量仅在此代码块内部有效,超出此范围后便会失效,不会影响其他代码块中的同名变量。

深拷贝和浅拷贝的区别?如何对数组进行深拷贝?

浅拷贝:将对象的引用复制给一个新对象,新对象和原对象引用的是同一个对象,修改一个对象的属性会影响另一个对象的属性。常见的浅拷贝方法有Object.assign()、扩展运算符(...)等。

深拷贝:将对象完全复制一份,新对象和原对象是两个独立的对象,修改一个对象的属性不会影响另一个对象的属性。常见的深拷贝方法有递归拷贝、JSON.parse(JSON.stringify())等。

以下是使用递归拷贝实现深拷贝的示例代码:

function deepCopy(source) {
  if (typeof source !== 'object' || source === null) {
    return source;
  }
  const target = Array.isArray(source) ? [] : {};
  for (const key in source) {
    if (Object.prototype.hasOwnProperty.call(source, key)) {
      target[key] = deepCopy(source[key]);
    }
  }
  return target;
}

什么数据存在对象中,什么数据存在prototype中

只要是对象的独有属性和方法,就应该定义在对象本身上

而对于一些多个对象需要共享的属性和方法,可以将它们定义在对象的原型(prototype)对象上。这样,多个对象就可以共享这些属性和方法,无需在每个对象上都定义一遍

一般来说,满足以下两点之一的属性或方法,应该定义在对象的原型对象上:

  1. 多个对象需要共享它;
  2. 它需要被继承。

如何判断A是不是B的实例

可以使用instanceof运算符来判断一个对象是否为某个构造函数的实例obj instanceof Object

this的指向?

this是一个特殊的关键字,它指向函数当前被调用时的上下文对象。this的具体指向取决于函数的调用方式。

  1. 作为对象方法调用时,this指向该对象;
  2. 作为普通函数调用时,this指向全局对象(在浏览器中通常是window对象,在Node.js中是global对象);
  3. 作为构造函数调用时,this指向新创建的对象;
  4. 使用call或apply方法调用时,this指向指定的对象;
  5. 箭头函数的this指向当前代码所在的上下文。

如何改变this的指向?

  1. call方法:用于调用一个函数,并且指定函数体内this对象指向;使用call方法可以立即调用函数,同时指定函数内部的this指向特定对象。
function sayHello() {
  console.log(`Hello, my name is ${this.name}.`);
}
const obj = { name: 'jack' };
sayHello.call(obj); // Hello, my name is jack.

  1. apply方法:与call方法类似,用于调用一个函数,并且指定函数体内this对象指向。apply方法与call方法的区别只是传递参数的方式不同
  2. bind方法:用于创建一个新函数,并且指定新函数体内this对象指向。在调用bind方法后,它会返回一个新函数,再次调用新函数才会执行
function sayHello() {
  console.log(`Hello, my name is ${this.name}.`);
}

const obj = { name: 'jack' };
const newFunc = sayHello.bind(obj);
newFunc(); // Hello, my name is jack.

什么是原型和原型链?原型链的终点?Function.prototype指向哪?

原型:每个函数都有一个 prototype(原型) 属性,这个属性是一个指针,指向一个对象,而这个对象包含某种特定类型的所有实例共享的属性和方法。

JavaScript 中所有的对象都是由它的原型对象继承而来。而原型对象自身也是一个对象,它也有自己的原型对象,这样层层上溯,就形成了一个类似链表的结构,这就是原型链

原型链是由原型对象组成的层次结构,它描述了JavaScript对象之间的继承关系。每个JavaScript对象的原型都指向它的继承原型,形成了一条链,即原型链。

原型链的终点是Object.prototype。所有对象的原型链都是从Object.prototype继承而来。如果在查找属性或方法时,最终到达了Object.prototype,还是没有找到,则返回undefined。

Function.prototype指向函数的原型对象。

什么是异步编程?异步编程的方法

异步编程是一种处理非阻塞I/O操作的技术,允许程序在某些操作执行的同时,执行其他操作,而不是等待这些操作执行完毕后才进行其他操作。

JavaScript中的异步编程可以通过回调函数、Promise、async/await、Generator函数等方式实现。

  1. 回调函数: 在函数调用的过程中传递一个函数作为参数,函数执行完毕后调用这个函数。回调函数虽然容易实现,但是嵌套过多会导致代码难以维护,产生回调地狱(Callback Hell)的问题。
  2. Promise: Promise是ES6中引入的一种异步编程方案。它是对回调函数的一种优化,可以解决回调地狱的问题。它的主要特点是提供了链式调用API,可以使用then()和catch()等方法让代码更加清晰和易于维护。
  3. async/await:async/await是一种基于Promise的语法糖,可以更好地解决回调地狱问题。async表示函数是异步的,await表示在等待异步操作完成后再继续执行。async/await提供了一种更加直观、流畅、易于理解的处理异步操作的方式。
  4. Generator函数+Promise:通过Generator函数的组合使用可以实现一种类似于async/await的效果。Generator函数通过yield关键字来暂停执行,然后通过next()方法继续执行。在Generator函数中,可以使用Promise来处理异步操作。
  5. 发布/订阅模式: 也称为观察者模式,通过定义一种一对多的依赖关系,当某个对象改变状态时,所有依赖它的对象都会得到通知并自动更新。

说一下promise

Promise 是异步编程的一种解决方案

承诺过一段时间会给你一个结果。promise有三种状态:pending(等待态),fulfiled(成功态),rejected(失败态);状态一旦改变,就不会再变。创造promise实例后,它会立即执行。

Promise是一种非常实用的异步编程技术,可以帮助我们更加优雅和高效地编写异步代码,避免多层回调函数嵌套的问题。

promise如果后面有多个.then怎么传值

Promise实例可以通过.then()方法链式调用多个回调函数,每个回调函数可以处理前一个回调函数的返回值,即通过return语句将值传递给下一个回调函数。

promise.then(function(value1) {
  // 处理 value1,并返回 value2
  return value2;
}).then(function(value2) {
  // 处理 value2,并返回 value3
  return value3;
}).then(function(value3) {
  // 处理 value3
});

Promise中的值是通过Promise的链式调用不断传递的,每个.then()方法的返回值可以作为下一个.then()方法执行的参数,从而实现值的传递和处理。

async await怎么捕获异常?

可以使用 try/catch 语句来捕捉异步操作中的异常

async function fetchData() {
  try {
    const response = await fetch('/api/data');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error(error);
  }
}

async await的底层原理?generator的原理?

async/await的底层原理是基于ES6中引入的Generator函数和Promise对象实现的。

Generator函数可以通过function*关键字定义,它返回一个可迭代对象,可以通过.next()方法一步一步执行函数中的代码,每次执行到yield语句时,函数暂停并返回一个yield表达式的值。可以通过.next()方法恢复函数执行并传递参数。例如:

http状态码

1xx:信息性状态码

  • 100:Continue(继续):客户端应继续其请求
  • 101:Switching Protocols(切换协议):服务器已经理解了客户端的请求,并将通过Upgrade消息头通知客户端采用不同的协议来完成这个请求

2xx:成功状态码

  • 200:OK(成功):请求已经成功处理
  • 201:Created(已创建):请求已经被实现,并且创建了新的资源
  • 202:Accepted(已接受):服务器已经接受了请求,但是尚未处理完成
  • 204:No Content(没有内容):请求已经成功处理,但是没有返回消息体

4xx:客户端错误状态码

  • 400:Bad Request(错误请求):客户端发送的请求无效
  • 401:Unauthorized(未授权):客户端请求未被授权访问该资源
  • 403:Forbidden(禁止访问):服务器拒绝响应客户端的请求
  • 404:Not Found(未找到):请求的资源不存在

5xx:服务器错误状态码

  • 500:Internal Server Error(内部服务器错误):服务器遇到了一个未曾预料的错误,无法完成客户的请求
  • 502:Bad Gateway(坏的网关):服务器作为网关或代理角色,未能及时从上游服务器收到响应
  • 503:Service Unavailable(服务不可用):服务器当前无法处理客户端的请求,一段时间后可能会恢复正常

什么是协商缓存?协商缓存的过程?协商缓存具体存在哪里?

协商缓存指的是客户端缓存中保存了一个资源的元数据; 当客户端发起请求时,会与服务器进行一次“协商”,如果服务器端判断该资源自上次请求后并未发生改变,服务器会返回 304 Not Modified,告诉客户端可以继续使用缓存中的资源,从而避免了不必要的数据传输,减轻了服务器的负担,提高了网页加载速度。

协商缓存的过程如下:

  1. 客户端第一次请求资源时,服务器返回资源并在响应头中添加一个 Last-Modified 标识。
  2. 客户端再次请求该资源时,客户端会在请求头中添加一个 If-Modified-Since 字段,该字段值为上次请求返回的 Last-Modified 值。
  3. 服务器端接收到请求后会根据 If-Modified-Since 字段和资源的最后修改时间进行比较,如果资源未被修改,则服务器返回 304 Not Modified 响应,客户端从缓存中获取该资源。

协商缓存存在客户端和服务器端,客户端通过浏览器缓存将资源保存在本地,避免再次发送请求;在服务器端,通过响应头的 Last-Modified 和 If-Modified-Since 字段进行通信,减少不必要的网络请求和数据传输。

cookie,localStorage,sessionStorage区别?它们会把数据存在哪?受不受同源策略制约?

  • Cookie 可以存储一些小型数据,如用户偏好设置、登录状态、购物车、用户行为等信息。
  • LocalStorage 可以存储大量的数据,数据可以长期保留,即使关闭了浏览器或重新启动电脑,数据仍旧存在。
  • SessionStorage 只存在当前会话中,当关闭浏览器或者重新打开时,数据就会被清空。

cookie常用的属性有哪些?

cookie常用的属性有以下几种:

  1. name和value: 表示cookie的名字和值,这是cookie中最基本的属性。
  2. domain: 指定cookie所属的域名,例如".google.com", 表示该cookie属于所有以".google.com"结尾的网站。
  3. path: 指定cookie的路径,例如"/account",表示该cookie只属于网站中/account路径下的页面。
  4. expires和max-age: 用于设置cookie的过期时间。expires设置的是一个具体的过期时间点,例如"Thu, 01 Jan 1970 00:00:01 GMT"。而max-age则设置的是cookie生存周期的秒数,例如"3600",表示该cookie会在3600秒后过期。
  5. secure: 表示cookie只能在通过HTTPS或者其他安全协议加密的连接中传输。
  6. HttpOnly: 限制了cookie只能通过HTTP和HTTPS进行访问,不能通过JavaScript等客户端语言进行访问,从而提高cookie的安全性。

vue2和vue3的区别?

Vue3 引入了组合式 API,替代 Vue2 的选项式 API,它使得组件的逻辑更清晰、更易于测试和组合。

vue2 的响应性主要依赖 Object.defineProperty 进行实现,但是 Object.defineProperty 只能监听 指定对象的指定属性的 getter 行为和 setter 行为;我们在 data 中声明了一个对象 person ,但是在后期为 person 增加了新的属性,那么这个新的属性就会失去响应性。想要解决这个问题其实也非常的简单,可以通过 Vue.$set 方法来增加 指定对象指定属性的响应性。但是这样的一种方式,在 Vue 的自动响应性机制中是不合理。

在 Vue3 中,Vue 引入了反射和代理的概念,所谓反射指的是 Reflect,所谓代理指的是 Proxy。我们可以利用 Proxy 直接代理一个普通对象,得到一个 proxy 实例 的代理对象。在 vue3 中,这个过程通过 reactive 这个方法进行实现。

Object.defineProperty如何监听数组?为什么无法获取数组的变化?

Object.defineProperty 可以用于监听对象属性的变化,但是不能直接监听数组的变化。

如果要监听到数组的变化,可以使用 Array.prototype 提供的一些方法,比如 push、pop、splice 等; 使用 Vue 提供的 Vue.set 或 $set 方法来实现数组响应式。

因为 Object.defineProperty 在监听一个对象的变化时,实际上是监听到了对象的某个属性的变化。而对于数组来说,它的某些操作(如 push、pop、splice 等)实际上是修改了数组本身的属性,而不是修改了某个已存在的属性的值。

vue为什么要用data包裹属性

组件是一个可复用的实例,当你引用一个组件的时候,组件里的data是一个普通的对象,所有用到这个组件的都引用的同一个data,就会造成数据污染。

将data封装成函数后,在实例化组件的时候,我们只是调用了data函数生成的数据副本,避免了数据污染。

Vue 在初始化时会检测组件实例对象上所有声明的属性,将这些属性添加到 Vue 的响应式系统中。而在组件实例对象上直接声明属性,这些属性不会被添加到响应式系统中,也就不具有响应式的能力。

vue生命周期?组件间生命周期的顺序?

如何实现界面的切换?如何定义路由?

可以使用 <router-link> 标签或 router.push 方法来跳转到对应的页面。

引入vue-router库来定义路由,包括路由的路径和对应的组件

vuex是做什么的?vue组件间通信的方式有哪些?React组件间通信的方式有哪些?

Vuex(Vue.js 中央状态管理模式)是一个专为 Vue.js 应用程序开发的状态管理库。它采用集中式存储管理全局共享状态,可以让我们更好地组织、维护和管理 Vue.js 应用程序中的状态。

Vuex 的核心概念分为以下几个部分:

  • State:状态存储,即数据存储的地方。Vue 组件中的 data 存储的数据仅为组件自身的,Vuex 的 State 存储的数据全局共享。
  • Getters:类似于 Vue 的计算属性,用于派生出一些状态,并且会缓存状态。
  • Mutations:修改状态的方式,必须是同步函数。
  • Actions:异步地、复杂的、或者需要多个 Mutation 触发的状态修改操作。
  • Modules:将 Store 分割成各个模块,用于更好的管理项目中庞大、复杂的状态。

Vue 组件间通信有以下几种方式:

  1. 父子组件通信:父组件通过props将数据传递给子组件,子组件通过$emit触发自定义事件回传数据
  2. 子父组件通信:子组件通过this.parent访问父组件实例,通过emit触发自定义事件回传数据
  3. 兄弟组件通信:通过一个事件总线(Event Bus)或者Vuex来实现,Event Bus 就是通过一个新的 Vue 实例来实现数据传输
  4. 跨级组件通信:通过provide/inject来实现,provide可以在祖先级别中注册一个变量,inject可以在子孙级别中注入

React 组件间通信也有以下几种方式:

  1. 父子组件通信:父组件通过props将数据传递给子组件,子组件通过回调函数回传数据给父组件
  2. 子父组件通信:父组件通过props将回调函数传递给子组件,子组件通过调用父组件传递的回调函数回传数据
  3. 兄弟组件通信:通过一个共同的父组件传递数据,或者通过Context API共享状态
  4. 跨级组件通信:通过Context API来实现,在祖先组件中创建一个Context,子组件可以通过Consumer订阅Context中的数据

git常用命令?回滚怎么写?

git init :将当前目录初始化为Git仓库
git add <file> :将文件添加到本地暂存区
git commit -m "message" :将暂存区的文件提交到本地仓库,并添加操作说明message
git push :将本地仓库内容推送到远程仓库
git pull :将远程仓库内容拉取到本地仓库
git clone :克隆远程仓库到本地

当需要回滚(即撤销)操作时,可以通过以下命令实现:

git reset:将文件从stage(即暂存区)中撤回到unstage(即工作区)

git reset --soft: 撤回commit,但不影响stage和工作区,可以使用git status查看变化
git reset --mixed: 撤回commit和stage,但不影响工作区,可以使用git status查看变化
git reset --hard: 撤回commit、stage和工作区,本地所有修改都会被删除,请谨慎使用

git revert:将指定commit的修改撤回(即创建一个新的commit来覆盖原有commit的修改)

git revert <commit-hash>: 撤回commit-hash对应的commit

webpack是干什么的?

Webpack是一个现代化的静态模块打包器,它将各种不同类型的文件(如js、css、图片等)视为一个模块,并将它们打包成最终的静态资源。Webpack的核心原理是将所有的资源都视为一个模块,并通过loader进行转换处理,最后将这些模块打包成一个或多个bundle。

Webpack的主要作用是优化前端资源加载,将多个文件打包成一个压缩文件,使得网页加载速度更快,用户体验更好。同时,Webpack还支持开发模式和生产模式的切换,支持开发过程中自动编译和热更新,以及支持代码分割和懒加载等高级特性,使得前端开发更加便捷和高效。

其他常用的插件有:

  • html-webpack-plugin: 用于自动生成HTML文件并将其加入Webpack打包后的结果中,可以同时处理CSS和JS文件并自动添加<link>和<script>标签。
  • css-loader: 用于将CSS文件转换为JavaScript模块,以便Webpack可以处理。
  • style-loader: 将CSS以<style>标签插入到HTML文件中。
  • babel-loader: 将ES6+的JavaScript代码转换为ES5的代码,以便Webpack可以处理。

webpack能处理什么类型的文件?不能处理什么类型的文件?

Webpack可以处理各种类型的文件,例如JavaScript、CSS、HTML、图片、字体等资源。Webpack通过使用loader来转译这些文件,将其转换为Webpack可以处理的模块。

Webpack可以处理大部分前端开发中遇到的文件类型。但是对于一些特殊的文件类型,例如PDF和Word文档等非常规的文件类型,Webpack可能并不能直接处理,需要借助其他工具或loader来进行支持。

算法题:移动零

可以使用双指针的方法解决,左指针指向已处理好的序列的尾部,右指针指向待处理序列的头部。遍历数组,当右指针指向的元素为0时,右指针向右移动1位,否则交换左右指针所指向的元素,左右指针同时向右移动1位。

function moveZeroes(nums) {
  let left = 0, right = 0;
  while (right < nums.length) {
    if (nums[right] !== 0) {
      // 交换左右指针所指向的元素
      let temp = nums[left];
      nums[left] = nums[right];
      nums[right] = temp;
      // 左右指针同时向右移动1位
      left++;
    }
    // 右指针向右移动1位
    right++;
  }
  return nums;
}
#大家都开始春招面试了吗##春招##前端面试##面试答案##美团#
真面经解析 文章被收录于专栏

根据真实面试经历盘点面试题目,总结面试经验,分类总结面试题目答案

全部评论
原型链的终点是Object.prototype。所有对象的原型链都是从Object.prototype继承而来。如果在查找属性或方法时,最终到达了Object.prototype,还是没有找到,则返回undefined。 这个最后是null吧
1 回复
分享
发布于 2023-05-11 22:24 广东
M
点赞 回复
分享
发布于 2023-05-09 22:50 上海
滴滴
校招火热招聘中
官网直投
深拷贝和浅拷贝的区别是什么?
点赞 回复
分享
发布于 2023-05-10 10:00 云南
感谢楼主还写了份答案
点赞 回复
分享
发布于 2023-05-10 13:59 广东
请问一下是哪个部门啊
点赞 回复
分享
发布于 2023-05-10 19:35 新加坡
感谢楼主
点赞 回复
分享
发布于 2023-06-07 17:16 湖北

相关推荐

12 72 评论
分享
牛客网
牛客企业服务