关于前端:前端面试题系列1

3次阅读

共计 7271 个字符,预计需要花费 19 分钟才能阅读完成。

1、已知如下对象,请基于 es6 的 proxy 办法设计一个属性拦挡读取操作的例子

要求实现去拜访指标对象 example 中不存在的属性时,抛出谬误:Property “$(property)” does not exist(2018 今日头条)

// 案例代码
const man = {
  name: 'jscoder',
  age: 22
}
// 补全代码
const proxy = new Proxy(...)
proxy.name // "jscoder"
proxy.age // 22
proxy.location // Property "$(property)" does not exist

答复:

const proxy = new Proxy(main, {get (target, property) {if (property in target) {return target[property];
    } else {throw Error(`Property "${property}" does not exist`)
    }
  }
});

2、红灯三秒亮一次, 绿灯一秒亮一次, 黄灯 2 秒亮一次

实现一个函数,如何让三个灯一直交替反复亮灯? (用 Promise 实现) 三个亮灯函数曾经存在:

function red() {console.log('red')
} // 3 秒
function green() {console.log('green')
} // 1 秒
function yellow() {console.log('yellow')
} // 2 秒

答复:

const timerFn = function (times, callback) {return new Promise((resolve, reject) => {setTimeout(() => {callback();
            resolve();}, times);
    });
};

async function repeatLights () {await timerFn(3000, red);
    await timerFn(1000, green);
    await timerFn(2000, yellow);
    repeatLights();}

repeatLights();

3、按程序写出控制台打印后果(2020 碧桂园)

var User = {
     count:1,
     action:{getCount:function () {return this.count}
     }
}
var getCount = User.action.getCount;
setTimeout(() => {console.log("result 1",User.action.getCount())
})
console.log("result 2",getCount())

答复:

result 2 undefined
result 1 undefined

4、简答 (字节跳动 二面)

  • 你感觉 typescript 和 javascript 有什么区别
  • typescript 你都用过哪些类型
  • typescript 中 type 和 interface 的区别

答复:

(1)TS 是 JS 的一个超集(扩大集),就是在 JS 的根底上多出一些扩大个性,包含:弱小的类型零碎、对 ES6+ 的良好反对,TS 最终会被编译为 JS 执行

  • JS 和 TS 都是 ECMAScript 的具体实现
  • TS 是动态类型,而 JS 是动静类型
  • TS 扩大了 JS 并且齐全容纳 JS
  • TS 须要编译,JS 不须要编译(除非须要兼容低版本运行环境)
  • JavaScript 由 Netscape 率先推出,当初次要由各大浏览器厂商实现
  • 而 TypeScript 目前由微软进行设计和保护

(2)原始类型: string / number / boolean / null / void / symbol
数组类型、对象类型、函数类型、元祖、枚举 enum、any 类型、Void 类型、接口 interfaces、类 class、泛型 generics

(3)typescript 中 type 和 interface 的区别
type 和 interface 相同点:

  • 都能够形容一个对象或函数
  • 都能够实现扩大 (extends) 性能,interface extends interface,type 通过穿插类型实现扩大

type 和 interface 不同点:

  • type 能够申明根本类型别名,联结类型,元组等类型,而 interface 不行;
  • interface 可能申明合并,而 type 不行;
  • 一般来说,定义类型时,能够用 interface 实现的就用 interface,不能就用 type

5、对 async/await 的了解,剖析外部原理

答复:

  • async/await 其实就是 generator 生成器的语法糖,它的呈现使得咱们编写异步代码更加简略不便,能够防止编写简单的 generator 函数,异步代码中再也没有回调函数,语法就像同步代码一样,是目前异步编程比拟完满的计划。
  • 外部原理:外部借助了 promise 和 generator 来实现。await 须要配合 async 来应用,就像 yield 须要配合 function * main () { ...} 中的 * 来应用一样,yield 前面能够追随一个 promise 实例,执行 main 函数能够失去一个 generator 实例 g,能够通过 g.next() 来管制 main 函数外部代码的执行程序,配合 g.next().value.then()g.next().done 就能实现 async/await 的成果。

6、async/await 如果左边办法执行出错该怎么办?(百度一面 2020)

答复:

// 能够通过 try catch 来捕捉谬误
async function main () {
    try {const articles = await ajax('/api/articles.json');
    } catch (error) {console.log(error);
    }
}

7、说一下 event loop 的过程?promise 定义时传入的函数什么时候执行?(小米 三面)

答复:

  • js 是单线程的,同一时间只能做一件事,两段 JS 不能同时执行,次要起因是要防止 DOM 渲染的抵触。解决方案就是异步,而异步编写的代码,没依照书写形式执行,callback 过多,导致可读性很差,难以了解,所以就呈现了 promise / async await。
  • event-loop 指事件轮询,是 js 实现异步的具体解决方案。同步代码,在主线程(调用栈 Call stack)中间接执行,压栈 - 弹栈。异步工作会顺次放入音讯队列(Queue)中,EventLoop 会监听调用栈和音讯队列,当调用栈中的代码执行完之后,它会拿音讯队列中的第一个工作放到调用栈执行,以此类推。
  • promise 定义时传入的函数,会在本次调用栈的开端去执行。

8、说一下防抖函数的利用场景,并简略说下实现形式(滴滴)

答复:

防抖函数

  • 防抖函数的利用场景:防抖是指,触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会从新计算函数执行工夫。常见场景有:键盘输入实时搜寻时 input 事件防抖,浏览器窗口扭转 resize 事件防抖等等(页面滚动事件、鼠标挪动事件)。
  • 实现形式:利用闭包和 setTimeout 来实现,创立一个 debounce 函数,定义一个 timer 变量用来保留定时器,返回一个函数,在函数内治理定时器和 fn 的执行机会。

节流函数

  • 节流函数的利用场景:节流是指,在间断的工夫内一直触发同个事件,会每隔 n 秒才执行一次这个事件。常见场景有:懒加载要监听计算滚动条的地位,用户点击提交按钮只容许肯定工夫内点击一次等等。
  • 实现形式:利用闭包和 setTimeout 配合一个标识符来实现,创立一个 throttle 函数,定义一个 canRun 变量用来保留当次工作是否可执行,返回一个函数,在函数内治理 canRun 的值和 fn 的执行机会,当 canRun 为 false 时间接返回。

9、说一下 V8 的垃圾回收机制(小米)

答复:

V8 是一款支流的 JavaScript 执行引擎,采纳即时编译,速度很快;内存设限,64 位操作系统最大 1.5G,32 位操作系统最大 800M,应用垃圾回收机制开释内存。采纳分代回收的思维,内存分为新生代、老生代,针对不同对象采纳不同算法进行垃圾回收。

新生代对象回收实现:

  • 回收过程采纳复制算法 + 标记整顿
  • 新生代内存辨别为两个等大小空间 From 和 To
  • 应用空间为 From,闲暇空间为 To
  • 流动对象存储在 From 空间,标记整顿后将流动对象拷贝至 To
  • From 与 To 替换空间之后实现内存开释

老生代对象回收实现:

  • 次要采纳标记革除、标记整顿、增量标记算法
  • 首先应用标记革除实现垃圾空间的回收
  • 采纳标记整顿进行空间优化
  • 采纳增量标记进行效率优化

10、performance API 中什么指标能够掂量首屏工夫

答复:

performance.timing 返回一个 PerformanceTiming 对象,这个对象包含了页面相干的性能信息。比方:performance.timing.navigationStart 示意页面开始加载的工夫,能够拿首屏加载实现的工夫减去 navigationStart 就失去首屏工夫。

11、在 EcmaScript 新个性中,暂时性死区有什么作用

答复:

  • ES6 中规定,如果区块中存在 let 和 const 命令,这个区块对这些命令申明的变量,从一开始就造成了关闭作用域。但凡在申明之前就应用这些变量,就会报错,这在语法上称为 暂时性死区。
  • ES6 规定暂时性死区和 let、const 语句不呈现变量晋升,次要是为了缩小运行时谬误,避免在变量申明前就应用这个变量,从而导致意料之外的行为。这样的谬误在 ES5 是很常见的,当初有了这种规定,防止这种谬误就很容易了。

12、观察者模式和公布订阅模式的区别

答复:

  • 观察者模式:观察者 — Watcher,有一个 update() 办法,是当事件产生时,具体要做的事件;指标 — Dep,subs 数组 -> 存储所有的观察者, addSub() -> 增加观察者, notify() -> 当事件产生时,调用所有观察者的 update() 办法;没有信号核心
  • 公布订阅模式:假设存在一个“信号核心”,某个人物执行实现,就向信号核心“公布”(publish)一个信号,其余工作能够向信号核心“订阅”(subscribe)这个信号,从而晓得什么时候本人能够开始执行。
  • 观察者模式是由具体指标调度,比方当事件触发,Dep 就会去调用观察者的办法,所以观察者模式的订阅者与发布者之间是存在依赖的;
  • 公布订阅模式由对立调度核心调用,因而发布者和订阅者不须要晓得对方的存在,两者没有间接依赖

13、gulp 本人写过工作吗?说一下它的构建流程(阿里 2018)

答复:

应用 gulp 写过一些小 demo,还未在生产我的项目中应用过。
gulp 的构建流程:

  • 创立 gulpfile.js 文件,gulp 的入口文件
  • 通过 exports.foo = done => {...} 创立并导出一个构建工作
  • 在工作中通过 gulp.src 函数读取文件流,配合文件流的 pipe() 办法将文件流进行解决和转换(交给插件解决或者输入到指定文件中),最初通过 gulp.dest() 办法将转换后果流输入到指标地位
  • 而后通过解决后将执行后果返回,完结一个工作的执行
  • 通过 gulp.series 创立串行工作,通过 gulp.parallel 创立并行任务
  • gulp 也反对异步工作,能够配合 promise 和 async 创立工作
  • 最初将创立的工作通过 exports 导出,就能够在命令窗口运行定义的 gulp 工作 gulp foo
  • gulp 构建过程的外围原理:输出 => 加工 => 输入,读取流 => 转换流 => 写入流

14、package-lock.json 有什么作用,如果我的项目中没有它会怎么样,举例说明

答复:

package-lock.json 作用:
用来锁定装置时的包的版本号和地址,保障我的项目成员在 npm install 时下载的依赖包版本统一。

如果我的项目中没有 package-lock.json,而 packag.json 中有依赖包 "lodash": "^4.17.4",这时候只能锁定大版本,每次 install 的时候是拉取的该大版本下的最新版本。然而为了我的项目稳定性咱们不应该随便降级依赖包,这可能导致不可预知的危险和适配测试等工作量。

15、webpack 罕用配置项有哪些,并阐明用处(跟谁学 2020)

答复:

module.exports = {
  mode: 'none', // 打包模式,none development production
  entry: './src/main.js', // 打包入口文件
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist') // 打包进口
  },
  devServer: {}, // 配置 devServer contentBase proxy 等
  devtool: 'source-map', // 配置 source-map 有 12 中模式可抉择
  module: {}, // 配置解决转换文件的各种 loader
  plugins: [], // 配置打包过程应用的插件 copy-webpack-plugin html-webpack-plugin 等等
  optimization: {} // 用于优化打包后果的配置 压缩代码 tree-shaking 移除冗余代码等}

16、论述 webpack css-loader 的作用 和 原理?(跟谁学)

答复:

  • 作用:css-loader 会对 @import 和 url() 进行解决,用于加载.css 文件,就像 js 解析 import/require() 一样。
  • 原理:默认 webpack 是只解析 js 代码的,css-loader 会读取解析.css 文件里的 css 代码成字符串,让咱们在打包过程中能解析和利用 css 代码。通常会配合 style-loader 来应用,它会将 css-loader 解析后的内容挂载到 html 页面的 style 标签中。

17、webpack 中 loader 和 plugin 的区别是什么(字节跳动 搜狐)

答复:

  • loader 专一实现资源模块的转换和加载(编译转换代码、文件操作、代码查看)
  • plugin 解决其余自动化工作(打包之前革除 dist 目录、拷贝动态文件、压缩代码等等)

18、webpack、rollup、parcel 它们的优劣?

答复:

webpack

  • 长处:生态齐全,配合各种插件简直能够实现所有打包需要,现如今前端应用程序最风行的打包工具
  • 毛病:文档比较复杂,配置较为繁琐,有肯定的学习老本;打包构建后果有很多模块依赖的代码,打包后果较大

rollup

  • 长处:rollup 很玲珑,仅仅是一款 ESM 打包器,输入后果更加扁平,会主动移除未援用的代码,打包后果仍然齐全可读
  • 毛病:加载非 ESM 的第三方模块比较复杂;模块最终都被打包到一个函数中,无奈实现 HMR;浏览器环境中,代码拆分性能依赖 AMD

parcel

  • 长处:零配置的前端利用打包器,构建速度快,能够主动装置依赖。
  • 毛病:生态不够欠缺,不利于扩大插件等是它的毛病。

19、babel.config.js 和 .babelrc 有什么区别?

答复:

  • .babelrc 的配置文件是针对文件夹的,即该配置文件所在的文件夹包含子文件夹都会利用此配置文件的设置,而且上层配置文件会笼罩下层配置文件,这种形式能够给不同的目录设置不同的规定。
  • babel.config.js 写法和 .babelrc 一样,然而 babel.config.js 是针对整个我的项目的,一个我的项目只有一个放在我的项目根目录。
  • .babelrc 文件放在我的项目根目录和 babel.config.js 成果统一,如果两种类型的配置文件都存在,.babelrc 会笼罩 babel.config.js 的配置

20、webpack 中 tree shaking 的用处和原理是什么?

答复:

  • tree-shaking 用处:移除 JS 中未被援用的代码,尽可能的将所有模块合并输入到一个函数中,晋升代码运行效率,较少代码体积
  • tree-shaking 原理:利用 ES2015 中的 import 和 export,找到未被援用的 export 代码或者模块,将它们从打包后果中移除

21、论述一下 eventbus 的原理,讲述 eventbus 在 vue 中的实际(猿辅导)

答复:

  • 原理:EventBus 事件总线。在 Vue 中能够应用 EventBus 来作为沟通桥梁(组件通信),指所有组件共用一个雷同的事件核心,能够向该核心注册发送事件或接管事件,所有组件都能够灵便的告诉其余组件。
  • 利用实际:兄弟组件通信、不相干组件之间的通信,比方你在某个组件中批改了一个变量,同时心愿在其余组件中监听到这个变量的扭转,EventBus.$emit() 用于创立公布事件,EventBus.$on() 用于订阅事件,EventBus.$off() 用于勾销订阅事件

22、vue-loader 的实现原理是什么

答复:

  • vue-loader 是一个 webpack 的 loader,它容许咱们以一种单文件组件的格局编写 vue 组件,组件个别分为三个模块 <template> <script> <style>
  • 容许为 vue 组件的每个局部应用其它的 webpack loader,例如在 <style> 的局部应用 Sass 和在 <template> 的局部应用 Pug;应用 scoped CSS;能够将 <style> 和 <template> 中援用的资源当作模块依赖来解决
  • vue-loader 不是简略的源转换器。它用本人专用的加载链解决 SFC(Single-file Component 单文件组件)外部的每个语言块,最初将这些块组成最终的模块。
  • 编译模块的过程中,vue-loader 能够将 script 的内容视为.js 文件(如果是 <script lang=”ts”,会被视为.ts 文件),配合 webpack 的每个模块规定,vue-loader 能够将 <template> <script> <style> 中的代码别离解析进去,并利用 webpack 的配置
  • 比方:假如咱们为所有的 *.js 配置过 babel-loader,通过 vue-loader 解决,这些规定也一样会复制和利用于到 Vue SFC 的 <script> 块中。
正文完
 0