2022千道前端问答题(更新中)

127 阅读7分钟

Javascript篇

1. 理解instanceof ?

  • instanceof 检测左侧的 __proto__ 原型链上,是否存在右侧的 prototype 原型。
Function instanceof Object; //true
Object instanceof Function; //true

2. Function和Object的关系?参考

  • Object的构造函数是Function,Function的构造函数是它自己。
  • Object的原型是Function的原型,Function的原型是匿名函数,匿名函数的原型是Object的原型。 image.png

3. prototype和__proto__的区别?

image.png

var a = {};
console.log(a.prototype);  //undefined
console.log(a.__proto__);  //Object {}

var b = function(){}
console.log(b.prototype);  //b {}
console.log(b.__proto__);  //function() {}

4.__proto__指向谁?参考

image.png

/*1、字面量方式*/
var a = {};
console.log(a.__proto__);  //Object {}
console.log(a.__proto__ === a.constructor.prototype); //true
console.log(a.__proto__ === Object.prototype); //true

/*2、构造器方式*/
var A = function(){};
var a = new A();
console.log(a.__proto__); //A {}
console.log(a.__proto__ === a.constructor.prototype); //true
console.log(a.__proto__ === A.prototype); //true

/*3、Object.create()方式*/
var a1 = {a:1}
var a2 = Object.create(a1);
console.log(a2.__proto__); //Object {a: 1}
console.log(a2.__proto__ === a2.constructor.prototype); //false(此处即为图1中的例外情况)
console.log(a2.__proto__ === a1); //true

5. 原型链?

image.png

6. ES6特性的意义

原有语法的增强、原有语法缺陷修复、全新的对象、方法、数据结构,带来生产力的提升。

7. GC回收

  1. JavaScript中的不可达对象,即是垃圾。
  2. 新生代采用标记整理 + 复制算法(空间换时间,空间小,交换频繁)
  3. 老生代采用标记清除、增量标记(程序执行和垃圾回收交替执行,体验好。当V8内存达到最大时,采用非增量标记回收的时间小于1S。)。

8、防抖和节流

  1. 防抖的关键点:定时器开启前清空定时器,定时器回调函数中置空timer。通过immediate 和 timer 决定首次执行或最后一次执行。
  2. 节流的关键点:定义变量记录上一次执行时间戳,通过间隙时间判断是否高频。非高频直接触发,高频延迟时间差后执行。注意高频情况的关键判断条件(有定时器的情况下,不要重复定义定时器,直接跳出**)**

9、new操作到底做了什么?

创建新的对象、关联this、返回对象(注意构造函数一定返回引用类型,不一定是this,但会忽略基本类型的返回)

10、let变量声明的使用

let定义的变量要等到代码执行到时才装载,在这之前访问(存在暂时性死区)会导致引用错误Uncaught ReferenceError

11、Node实现common.js模块化

实现“模块”功能的奥妙就在于JavaScript是一种函数式编程语言,它支持闭包。如果我们把一段JavaScript代码用一个函数包装起来,这段代码的所有“全局”变量就变成了函数内部的局部变量。Node利用JavaScript的函数式编程的特性,轻而易举地实现了模块的隔离。

12、module.exports vs exports

exports相当于是对module.exports的引用,不可以直接对exports赋值(这样会改变引用地址)。

13、webpack中loader和plugin理解

loader专注实现资源模块加载及处理,plugin增强自动化能力。loader为函数入参为source(资源);plugin为类重现apply方法,tap方法注册钩子函数。

14、关于声明和声明未定义undefined

在 ECMA-262 第 3 版增加undefined这个特殊值的目的就是为了正式明确空对象指针(null)和未初始化变量的区别。对未声明的变量,只能执行一个 有用的操作,就是对它调用 typeof。

15、Number() 、parseInt()、parseFloat()的区别?

  • Number()比较复杂涉及布尔值、数值、null、undefined、字符串、对象(调valueOf())。
  • parseInt()、parseFloat()是从第一个非空格字符开始转换。如果第一个字符不是数值字符、加号或减号,parseInt()立即 返回 NaN。如果第一个字符 是数值字符、加号或减号,则继续依次检测每个字符,直到字符串末尾,或碰到非数值字符。
  • parseFloat()只解析十进制值,因此不能指定底数,十六进制数值始终会返回 0 (开头的零始终被忽略)
  • Number("")为0,parseInt("")为NaN。

16、Symbol类型的用途

  • Symbol类型并不是为了提供私有类型(因为Reflect.ownKeys()可以获取到)。它就是用于创建唯一记号,用作非字符串的对象属性。
  • 符号没有字面量语法,这也是它们发挥作用的关键??

17、for await of VS Promise.all

Promise.all,将一次性发送所有请求,然后在所有请求完成后您将收到响应,for await of您将一次性发送请求,但会一一收到响应。

18、对象字面量 VS 构造函数

  • 对象字面量强调对象就是一个简单的可变的散列表,而不必一定派生自某个类
  • 对象字面量不需要“作用域解析”,构造函数定义需要解析器顺着作用域链从当前作用域开始查找,直到找到全局Object()构造函数为止。
  • new Object()传入不同的参数(数字、字符串和布尔值),最终得到的对象是由不同的构造函数生成。(不推荐,会导致一些意想不到的结果)

19. 说一说javascript跨域和jsonp

20. 不要与浏览器预加载扫描器对抗

21. WeakMap 和 Map 的区别,WeakMap 原理,为什么能被 GC?

TypeScript篇

1. interface 和 type 的区别?

  • interface 基本上是描述数据形状(例如,对象)的一种方法。
  • type 是数据类型的定义,例如,联合、原语、交集、元组或任何其他类型
  • interface 支持 declaration merging,而 type alias 不支持。
  • 类型与类型之间连接用 &,接口的组合用 extends.
  • 我们使用的 type 关键字,定义的只是类型别名,而不是全新的类型。

2. TS 中的抽象类(使用abstract声明的类)?

  • 抽象类不能被实例化,我们只能实例化它的子类,子类可以实现它的所有抽象方法

3. 常⻅泛型变量代表的意思

  • T:通常⽤作第⼀个类型变量名称
  • K(Key):表示对象中的键类型
  • V(Value):表示对象中的值类型
  • E(Element):表示元素类型

4. TS中的修饰符

  • 修饰符是一个函数,包含类、属性、方法、参数修饰符
  • 函数入参一般为target: TFunction(被装饰的类)、propertyKey: string | symbol (被装饰类的属性名)、descriptor: TypePropertyDescript (属性描述符)、parameterIndex: number (⽅法中参数的索引值)

5. 在什么时候需要使⽤泛型呢?

  • 当你的函数、接⼝或类将处理多种数据类型时
  • 当函数、接⼝或类在多个地⽅使⽤该数据类型时

6. 泛型约束

  • 有时我们需要限制每种类型所接收的类型数量,采用extends
  • 泛型约束默认参数,只有当代码中没有直接指定类型参数,从实际值参数中也无法推断类型时,这个默认类型才会起作用。

7. 泛型条件类型

interface Dictionary { 
    [key: string]: T; 
} 
type StrDict = Dictionary 
type DictMember = T extends Dictionary ? V : never
type StrDictMember = DictMember // string

在上⾯示例中,当类型 T 满⾜ T extends Dictionary 约束时,我们会使⽤ infer 关键字声明了⼀ 个类型变量 V,并返回该类型,否则返回 never 类型

框架篇

1. 为何 Vue.use() 必须在调用 new Vue() 之前调用?

因为安装插件时,插件给Vue添加全局功能,所以必须写在new Vue() 之前,否则创建的Vue实例无法获取插件添加的Vue全局功能

2. vue diff算法的原理

  • diff 算法是一种通过同层的树节点进行比较的高效算法
  • 比较只会在同层级进行, 不会跨层级比较。一般跨层的修改比较少,若采用跨层会出现生命周期的错乱。
  • 在diff比较的过程中,循环从两边向中间比较

综合篇

1. 说说什么是单点登录?如何实现?