每天10个前端小知识 【Day 10】

news2025/1/18 10:53:19

在这里插入图片描述

前端面试基础知识题

1. es5 中的类和es6中的class有什么区别?

在es5中主要是通过构造函数方式和原型方式来定义一个类,在es6中我们可以通过class来定义类。

class类必须new调用,不能直接执行。
在这里插入图片描述

class类执行的话会报错,而es5中的类和普通函数并没有本质区别,执行肯定是ok的。

class类不存在变量提升
在这里插入图片描述
在这里插入图片描述
2报错,说明class方式没有把类的定义提升到顶部。

class类无法遍历它实例原型链上的属性和方法

function Foo (color) {
    this.color = color
}
Foo.prototype.like = function () {
    console.log(`like${this.color}`)
}
let foo = new Foo()

for (let key in foo) {
    // 原型上的like也被打印出来了
    console.log(key)  // color、like
}
class Foo {
    constructor (color) {
        this.color = color
    }
    like () {
        console.log(`like${this.color}`)
    }
}
let foo = new Foo('red')

for (let key in foo) {
    // 只打印一个color,没有打印原型链上的like
    console.log(key)  // color
}

new.target属性
es6为new命令引入了一个new.target属性,它会返回new命令作用于的那个构造函数。如果不是通过new调用或Reflect.construct()调用的,new.target会返回undefined。

function Person(name) {
  if (new.target === Person) {
    this.name = name;
  } else {
    throw new Error('必须使用 new 命令生成实例');
  }
}

let obj = {}
Person.call(obj, 'red') // 此时使用非new的调用方式就会报错

class类有static静态方法

static静态方法只能通过类调用,不会出现在实例上;另外如果静态方法包含 this 关键字,这个 this 指的是类,而不是实例。static声明的静态属性和方法都可以被子类继承。

class Foo {
  static bar() {
    this.baz(); // 此处的this指向类
  }
  static baz() {
    console.log('hello'); // 不会出现在实例中
  }
  baz() {
    console.log('world');
  }
}

Foo.bar() // hello

2. 背包问题

在这里插入图片描述

3. 全排列

在这里插入图片描述

4. 使用Promise封装一个异步加载图片的方法

这个比较简单,只需要在图片的onload函数中,使用resolve返回一下就可以了。

function loadImg(url) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = function() {
      resolve(img);
    };
    img.onerror = function() {
    	reject(new Error('Could not load image at' + url));
    };
    img.src = url;
  });

5. 怎么使用 setTimeout 实现 setInterval?

setInterval 的作用是每隔一段指定时间执行一个函数,但是这个执行不是真的到了时间立即执行,它真正的作用是每隔一段时间将事件加入事件队列中去,只有当当前的执行栈为空的时候,才能去从事件队列中取出事件执行。所以可能会出现这样的情况,就是当前执行栈执行的时间很长,导致事件队列里边积累多个定时器加入的事件,当执行栈结束的时候,这些事件会依次执行,因此就不能到间隔一段时间执行的效果。

针对 setInterval 的这个缺点,我们可以使用 setTimeout 递归调用来模拟 setInterval,这样我们就确保了只有一个事件结束了,我们才会触发下一个定时器事件,这样解决了 setInterval 的问题。

// 思路是使用递归函数,不断地去执行 setTimeout 从而达到 setInterval 的效果

function mySetInterval(fn, timeout) {
  // 控制器,控制定时器是否继续执行
  var timer = {
    flag: true
  };

  // 设置递归函数,模拟定时器执行。
  function interval() {
    if (timer.flag) {
      fn();
      setTimeout(interval, timeout);
    }
  }

  // 启动定时器
  setTimeout(interval, timeout);

  // 返回控制器
  return timer;
}

6. Js 动画与 CSS 动画区别及相应实现

CSS3 的动画的优点 在性能上会稍微好一些,浏览器会对 CSS3 的动画做一些优化 代码相对简单 缺点 在动画控制上不够灵活 兼容性不好 JavaScript 的动画正好弥补了这两个缺点,控制能力很强,可以单帧的控制、变换,同时写得好完全可以兼容 IE6,并且功能强大。对于一些复杂控制的动画,使用 javascript 会比较靠谱。而在实现一些小的交互动效的时候,就多考虑考虑 CSS 吧

7. 什么是“前端路由”?什么时候适合使用“前端路由”?“前端路由”有哪些优点和缺点?

前端路由就是把不同路由对应不同的内容或页面的任务交给前端来做,之前是通过服务端根据 url 的不同返回不同的页面实现的。

在单页面应用,大部分页面结构不变,只改变部分内容的使用

优点:用户体验好,不需要每次都从服务器全部获取,快速展现给用户 缺点:单页面无法记住之前滚动的位置,无法在前进,后退的时候记住滚动的位置 实现方式 前端路由一共有两种实现方式,一种是通过 hash 的方式,一种是通过使用 pushState 的方式。

8. 什么是点击穿透,怎么解决?

在发生触摸动作约300ms之后,移动端会模拟产生click动作,它底下的具有点击特性的元素也会被触发,这种现象称为点击穿透。

常见场景

情景一:蒙层点击穿透问题,点击蒙层(mask)上的关闭按钮,蒙层消失后发现触发了按钮下面元素的click事件。
情景二:跨页面点击穿透问题:如果按钮下面恰好是一个有href属性的a标签,那么页面就会发生跳转。
情景三:另一种跨页面点击穿透问题:这次没有mask了,直接点击页内按钮跳转至新页,然后发现新页面中对应位置元素的click事件被触发了。
情景四:不过概率很低,就是新页面中对应位置元素恰好是a标签,然后就发生连续跳转了。

发生的条件

上层元素监听了触摸事件,触摸之后该层元素消失
下层元素具有点击特性(监听了click事件或默认的特性(a标签、input、button标签))

解决点击穿透的方法

方法一:书写规范问题,不要混用touch和click。既然touch之后300ms会触发click,只用touch或者只用click就自然不会存在问题了。
方法二:吃掉(或者说是消费掉)touch之后的click,依旧用tap,只是在可能发生点击穿透的情形做额外的处理,拿个东西来挡住、或者tap后延迟350毫秒再隐藏mask、pointer-events、在下面元素的事件处理器里做检测(配合全局flag)等。

9. 介绍些 setTimeout 的运行机制

setTimeout简介

setTimeout()函数:用来指定某个函数或某段代码在多少毫秒之后执行。它返回一个整数,表示定时器timer的编号,可以用来取消该定时器。

先看个简单的例子:

console.log(1);
setTimeout(function () {
    console.log(2);
}, 0);
console.log(3);

问:最后的打印顺序是什么?(如果不了解js的运行机制就会答错)

正确答案:1 3 2

解析:无论setTimeout的执行时间是0还是1000,结果都是先输出3后输出2,这就是面试官常常考查的js运行机制的问题,接下来我们要引入一个概念,JavaScript 是单线程的。

JavaScript 单线程

JavasScript引擎是基于事件驱动和单线程执行的,JS引擎一直等待着任务队列中任务的到来,然后加以处理,浏览器无论什么时候都只有一个JS线程在运行程序,即主线程。那么单线程的JavasScript是怎么实现“非阻塞执行”呢?是通过任务队列。
所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。
单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。但是如果有些任务很慢时(比如Ajax操作从网络读取数据),我还是要等结果在执行后一个任务吗?于是,有了一种异步任务。
同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;而异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有主线程执行完毕,主线程去通知"任务队列",某个异步任务可以执行了,该任务才会进入主线程执行。
所以js的运行机制如下:

  • 1.所有同步任务都在主线程上执行,形成一个执行栈(Call Stack)

  • 2.主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件

-3. 一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。

  • 4.主线程不断重复上面的第三步。

setTimeout运行机制

setTimeout 和 setInterval的运行机制,其实就是将指定的代码移出本次执行,等到下一轮 Event Loop 时,再检查是否到了指定时间。如果到了,就执行对应的代码;如果不到,就等到再下一轮 Event Loop 时重新判断。

这意味着,setTimeout指定的代码,必须等到本次执行的所有同步代码都执行完,才会执行。

10. Promise.all 和 Promise.allSettled 有什么区别?

一句话概括Promise.allSettled和Promise.all的最大不同:Promise.allSettled永远不会被reject。

Promise.all的痛点

当需要处理多个Promise并行时,大多数情况下Promise.all用起来是非常顺手的,比如下面这样

const delay = n => new Promise(resolve => setTimeout(resolve, n));

const promises = [
  delay(100).then(() => 1),
  delay(200).then(() => 2),
  ]

Promise.all(promises).then(values=>console.log(values))
// 最终输出: [1, 2]

可是,是一旦有一个promise出现了异常,被reject了,情况就会变的麻烦。

const promises = [
  delay(100).then(() => 1),
  delay(200).then(() => 2),
  Promise.reject(3)
  ]

Promise.all(promises).then(values=>console.log(values))
// 最终输出: Uncaught (in promise) 3

Promise.all(promises)
.then(values=>console.log(values))
.catch(err=>console.log(err))
// 加入catch语句后,最终输出:3

尽管能用catch捕获其中的异常,但你会发现其他执行成功的Promise的消息都丢失了,仿佛石沉大海一般。

要么全部成功,要么全部重来,这是Promise.all本身的强硬逻辑,也是痛点的来源,不能说它错,但这的确给Promise.allSettled留下了立足的空间。

Promise.allSettled

假如使用Promise.allSettled来处理这段逻辑会怎样呢?
const promises = [

  delay(100).then(() => 1),
  delay(200).then(() => 2),
  Promise.reject(3)
  ]

Promise.allSettled(promises).then(values=>console.log(values))
// 最终输出: 
//    [
//      {status: "fulfilled", value: 1},
//      {status: "fulfilled", value: 2},
//      {status: "rejected", value: 3},
//    ]

可以看到所有promise的数据都被包含在then语句中,且每个promise的返回值多了一个status字段,表示当前promise的状态,没有任何一个promise的信息被丢失。

因此,当用Promise.allSettled时,我们只需专注在then语句里,当有promise被异常打断时,我们依然能妥善处理那些已经成功了的promise,不必全部重来。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/335180.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【PyTorch】教程:Transfer learning

Transfer learning 实际工作中,只有很少的人从头开始训练 CNN,因为很难获得大量的样本。一般情况下,会通过调用预训练模型,例如 ConvNet 在 ImageNet(1.2 M 图像 1000 个类别),可以用 ConvNet 初始化&#…

Verilog 组合逻辑一些注意事项

reg型变量不一定会被综合成触发器 【参考链接】 以下是verilog-2001的标准中对wire和reg的定义如下: wire: A wire net can be used for nets that are driven by a single gate or continuous assignment. reg: Assignments to a reg are…

微信小程序 Springboot java nodejs图书馆图书借阅系统

图书借阅管理系统用户端是基于微信小程序,管理员端是基于java编程语言,mysql数据库, idea工具开发,本系统是分为用户和管理员两个角色,其中用户的主要功能有注册登陆小程序,查看系统功能,图书搜…

VB 消息、消息队列、事件

windows是图像化界面,多任务消息windows系统将消息(大的结构)发给其他应用程序Windows消息包含了所有的外部输入或者计算机内部信息,应用程序的消息队列先进先出,Windows消息的循环--每个应用程序里有自己的消息循环外…

微信卸载后重装的聊天记录还能找回吗?

很多人微信卸载后,问能不能恢复之前的聊天记录? 我想大家肯定都去百度搜索了,能搜出来可行的办法了么,没有是吧,那就看看我能不能帮到你,根据我的经验来解决。 答:理论上是不能的,因…

SpringBoot集成swagger3(CD2207)(内含教学视频+源代码)

SpringBoot集成swagger3(CD2207)(内含教学视频源代码) 教学视频源代码下载链接地址:https://download.csdn.net/download/weixin_46411355/87435564 目录SpringBoot集成swagger3(CD2207)&#…

LeetCode栈与队列相关解法

栈与队列1. 用栈实现队列[232. 用栈实现队列](https://leetcode.cn/problems/implement-queue-using-stacks/)2. 用队列实现栈[225. 用队列实现栈](https://leetcode.cn/problems/implement-stack-using-queues/)两个队列实现一个队列实现3. 有效括号[20. 有效的括号](https://…

mysql使用innobackupex主从同步

目录 1.用innobackupex物理备份主库数据至文件夹 2.在从库用innobackupex恢复数据库 3.配置主从并启动从库 innobackupex是一款MySQL备份工具,备份速度快(通过直接copy物理文件),而且支持压缩、流式传输、加密等功能 新安装的数据库自带innobackupex…

程序的翻译环境和执行环境

程序环境和预处理🦖程序的翻译环境和执行环境🦖详解编译链接🐳 翻译环境🐳 详解编译过程🐳 运行环境🦖预处理详解🐳 预定义符号🐳 #define🦀 #define 定义标识符&#x1…

端到端模型(end-to-end)与非端到端模型

一、端到端(end to end) 从输入端到输出端会得到一个预测结果,将预测结果和真实结果进行比较得到误差,将误差反向传播到网络的各个层之中,调整网络的权重和参数直到模型收敛或者达到预期的效果为止,中间所…

9.关系查询处理和查询优化

其他章节索引 梳理 名词解释 代数优化:是指关系代数表达式的优化,也即按照一定规则,通过对关系代数表达式进行等价变换,改变代数表达式中操作的次序和组合,使查询更高效物理优化:是指存取路径和底层操作算…

类和对象(中)(二)

类和对象(中)(二)1.赋值运算符重载1.1运算符重载1.2赋值运算符重载1.3前置和后置重载2.const成员3.取地址及const取地址操作符重载🌟🌟hello,各位读者大大们你们好呀🌟🌟…

【Linux基础知识】

Linux基础知识 Linux基础知识 系统目录结构 /bin: 命令和应用程序。 /boot: 这里存放的是启动 Linux 时使用的一些核心文件,包括一些连接文件以及镜像文件。 /dev : dev 是 Device(设备) 的缩写, 该目录下存放的是 Linux 的外…

MySQL —— 内置函数

目录 内置函数 一、日期函数 二、字符串函数 三、数学函数 四、其他函数 内置函数 一、日期函数 函数名称描述current_date()获取当前日期current_time()获取当前时间current_timestamp()获取当前时间戳now()获取当前日期时间date(datetime)获取datetime参数的日期部分d…

【C→C++】打开C++世界的大门

文章目录前言什么是CC的发展史C的重要性1. 使用广泛度2. 工作领域的应用1. C关键字(C98)2. 命名空间2.1 命名空间的定义2.2 命名空间的使用2.3 std命名空间的使用惯例3. C输入&输出3.1 输入输出3.2 说明4. 缺省参数4.1 缺省参数概念4.2 缺省参数分类5. 函数重载5.1 函数重载…

作业帮发布新款AI学习桌,引领书桌行业智能化发展

2月9日,作业帮举办AI学习桌新品沟通会,宣布其独家开创的AI学习桌推出四个月内跻身天猫书桌单品GMV前四,作业帮将加大投入,正式进军书桌市场,并发布新款AI学习桌产品。AI伴学护眼护脊,颠覆传统书桌想象力作业…

一:Datart的下载、本地运行

前言:本文只是个人在使用datart的一个记录,仅供参考。如果有不一样的地方,欢迎评论或私信进行交流。datart 是新一代数据可视化开放平台,支持各类企业数据可视化场景需求,如创建和使用报表、仪表板和大屏,进…

ASEMI三相整流模块MDS100-16图片,MDS100-16尺寸

编辑-Z ASEMI三相整流模块MDS100-16参数: 型号:MDS100-16 最大重复峰值反向电压(VRRM):1600V 最大RMS电桥输入电压(VRMS):1700V 最大平均正向整流输出电流(IF&#…

计算机网络|第二章 物理层|湖科大课程|从零开始的计网学习——物理层(计网入门就看这篇!)

图片来源于胡科大计算机网络课程,https://www.bilibili.com/video/BV1c4411d7jb?p20&vd_sourcedeb12d86dce7e419744a73045bc66364。文章非盈利商业用途,供博主与大家学习参考,如有侵权,请联系我删除!2.1物理层的基…

一起来体验一把ChatGPT,附详细的注册流程!

文章目录ChatGPT是什么ChatGPT效果体验ChatGPT详细注册流程i 步骤1ii 步骤2iii 步骤3ChatGPT是什么 ChatGPT是由人工智能实验室OpenAI 研发的通用聊天机器人,于2022年11月30日上线。ChatGPT的网页注册之后就可以免费试用。 用户与ChatGPT之间的对话互动包括了聊天…