qidao123.com技术社区-IT企服评测·应用市场

标题: 2024 前端高频面试题之 JS 篇 [打印本页]

作者: 曹旭辉    时间: 2024-12-6 07:34
标题: 2024 前端高频面试题之 JS 篇

1、什么是原型、原型链?

原型:


原型链:

当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的 __proto__ 隐式原型上查找,即它的构造函数的 prototype,如果还没有找到就会再在构造函数的 prototype 的 __proto__ 中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链。

原型链判断:

  1. Object.prototype.__proto__; //null
  2. Function.prototype.__proto__; //Object.prototype
  3. Object.__proto__; //Function.prototype
  4. Object instanceof Function; //true
  5. Function instanceof Object; //true
  6. Function.prototype === Function.__proto__; //true
复制代码
2、什么是继承?说一说有哪些?继承组合的原理及优点?

继承(inheritance)是面向对象软件技能当中的一个概念。如果一个种别 B“继承自”另一个种别 A,就把这个 B 称为“A 的子类”,而把 A 称为“B 的父种别”也可以称“A 是 B 的超类”

组合继承: 原型链继承和借用构造函数方法组合就是组合继承。用原型链实现对原型属性和方法的继承,用借用构造函数技能来实现实例属性的继承。

寄生组合式继承: 结合借用构造函数转达参数和寄生模式实现继承。这是最成熟的方法,也是如今库实现的方法

优点:

继承可以使得子类具有父种别的各种属性和方法,在子种别继承父种别的同时,可以重新界说某些属性,并重写某些方法,即覆盖父种别的原有属性和方法,使其获得与父种别不同的功能
3、new 操作符具体干了什么?


4、js 有哪些方法改变 this 指向?

call,apply,bind。三者的第一个参数都是 this 必要指向的对象,但在后续的参数上只有 apply 是接收一个数组,call 和 bind 用逗号分开;call 和 apply 直接调用,返回的是一个值,而 bind 不直接调用,返回的是一个函数形式,实验:foo.bind(obj)()
5、bind 有哪些实现的注意点?(可以实现参数的柯里化)


6、对一个函数链式调用 bind,this 指向的是谁?为什么?

第一个 bind,由于被改变 this 指向之后就不可以更改了。
7、es6 有哪些新特性?let、const、var 有什么区别?


let,const 块级作用域,var 全局作用域

let,const 不允许重复声明,var 可以

let,const 不存在变量提升(临时性死区),var 可以

const 不能修改且要有初始值,let,var 值可以修改
8、es5 怎样实现 let 属性?

利用自实验匿名函数(IIFE)实现;闭包
  1. (function () {
  2.   var a = 1;
  3.   console.log(a); // 1
  4. })();
  5. console.log(a); // 会报错
复制代码
9、闭包是什么?利用场景有哪些?怎样实现?

闭包是指有权访问另一个函数作用域中变量的函数。

10、垃圾回收机制原理?

GC 即 Garbage Collection ,步伐工作过程中会产生很多垃圾,这些垃圾是步伐不消的内存或者是之前用过了,以后不会再用的内存空间,而 GC 就是负责回收垃圾的,由于他工作在引擎内部,以是对于我们前端来说,GC 过程是相对比力无感的,这一套引擎实验而对我们又相对无感的操作也就是常说的垃圾回收机制。
垃圾回收策略:

标志扫除法大致过程就像下面这样(会引申一个整理策略知识点)

引用计数法是跟踪记录每个变量值被利用的次数

如果对象 A 和对象 B 互相引用,他们的引用数目都是 2,导致无法被回收。
11、节流和防抖原理?利用场景?

  1. // 节流 就像fps游戏的射速,就算一直按着鼠标射击,也只会在规定射速内射出子弹
  2. function throttle(fn, timeout) {
  3.   let timer = null;
  4.   return function (...arg) {
  5.     if (timer) return;
  6.     timer = setTimeout(() => {
  7.       fn.apply(this, arg);
  8.       timer = null;
  9.     }, timeout);
  10.   };
  11. }
  12. // 防抖 就像坐电梯,十秒自动关门,一旦有人进来再重新倒计时
  13. function debounce(fn, timeout) {
  14.   let timer = null;
  15.   return function (...arg) {
  16.     if (timer) clearTimeout(timer);
  17.     timer = setTimeout(() => {
  18.       fn.apply(this, arg);
  19.     }, timeout);
  20.   };
  21. }
复制代码
利用场景:

12、箭头函数和普通函数的区别?箭头函数调用 call、apply、bind 会发生什么?


13、0.1 + 0.2 === 0.3 吗?为什么?整数之间运算怎么保证准确?

盘算机是通过二进制的方式存储数据的,以是盘算机盘算 0.1+0.2 的时候,现实上是盘算的两个数的二进制的和。这两个小数都是无限循环小数,以是相加未便是 0.3。

14、如何判断数组范例?


  1. Object.prototype.toString.call(obj).slice(8, -1) === "Array";
复制代码

  1. Array.isArray(obj);
复制代码

  1. obj.__proto__ === Array.prototype;
复制代码

  1. obj instanceof Array;
复制代码
15、promise 是什么?promise.all 和 promise.race 有什么区别?

Promise 是异步编程的一种办理方案,比传统的办理方案回调函数和变乱更合理和更强盛。一个 Promise 的当前状态必须为以下三种状态中的一种:等待态(Pending)、实验态(Fulfilled)和拒绝态(Rejected),状态的改变只能是单向的,且变化后不可在改变。

promise.all() 和 promise.race() 方法都是将多个 Promise 实例,包装成一个新的 Promise 实例。区别在于 all 是都调用乐成一起返回,race 返回调用最快的那个。
16、请你实现一个 promise 调度器。(并行限定的 promise 调度器)

参考文档
  1. addTask(1000,"1");
  2. addTask(500,"2");
  3. addTask(300,"3");
  4. addTask(400,"4");
  5. 的输出顺序是:2 3 1 4
  6. 整个的完整执行流程:
  7. 一开始1、2两个任务开始执行
  8. 500ms时,2任务执行完毕,输出2,任务3开始执行
  9. 800ms时,3任务执行完毕,输出3,任务4开始执行
  10. 1000ms时,1任务执行完毕,输出1,此时只剩下4任务在执行
  11. 1200ms时,4任务执行完毕,输出4
  12. class Scheduler {
  13.     constructor(limit) {
  14.         this.queue = [];
  15.         this.maxCount = limit;
  16.         this.runCounts = 0;
  17.     }
  18.     add(time, order) {
  19.         const promiseCreator = () => {
  20.             return new Promise((resolve, reject) => {
  21.                 setTimeout(() => {
  22.                     console.log(order);
  23.                     resolve();
  24.                 }, time);
  25.             });
  26.         };
  27.         this.queue.push(promiseCreator);
  28.     }
  29.     taskStart() {
  30.         for (let i = 0; i < this.maxCount; i++) {
  31.             this.request();
  32.         }
  33.     }
  34.     request() {
  35.         if (!this.queue || !this.queue.length || this.runCounts >= this.maxCount) {
  36.              return;
  37.          }
  38.          this.runCounts++;
  39.          this.queue
  40.              .shift()()
  41.              .then(() => {
  42.                  this.runCounts--;
  43.                  this.request();
  44.              });
  45.          }
  46.      }
  47. const scheduler = new Scheduler(2);
  48. const addTask = (time, order) => {
  49.      scheduler.add(time, order);
  50. };
  51. addTask(1000, "1");
  52. addTask(500, "2");
  53. addTask(300, "3");
  54. addTask(400, "4");
  55. scheduler.taskStart();
复制代码
17、RAF 和 RIC 是什么?


18、js 异步加载脚本方法?有什么区别?


其中蓝色代表 js 脚本网络加载时间,赤色代表 js 脚本实验时间,绿色代表 html 剖析。

defer 和 async 属性都是异步去加载外部的 JS 脚本文件,它们都不会阻塞页面的剖析,其区别如下:

19、html 文档生命周期有哪些?

生命周期:

作用:

20、foreach 和 map 可以跳出循环吗?为什么?怎样跳出循环体?(函数中跳出循环体也是跳出函数本身)

不可以跳出循环,可以抛堕落误跳出循环。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/) Powered by Discuz! X3.4