13

0 阅读24分钟

script脚本的局限性

background-color的作用范围一般是content + padding

sleep本质上就是可以模拟 event loop

遇到并行的异步任务时,可以使用promise.all

使用promise.all做优化,如下

const a  = [3, 12, 4] // ['3', '12', '4']也适用
console.log(a.sort()) // [12, 3, 4]
console.log(a.sort((a, b) => a -b)) // [3,4,12]

数组交换时出现的问题

let arr = [1,2,6,4,3]

  [arr[0], 2] = [2, arr[0]] // 想要将1 and 2换位置,这样写肯定有问题。


数组交换时,必须带着index。
如上,想要交换1和2,并且2的位置不知道,做法如下
const index = arr.indexOf(2);
[arr[0], arr[index]] = [arr[index], arr[0]]

经典算法,双指针

// const a = [1, 2, 3, 4, 5, 6],

//     k = 5 // output: 2

// const b = [1, 2, 3, -1, 4, 5, 6],

//     k2 = 5 // output: 3
// 找到数组中连续子串的和等于k的情况的总和, 数组不是有序的。



// 双指针问题,第二个for循环开始时,就把他认为是满足条件的开始, 也就是把它当作起始点。
// 连续子串,就不要断,连续加
let arr = [1, 7, 2, 6, 4, 3]

function fn(arr, k) {
  let result = 0
  const len = arr.length
  for (let i = 0; i < len; i++) {
    let res = 0
    for (let j = i; j < len; j++) {
      res += arr[j]
      if (res === k) {
        result++
      }
    }
  }
  return result
}
console.log(fn([1, 2, 3, -1, 4, 5, 6], 5));

ssr实现

要实现React应用的SSR,通常会涉及以下几个关键步骤:

  • 设置服务器环境:使用Node.js和Express等服务器框架来接收HTTP请求并准备数据。
  • 渲染组件:在服务器端使用react-dom/server的renderToString或renderToNodeStream方法来将React组件转换为HTML字符串。
  • 数据预取:在服务器端获取数据,填充到React组件的状态或props中,确保发送到客户端的是带有数据的HTML。
  • 客户端 hydration:当HTML在客户端被加载后,React接管并重新渲染这个标记,使其成为可交互的应用,这一步称为“hydration”。
  • 路由处理:如果应用包含多个页面,需要在服务器端正确处理URL路由,确保每个URL都能返回正确的HTML内容。

此外,为了简化SSR的复杂度,开发者通常会选择使用如Next.js或Gatsby这样的框架,它们内置了对SSR的支持,能够自动处理很多底层细节,让开发者更专注于业务逻辑。

const koa = require('koa')
const mount = require('koa-mount')
const static = require('koa-static')
const fs = require('fs')

const app = new koa()

app.use(mount('/', async (ctx) => {

  ctx.body = await fs.readFileSync(__dirname + '/source/index.htm', 'utf-8')
}))

app.listen(8000),

如上,通过nodejs对index.htm渲染返回给浏览器,这样算是ssr吗

不,上述代码示例并不算作 Server-Side Rendering (SSR)。

在这个例子中,Node.js 使用 Koa 框架搭建了一个简单的静态文件服务器。当访问根路径 '/' 时,服务器会读取 index.htm 文件的内容并通过 ctx.body 直接返回给客户端。这个过程仅涉及到了静态文件的服务器端发送,并没有进行任何动态数据注入或JavaScript渲染过程。客户端浏览器接收到的是完整的 HTML 文件内容,然后像处理任何普通静态网页一样进行解析和渲染。

Server-Side Rendering (SSR) 指的是在服务器端生成完整的 HTML 页面,这包括执行 JavaScript 应用(如React、Vue等前端框架应用),将这些应用渲染成静态 HTML,再将其发送到浏览器的过程。这样做的目的是为了改善首屏加载速度以及利于SEO(搜索引擎优化)。

怎么开启预解析dns

预解析DNS(DNS prefetching)是一种优化技术,它允许浏览器在实际需要之前预先解析域名的DNS记录。这可以减少页面加载时间,因为DNS查询通常需要一定的时间,而预解析可以在用户点击链接前就完成这一过程。以下是几种开启预解析DNS的方法:

对于Web开发者,在HTML中使用标签:

在你的网页头部(部分),你可以添加如下DNS预解析链接标签,指定你希望浏览器预先解析的域名:

<head>
  <link rel="dns-prefetch" href="https://example.com">
</head>

这告诉浏览器提前解析example.com的DNS记录。

解释下bff层

BFF层,全称 Backend for Frontend,是一种软件架构设计模式,特别适用于现代的分布式和微服务系统中。它旨在通过为不同的前端应用(如网页、移动应用、智能设备应用等)提供专门定制化的后端服务,来优化用户体验和开发效率。

服务端路由和客户端路由有什么区别

服务端路由 是指在服务器端根据URL路径分发请求并返回相应内容的过程。当一个HTTP请求到达服务器时,服务端路由机制会解析URL,决定由哪个处理函数来响应这个请求,可能涉及加载数据、渲染视图等操作。服务端路由是实现SSR的基础,因为它控制着根据不同的URL路径返回不同的服务器渲染页面。

客户端路由 则是在浏览器中完成的路由处理。它不涉及服务器的页面重载,而是通过JavaScript监听URL变化,动态替换页面的部分内容或整体视图,实现页面间的切换效果。这种模式常见于单页面应用(SPA,Single Page Application),如使用React Router或Vue Router的Web应用。客户端路由提供了更流畅的用户体验,因为页面切换无需重新加载整个页面,但首次加载时需要下载更多的JavaScript代码,且对SEO不那么友好,除非采取特殊措施如预渲染或使用JavaScript支持的爬虫。

前端有个场景题。 有一个特别大的for循环,我希望将它执行完,但是它非常耗费时间,会阻碍dom渲染。 我最开始的方案是设置一个超时时间,比如说for循环执行3秒后,就停止for循环去进行dom渲染。但是这种方法记不住状态,每次又要重头执行,

所以,有什么好的解决办法吗

对于这种需要长时间运行的计算任务,而又不想阻塞UI线程影响用户体验的情况,可以采用Web Workers或请求AnimationFrame等技术来异步处理计算任务,从而避免阻塞主线程。以下是两种解决方案的简要介绍:

1. Web Workers

Web Workers 允许在后台线程执行脚本,这样就不会影响页面的性能。这对于大量计算或长时间运行的任务特别有用。

示例代码:

// main.js
if (window.Worker) {
  var myWorker = new Worker('worker.js');

  myWorker.onmessage = function(e) {
    console.log('Message received from worker: ' + e.data);
    // 在这里处理worker完成后的结果,比如更新DOM
  };

  myWorker.postMessage('Start the long task'); // 开始工作
} else {
  console.log('Your browser doesn't support web workers.');
}

然后,在worker.js文件中执行你的循环任务:

// worker.js
self.onmessage = function(e) {
  var data = e.data;
  // 执行你的大循环
  for (var i = 0; i < 1e9; i++) {
    // 进行计算...
  }
  self.postMessage('Task finished'); // 任务完成,向主线程发送消息
};

2. 分片执行与requestAnimationFrame

如果你的环境不支持Web Workers或者任务适合分批处理,你可以考虑将大循环分片,并利用requestAnimationFrame在浏览器重绘之前执行一部分任务,避免阻塞UI更新。

let i = 0;
const batchSize = 1000;
const maxIterations = 1e8; // 假设的大循环次数

function processBatch() {
  for (let j = 0; j < batchSize && i < maxIterations; j++, i++) {
    // 执行循环体内的操作
  }
  if (i < maxIterations) {
    // 在下一帧继续执行
    requestAnimationFrame(processBatch);
  } else {
    // 循环完成,可以在这里执行后续操作,如更新DOM
    console.log('Loop finished');
  }
}

// 开始执行
requestAnimationFrame(processBatch);

这种方法通过将任务拆分为小块并在每一帧中执行一部分,确保了DOM的及时更新,提高了用户体验。但请注意,这种方法的效率取决于batchSize的大小和实际任务的复杂度,可能需要根据实际情况调整。

前端工程化涉及到哪些技术

前端工程化涵盖了广泛的技术和实践,旨在提升开发效率、代码质量和项目的可维护性。以下是前端工程化中涉及的一些关键技术:

  1. 模块化与组件化
    • 模块化:利用ES6模块、CommonJS、AMD等规范组织代码,使代码结构清晰、易于管理和重用。
    • 组件化:使用React、Vue、Angular等前端框架构建可复用的UI组件,提高开发效率和代码复用率。
  1. 构建工具与任务自动化
    • Webpack、Rollup、Parcel:这些是常用的打包工具,能够对资源进行编译、压缩、合并、模块解析等,优化资源加载。
    • Gulp、Grunt、npm scripts:用于自动化执行开发任务,如编译Sass到CSS、代码校验、自动刷新浏览器等。
  1. 代码规范与质量控制
    • ESLint:静态代码分析工具,用于检查代码质量,遵循一定的编码规范。
    • Prettier:代码格式化工具,确保团队代码风格一致。
    • Jest、Mocha、Karma:单元测试和端到端测试框架,保障代码质量。
  1. 版本控制与包管理
    • Git:版本控制系统,管理代码变更历史,便于团队协作。
    • npm、Yarn:包管理工具,用于依赖管理、安装外部库和脚本执行。
  1. 持续集成与持续部署(CI/CD)
    • Jenkins、Travis CI、CircleCI、GitHub Actions:自动化测试、构建和部署流程,提高开发效率和交付速度。
  1. 状态管理
    • Redux、Vuex、MobX:集中管理应用程序状态,特别是对于大型复杂应用,有助于状态逻辑的清晰管理。
  1. 路由管理
    • React Router、Vue Router、Angular Router:管理前端应用的路由,实现页面间的导航和状态管理。
  1. 资源优化
    • 图片压缩、代码压缩(UglifyJS、Terser)、懒加载、CDN部署等技术,减少资源加载时间和提升用户体验。
  1. 预处理器与转译器
    • Babel:将ES6+代码转换为向后兼容的JavaScript版本。
    • Sass、Less:CSS预处理器,增加样式编写的功能性和可维护性。

通过这些技术的综合运用,前端工程化帮助开发者在复杂的项目中保持代码的可维护性和可扩展性,同时提升开发和迭代的速度。

前端如何实现准确的小数运算(在支付场景下)

这是因为JavaScript采用IEEE 754标准浮点数表示方法,导致某些十进制小数不能精确存储和运算。理解这一点是解决此类问题的基础。

在计算机内部,浮点数(包括小数)是以指数和尾数的形式存储的。由于二进制无法精确表示所有十进制小数,所以会导致部分小数在运算过程中产生微小误差。

  1. 比较小数时设置容差值**

function areNumbersEqual(a, b, epsilon = 0.00001) {

return Math.abs(a - b) < epsilon;

}

console.log(areNumbersEqual(0.1 + 0.2, 0.3)); // 输出:true

2. 使用toFixed() 或 toPrecision() 固定小数位数

对于显示给用户的小数结果,可以利用toFixed()方法保留指定位数的小数后进行比较或展示。


let result = (0.1 + 0.2).toFixed(2);

console.log(result); // 输出:"0.30"

3. 使用Big.js或Decimal.js等库进行精确计算

对于需要高精度计算的场合,推荐使用专门的数学库。


import Big from 'big.js';

let a = new Big(0.1);

let b = new Big(0.2);

let sum = a.plus(b);

console.log(sum.toString()); // 输出:"0.3"

如何设置缓存,使得新版本能够及时更新(前端后端如何配置)

为了确保新版本能够及时更新,前端和后端都需要采取一些措施来合理地管理缓存。以下是一些建议:

前端配置

  1. 利用版本控制
    • 在静态资源(如CSS、JS文件)的URL后面添加版本号或哈希值,例如 script.js?v=2.0 或 style.css?hash=ab123c。这样,当资源发生变化时,浏览器会将其视为全新的文件并重新下载。
  1. 使用Cache-Control和ETag
    • 服务器端可以设置Cache-Control头部来指示浏览器如何缓存资源。例如,Cache-Control: max-age=3600 指示资源可以被缓存1小时。
    • 使用ETag(实体标签)作为资源的唯一标识。当资源改变时,ETag也随之改变,促使浏览器重新请求资源。
  1. Service Worker更新策略
    • 对于PWA应用,可以通过编写Service Worker脚本来控制资源的缓存和更新策略。在新版本发布时,可以通过Service Worker的更新机制强制更新缓存内容。
  1. 利用动态导入
    • 在前端代码中,使用动态导入(如import())来懒加载某些模块,这样可以确保在需要时获取最新的代码。
  1. HTML Meta标签
    • 虽然不推荐,但在某些情况下,可以在HTML 中添加 来告诉浏览器不要缓存页面,但这会影响到所有资源。

后端配置

  1. 设置HTTP响应头
    • 在后端服务器配置中,为静态资源设置合适的Cache-Control、Expires和/或ETag头部,确保浏览器知道何时应该检查资源是否有更新。
  1. 配置CDN缓存策略
    • 如果使用了CDN,需要在CDN提供商的控制台中配置缓存规则,比如设置缓存时间、版本控制策略等,确保CDN节点能够及时获取到最新的资源。
  1. API版本控制
    • 对于API请求,实施版本控制策略,如在URL中包含版本号(如/api/v2/users)。这样,当API有重大变更时,客户端可以选择请求最新版本的API。

前端下载单个图片怎么操作

前端下载单个图片可以通过几种方法实现,以下是一些常见的技术方案:

1. 使用标签的download属性(适用于同源图片)

对于同源(即图片位于与网页相同的源下)的图片,可以直接使用HTML的标签配合download属性来实现图片的下载。

<a href="your-image-url.jpg" download="image-name.jpg">下载图片</a>

这段代码会在页面上生成一个链接,用户点击后就会触发图片的下载,并且可以自定义下载时的文件名。

2. 利用JavaScript动态创建标签(适用于动态生成的下载需求)

如果需要通过JavaScript来动态触发下载,可以这样做:

function downloadImage(url, name) {
  const link = document.createElement('a');
  link.href = url;
  link.download = name || 'image.jpg';
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}

// 使用方法
downloadImage('your-image-url.jpg', 'custom-name.jpg');

这段代码会创建一个隐藏的标签,设置其href为图片URL,并设置download属性,然后模拟点击来触发下载,之后立即移除这个标签。

502和504的区别,如果服务器挂了返回哪一个

  • 502 Bad Gateway: 这个错误通常意味着作为代理或网关的服务器从上游服务器收到了无效的响应。换句话说,当你尝试访问一个网站时,你实际上是在与一个前端服务器(例如Nginx)通信,这个前端服务器再进一步向实际处理请求的后端服务器转发请求。如果后端服务器没有正确响应或者响应的内容不是预期的格式,前端服务器就会返回502错误。常见原因包括后端服务器未运行、配置错误、或者网络问题导致两服务器间的通信中断。
  • 504 Gateway Timeout: 当作为代理或网关的服务器在等待后端服务器响应时超过了预设的时间阈值,就会返回504错误。这意味着请求确实到达了代理服务器,但是代理服务器在等待后端服务器响应的过程中超时,没有在规定时间内收到响应。这通常表明后端服务器处理请求的时间过长,可能是因为资源不足、请求过多、或者后端服务本身存在性能瓶颈。

有一些pdf点开是展示,有一些点击是直接下载,是前端配置的还是后端,如何配置的?

PDF文件在浏览器中的行为(是直接展示还是下载)主要受以下几个因素影响:

  1. 前端配置
  1. 后端配置
    • HTTP响应头设置:如上所述,通过调整Content-Disposition和MIME类型,后端可以指定浏览器应如何处理文件。
    • 服务器配置:不同的Web服务器(如Apache、Nginx)有各自的配置方法来控制文件的下载行为。例如,在Nginx中,可以通过修改location块的配置来改变Content-Disposition的值。
  1. 浏览器设置和特性
    • 浏览器自身的设置和能力也会影响这一行为。一些浏览器默认配置为直接预览PDF,而用户也可以自行更改这些设置。此外,是否直接展示还依赖于浏览器是否内置了PDF阅读器功能。

nginx

Nginx是一款高性能的Web服务器和反向代理服务器,同时也可作为邮件代理服务器。它以其稳定性、低内存消耗和高并发连接处理能力而闻名,常被用于部署静态网站、代理服务器和负载均衡等场景。

proxy

Proxy 在 JavaScript 和 TypeScript 中是一个强大的特性,用于创建对象的代理,可以拦截并自定义对象上的基本操作。这使得开发者能够在访问或修改对象的属性、调用方法、遍历对象等操作之前插入自定义逻辑。以下是关于 Proxy 的一些关键点:

基本概念

  • 构造函数: Proxy 是一个构造函数,用于生成代理对象。你可以通过 new Proxy(target, handler) 来创建一个新的代理实例,其中 target 是被代理的对象,而 handler 是一个定义了代理行为的对象,包含一系列称为陷阱(traps)的方法。
  • 陷阱(Traps) : 这些方法在代理对象上的操作被触发时执行,允许你定义拦截后的自定义行为。比如,get 陷阱在访问属性时被调用,set 陷阱在设置属性值时被调用,还有其他如 apply、has、deleteProperty 等陷阱。

range怎么生成一个dom节点?

Range对象本身并不直接用于生成DOM节点,而是用于操作文档中的选定内容区域。不过,你可以结合Range与其他DOM方法来创建和插入新的DOM节点。下面是一个基本示例,展示了如何使用Range来辅助生成并插入一个新的DOM节点:

假设我触发修改某个数值的按钮和依赖这个数值的视图不在一个地方,我该如何通信(原生js的情况下)

在原生JavaScript中,实现不同部分之间的通信(比如修改数值的按钮与依赖该数值的视图)通常可以通过以下几种方式来完成:

1. 事件监听与发布/订阅模式

  • 事件监听: 可以给修改数值的按钮添加一个事件监听器,当按钮被点击时,触发一个函数来修改数据,并触发一个自定义事件通知其他部分更新。
  • 发布/订阅模式: 对于更复杂的场景,可以实现一个简单的事件总线(Event Bus)来解耦发布者和订阅者。

2. 全局变量与闭包

虽然不是最佳实践,但在简单的应用中,可以通过维护全局变量并在需要的地方检查变量的改变来实现通信。使用闭包可以帮助限制对全局变量的直接访问,提高代码的封装性。

3. 使用 localStorage sessionStorage

对于需要跨页面通信的情况,可以利用Web Storage API(如localStorage或sessionStorage)来存储共享数据。当数值改变时,写入存储,其他部分通过监听存储变化或定期检查存储来更新视图。

4. 直接调用函数

如果两个部分之间有明确的关联,可以直接在事件处理函数中调用另一个部分负责更新视图的函数。这种方式直接但不够灵活,增加了各部分间的耦合度。

你说的网关是什么?解释一下计算机网络中网关这个概念。

在计算机网络中,网关(Gateway)是一个非常重要的概念,它充当着不同网络或子网之间的桥梁,负责在这些网络之间传输数据包。简而言之,网关是连接两个不同网络,并能对数据包进行转发的设备。它能够理解并转换两种网络之间不同的通信协议,使得信息能够在不同类型的网络间流通。

具体来说,网关具有以下几个关键特性:

  1. 协议转换:网关能够实现不同网络协议之间的转换。例如,当一个使用IPv4协议的网络需要与使用IPv6协议的网络通信时,网关会负责将数据包从一种协议格式转换为另一种,确保双方能够正确理解对方的数据。
  2. 网络分隔:网关可以作为不同网络或子网之间的边界设备,帮助实现网络分段,增强网络的安全性和管理便利性。
  3. 路由功能:网关具备路由功能,能够决定数据包的最佳路径,将数据有效地从一个网络转发到另一个网络。它维护着一张路由表,根据表中的信息来指导数据的转发。
  4. 访问控制:在很多情况下,网关还承担着网络安全的角色,通过实施访问控制列表(ACL)、防火墙规则等措施,控制不同网络间的数据流动,保护内部网络不受外部威胁。
  5. 多服务集成:在某些应用场景下,如家庭网络中的智能网关,除了基本的网络互联功能外,还可能集成Wi-Fi接入点、路由器、网络地址转换(NAT)服务、甚至智能家居控制中心等功能。

Array.from原理

Array.from() 方法是JavaScript中的一个内置函数,用于将类数组对象或可迭代对象转换为一个新的数组实例。它的主要原理和用途如下:

原理

  1. 接收参数:Array.from() 方法接受一到三个参数:
    • 第一个参数是必需的,通常是一个类数组对象(拥有length属性和索引元素)或可迭代对象(如Map、Set、生成器函数等)。
    • 第二个参数是可选的,是一个映射函数(mapFunction),对每个元素执行此函数,并将返回值放入新数组中对应位置。
    • 第三个参数也是可选的,是对映射函数中this的绑定。
  1. 转换过程
    • 首先,方法会检查第一个参数是否为可迭代对象。如果是,则遍历该对象,将遍历到的每一项作为新数组的元素。
    • 如果第一个参数是类数组对象,则会根据其length属性创建相应长度的新数组,并复制元素。
    • 映射函数(如果提供)会在每个元素被添加到新数组前执行,允许对元素进行转换处理。
    • 最后,返回由处理后的元素组成的新数组。

已知js有一个insertBefore的api,那么我要怎么实现insertAfter呢?

在JavaScript中,虽然没有直接的insertAfter API,但你可以通过组合使用现有的DOM操作方法来实现类似的功能。下面是一个简单的方法来实现insertAfter的效果:

function insertAfter(newElement, targetElement) {
  // 获取目标元素的父节点
  const parent = targetElement.parentNode;

  // 检查父节点是否存在以及目标元素不是最后一个子节点
  if (parent && parent.lastChild === targetElement) {
    // 如果目标元素是最后一个子节点,则直接appendChild
    parent.appendChild(newElment);
  } else {
    // 否则,在目标元素之后插入新元素
    parent.insertBefore(newElement, targetElement.nextSibling);
  }
}

这个函数接受两个参数:newElement是要插入的新元素,而targetElement是在其之后插入新元素的目标元素。函数首先获取目标元素的父节点,然后判断目标元素是否为其父节点的最后一个子节点。如果是最后一个子节点,则直接使用appendChild将其添加到父节点的末尾;如果不是,则使用insertBefore将新元素插入到目标元素的下一个兄弟节点之前,从而实现了“插入在之后”的效果。

二进制浮点数运算产生的精度问题

console.log(0.1 + 0.2 === 0.3);
console.log(0.1 * 0.2 === 0.3);
console.log(0.2 + 0.2 === 0.4);  // true
console.log(0.2 * 0.2 === 0.4);
// 其他都是false

0.1和0.2的和由于二进制浮点表示的限制,并不能精确表示为十进制的0.3,所以直接比较0.1 + 0.2与0.3时,由于精度丢失,结果并不会严格相等。

但0.2 + 0.2恰好在JavaScript的浮点数精度范围内能够精确表示为0.4,因此这行代码在多数情况下会输出true。

哪些标签可以跨域加载资源,怎么加载

  1. <img>: 用于加载图片资源。

  2. <script>: 用于加载JavaScript文件。无论JavaScript文件的来源如何

  3. <link>: 主要用于加载CSS样式表文件,同样支持跨域加载

  4. <video><audio>: 这两个标签可以用来加载跨域的多媒体资源,如视频和音频文件。

  5. *<iframe>

哪些方法能对上述标签里面的内容进行修改

可以使用innerTexttextContent属性

localstorage如果被用户改了怎么办,怎么解决

localStorage 存储的数据容易受到用户修改,因为它们直接存储在客户端,用户可以通过浏览器的开发者工具轻松访问和修改这些数据。这种修改可能导致应用程序状态不一致或安全风险。为了解决这个问题,可以采取以下几种策略:

  1. 验证数据:在从localStorage读取数据后,始终在代码中进行数据验证。确保数据格式正确,符合预期的值范围或结构。例如,如果存储的是用户身份验证令牌,可以验证令牌的格式、过期时间等。
  2. 加密数据:在存储数据到localStorage之前对其进行加密,取出时解密。这样即使用户修改了存储的值,他们也无法理解或正确修改加密后的数据。需要注意的是,加密和解密过程会增加一定的性能开销。
  3. 使用HTTP-only Cookie:对于敏感信息,如认证令牌,考虑使用HTTP-only Cookie存储,因为这类Cookie不能通过JavaScript访问,从而减少了XSS攻击的风险。
  4. 签名数据:在存储数据时,可以附加一个基于数据内容计算的签名或哈希值。当数据被读取时,重新计算签名并与存储的签名进行比较,以此来验证数据的完整性和真实性。

网关和代理是一个意思吗?

  1. 网关(Gateway) :
    • 网关是连接两个不同网络的设备,它可以执行协议转换任务,使得使用不同协议的系统能够相互通信。
    • 网关通常位于网络的边缘,作为从一个网络到另一个网络的入口点,它可能需要处理不同类型的流量,并且能够将一种协议的数据包转换为另一种协议的数据包。
    • 网关可能还承担着安全性角色,比如防火墙功能,控制不同网络之间的数据流。
    • 网关通常比代理更深入地参与到通信过程中,不仅仅是简单的转发,还可能对数据包的内容或格式进行转换。

总结来说,代理主要关注于请求的转发和可能的修改,而网关则侧重于不同网络或协议之间的转换和桥接。两者都是网络架构中的重要组件,但各自有着明确的用途和功能定位。

return 能穿透多层for循环

function fn() {
  for (let i = 0; i < 10; i++) {
    if (i === 2) {
      return i
    }
  }
}
console.log(fn()); // 2





function fns() {
  for (let i = 0; i < 10; i++) {
    for (let j = 0; j < 5; j++) {
      if (j === 3) {
        return j  // 只要return, 两层for都直接结束。break没有这种效果。
      }
    }

  }


}
console.log(fns()); // 3