发表于

2022-06-22 速石面试 记录

Authors

1. JavaScript this 解释

this 的指向,始终坚持一个原理:this 永远指向最后调用它的那个对象

改变 this 的指向我总结有以下几种方法:

  • 使用 ES6 的箭头函数
  • 在函数内部使用 _this = this
  • 使用 apply、call、bind
  • new 实例化一个对象
  • 全局作用域下的 this 指向 window
  • 如果给元素的事件行为绑定函数,那么函数中的 this 指向当前被绑定的那个元素
  • 函数中的 this,要看函数执行前有没有 . , 有 . 的话,点前面是谁,this 就指向谁,如果没有点,指向 window
  • 自执行函数中的 this 永远指向 window
  • 定时器中函数的 this 指向 window
  • 构造函数中的 this 指向当前的实例
  • call、apply、bind 可以改变函数的 this 指向
  • 箭头函数中没有 this,如果输出 this,就会输出箭头函数定义时所在的作用域中的 this

2. JavaScript 变量提升

当栈内存(作用域)形成, JS 代码自上而下执行之前,浏览器首先会把所有带 var/function 关键字的进行提前声明或者定义,这种预先处理机制称之为变量提升。

console.log(a); // undefined
console.log(fn); // fn(){var b = 2}
console.log(b); // Uncaught ReferenceError: b is not defined
var a = 1;
function fn() {
    var b = 2;
};

变量提升阶段,var 只声明,而 function 声明和赋值都会完成

最开始的时候输出 a 和 fn,会发现 a 是 undefined,而 fn 是 function 的字符串。 在变量提升阶段,带 var 的只声明(默认值为 undefined),而带 function 的变量声明和赋值都会完成。到了代码执行阶段,var 声明的变量会赋值,而 function 声明的变量因为在变量提升阶段已经赋值,所以直接跳过。

变量提升只发生在当前作用域

变量提升只发生在当前作用域,开始加载页面的时候只对全局作用域下的进行变量提升,此时函数作用域如果没执行的话存储的还只是字符串而已。 当函数执行时会生成函数作用域,也称私有作用域,在代码执行前会先形参赋值再进行变量提升。在 ES5 中作用域只有全局作用域和私有作用域,大括号不会形成作用域。全局作用域下声明的变量或者函数是全局变量,在似有作用域下声明的变量是私有变量。

3. JavaScript var const let 区别

在 javascript 中有三种声明变量的方式:var、let、const。

JS 中作用域有:全局作用域、函数作用域。没有块作用域的概念。ECMAScript 6(简称 ES6)中新增了块级作用域。块作用域由 包括,if 语句和 for 语句里面的也属于块作用域。

var 定义的变量可以修改,如果不初始化会输出 undefined,不会报错。

var 声明全局变量,换句话理解就是,声明在 for 循环中的变量,跳出 for 循环同样可以使用。

声明在 for 循环内部的 sum,跳出 for 循环一样可以使用,不会报错正常弹出结果

let 是块级作用域,函数内部使用 let 定义后,对函数外部无影响。并且 let 不能定义同名变量,否则会报错。

const:用于声明常量,也具有块级作用域 ,也可声明块级。const 定义的变量不可以修改,而且必须初始化。 执行顺序

  1. 先执行主线程
  2. 遇到宏队列(macrotask)放到宏队列(macrotask)
  3. 遇到微队列(microtask)放到微队列(microtask)
  4. 主线程执行完毕
  5. 执行微队列(microtask),微队列(microtask)执行完毕
  6. 执行一次宏队列(macrotask)中的一个任务,执行完毕
  7. 执行微队列(microtask),执行完毕
  8. 依次循环

它和 let 一样,也不能重复定义同一个变量,const 一旦定义,无法修改.

let 和 const 属于局部变量,不会出现变量提升的情况,全局定义的 let 和 const 变量,不属于顶层变量,不属于 window 的属性

4. JavaScript event loop 和 事件分发机制

5. 前端工程化

6. SEO

  • 写一个静态页面给搜索引擎
  • Next.js 看着可以做搜索引擎优化 具体需要测试
  • Server Side Rendering 需要 nodejs 服务
  • 直接前后端不分离

7. JavaScript 宏任务 & 微任务

常用的方式:setTimeout setIntervel ajax Promise asyc/await 宏任务(marcotask)微任务(microtask) 的执行顺序 先执行微任务,然后在执行宏任务; JS 中的宏任务:script 代码、setTimeout、setInterval、setImmediate、Ajax、DOM 事件 JS 中的微任务:process.nextTick、MutationObserver、Promise.then catch finally

8. JavaScript 装饰器模式

9. Object.defineProperty 和 Proxy 区别

Object.defineProperty 只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。Vue 2.x 里,是通过 递归 + 遍历 data 对象来实现对数据的监控的,如果属性值也是对象那么需要深度遍历,显然如果能劫持一个完整的对象是才是更好的选择。

Proxy 可以劫持整个对象,并返回一个新的对象。Proxy 不仅可以代理对象, 还可以代理数组。还可以代理动态增加的属性。

Proxy 的优势如下:

  • Proxy 可以直接监听对象而非属性;
  • Proxy 可以直接监听数组的变化;
  • Proxy 有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具备的;
  • Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而 Object.defineProperty 只能遍历对象属性直接修改;
  • Proxy 作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利;

Object.defineProperty 的优势如下:

  • 兼容性好,支持 IE9,而 Proxy 的存在浏览器兼容性问题,而且无法用 polyfill 磨平,因此 Vue 的作者才声明需要等到下个大版本( 3.0 )才能用 Proxy 重写

10. React 双向绑定

11. JavaScript 观察订阅模式 (ReactiveX JS or ReactiveX Java)

12. 订票系统实现 (开放式问题)

13. 什么是云计算

云计算(cloud computing)是分布式计算的一种,指的是通过网络“云”将巨大的数据计算处理程序分解成无数个小程序,然后,通过多部服务器组成的系统进行处理和分析这些小程序得到结果并返回给用户。云计算早期,简单地说,就是简单的分布式计算,解决任务分发,并进行计算结果的合并。因而,云计算又称为网格计算。通过这项技术,可以在很短的时间内(几秒钟)完成对数以万计的数据的处理,从而达到强大的网络服务。

现阶段所说的云服务已经不单单是一种分布式计算,而是分布式计算、效用计算、负载均衡、并行计算、网络存储、热备份冗杂和虚拟化等计算机技术混合演进并跃升的结果。