ToB企服应用市场:ToB评测及商务社交产业平台

标题: 前端杂学录(八) [打印本页]

作者: 农民    时间: 2024-10-15 03:01
标题: 前端杂学录(八)
1.HTTP哀求报文和相应报文的具体组成,能明白常见哀求头的寄义,有几种哀求方式,区别是什么

1. HTTP 哀求报文的组成

一个 HTTP 哀求报文通常包罗以下几个部门:
1.1 哀求行


  1. GET /index.html HTTP/1.1
复制代码
1.2 哀求头

哀求头包罗了多个字段,用于传递额外的信息。常见的哀求头包括:

  1. Host: www.example.com
  2. User-Agent: Mozilla/5.0
  3. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
复制代码
1.3 空行

哀求头与哀求体之间有一个空行,表示哀求头部门的结束。
1.4 哀求体

哀求体包罗了要发送给服务器的数据,通常在 POST、PUT 等方法中使用。GET 方法通常没有哀求体。
  1. name=John&age=30
复制代码
2. HTTP 相应报文的组成

一个 HTTP 相应报文同样包罗几个部门:
2.1 相应行


  1. HTTP/1.1 200 OK
复制代码
2.2 相应头

相应头同样包罗多个字段,用于传递额外的信息。常见的相应头包括:

  1. Content-Type: text/html; charset=UTF-8
  2. Content-Length: 1234
复制代码
2.3 空行

相应头与相应体之间有一个空行,表示相应头部门的结束。
2.4 相应体

相应体包罗服务器返回的数据(如 HTML 页面、JSON 数据等)。
示例:
  1. <html>...</html>
复制代码
3. 常见哀求方式及其区别

HTTP 支持多种哀求方法,主要包括:
3.1 GET


3.2 POST


3.3 PUT


3.4 DELETE


3.5 HEAD


3.6 OPTIONS


2.HTTP所有状态码的具体寄义,看到非常状态码能快速定位问题

1. 1xx:信息性状态码

这些状态码表示哀求已被吸收并正在处置惩罚。

2. 2xx:成功状态码

这些状态码表示哀求已成功处置惩罚。

3. 3xx:重定向状态码

这些状态码表示哀求需要进一步操作才气完成。

4. 4xx:客户端错误状态码

这些状态码表示哀求存在问题,导致服务器无法处置惩罚。

5. 5xx:服务器错误状态码

这些状态码表示服务器在处置惩罚哀求时发生了错误。

6. 如何快速定位问题

当遇到非常状态码时,可以根据状态码的种别和具体寄义快速定位问题:

3.HTTP1.1、HTTP2.0带来的改变

1. HTTP/1.1 的特点


2. HTTP/2.0 的改变

2.1 二进制协议


2.2 多路复用


2.3 头部压缩


2.4 服务器推送


2.5 连接复用


2.6 更好的流量控制


3. 总结

HTTP/2.0 在多个方面对 HTTP/1.1 进行了明显改进,主要包括:

4.HTTPS的加密原理,如何开启HTTPS,如何劫持HTTPS哀求

1. HTTPS 的加密原理

1.1 SSL/TLS 协议

HTTPS 基于 SSL(安全套接层)或 TLS(传输层安全协议)协议工作。其主要功能包括:

1.2 加密过程

2. 如何开启 HTTPS

要在网站上启用 HTTPS,需要遵循以下步骤:
2.1 获取 SSL/TLS 证书


2.2 安装证书


2.3 重定向 HTTP 到 HTTPS


2.4 测试 HTTPS


3. 如何劫持 HTTPS 哀求

尽管 HTTPS 提供了安全保障,但在一些情况下,攻击者仍大概实验劫持 HTTPS 哀求。以下是一些常见的攻击方法:
3.1 中间人攻击(MITM)


3.2 SSL 剥离攻击


3.3 恶意软件


5.明白WebSocket协议的底层原理、与HTTP的区别

1. WebSocket 协议的底层原理

1.1 创建连接


1.2 数据帧结构


1.3 持久连接


2. WebSocket 与 HTTP 的区别

特性HTTPWebSocket连接范例无状态的哀求-相应模子持久的全双工连接创建连接每个哀求都需要创建和关闭连接仅在初始握手时创建一次连接数据传输单向哀求-相应双向实时传输数据格式文本格式二进制和文本格式性能每次哀求都需重新传输 HTTP 头部传输数据时只需较小的帧头适用场景得当哀求-相应的应用得当实时应用(如聊天、游戏) 6.多种方式实现数组去重、扁平化、对比优缺点

1. 数组去重

1.1 使用 Set

  1. const uniqueArray = [...new Set(array)];
复制代码
优点


缺点


1.2 使用 filter 和 indexOf

  1. const uniqueArray = array.filter((item, index) => array.indexOf(item) === index);
复制代码
优点


缺点


1.3 使用 reduce

  1. const uniqueArray = array.reduce((acc, item) => {
  2.   if (!acc.includes(item)) {
  3.     acc.push(item);
  4.   }
  5.   return acc;
  6. }, []);
复制代码
优点


缺点


1.4 使用对象或 Map

  1. const uniqueArray = Object.keys(array.reduce((acc, item) => {
  2.   acc[item] = true;
  3.   return acc;
  4. }, {}));
复制代码
优点


缺点


2. 数组扁平化

2.1 使用 flat 方法(ES2019)

  1. const flatArray = array.flat();
复制代码
优点


缺点


2.2 使用 reduce 递归

  1. const flatten = (arr) => arr.reduce((acc, item) =>
  2.   Array.isArray(item) ? acc.concat(flatten(item)) : acc.concat(item), []);
复制代码
优点


缺点


2.3 使用 forEach 递归

  1. const flatten = (arr) => {
  2.   const result = [];
  3.   arr.forEach(item => {
  4.     if (Array.isArray(item)) {
  5.       result.push(...flatten(item));
  6.     } else {
  7.       result.push(item);
  8.     }
  9.   });
  10.   return result;
  11. };
复制代码
优点


缺点


2.4 使用 concat 和 apply

  1. const flatten = (arr) => [].concat.apply([], arr);
复制代码
优点


缺点


3. 总结

数组去重


数组扁平化


7.JSON.parse和JSON.stringify

JSON.parse 和 JSON.stringify 是 JavaScript 中用于处置惩罚 JSON 数据的两个内置函数。
JSON.parse

JSON.parse() 函数用于将 JSON 字符串转换为 JavaScript 对象。
语法:
  1. JSON.parse(text[, reviver])
复制代码

示例:
  1. const jsonString = '{"name": "Kimi", "age": 30}';
  2. const obj = JSON.parse(jsonString);
  3. console.log(obj.name); // 输出: Kimi
复制代码
假如提供了 reviver 函数,它会对解析后的对象中的每个键值对进行处置惩罚:
  1. const jsonString = '{"name": "Kimi", "age": 30}';
  2. const obj = JSON.parse(jsonString, (key, value) => {
  3.   if (key === "age") {
  4.     return value + 10; // 修改年龄
  5.   }
  6.   return value;
  7. });
  8. console.log(obj.age); // 输出: 40
复制代码
JSON.stringify

JSON.stringify() 函数用于将 JavaScript 对象转换为 JSON 字符串。
语法:
  1. JSON.stringify(value[, replacer[, space]])
复制代码

示例:
  1. const obj = { name: "Kimi", age: 30 };
  2. const jsonString = JSON.stringify(obj);
  3. console.log(jsonString); // 输出: {"name":"Kimi","age":30}
复制代码
假如提供了 replacer 函数,它会决定哪些属性/对象应该被包罗在 JSON 字符串中:
  1. const obj = { name: "Kimi", age: 30, city: "Shanghai" };
  2. const jsonString = JSON.stringify(obj, (key, value) => {
  3.   if (key === "city") {
  4.     return undefined; // 从 JSON 字符串中排除 'city'
  5.   }
  6.   return value;
  7. });
  8. console.log(jsonString); // 输出: {"name":"Kimi","age":30}
复制代码
假如提供了 space 参数,可以美化输出:
  1. const jsonString = JSON.stringify(obj, null, 2);
  2. console.log(jsonString);
  3. /*
  4. 输出:
  5. {
  6.   "name": "Kimi",
  7.   "age": 30
  8. }
  9. */
复制代码
注意事项


8.多种方式实现深拷贝、对比优缺点

1. 使用 JSON 方法

代码示例

  1. const deepCopy = (obj) => JSON.parse(JSON.stringify(obj));
复制代码
优点


缺点


2. 使用递归

代码示例

  1. const deepCopy = (obj) => {
  2.   if (obj === null || typeof obj !== 'object') {
  3.     return obj; // 基本类型直接返回
  4.   }
  5.   if (Array.isArray(obj)) {
  6.     return obj.map(item => deepCopy(item)); // 处理数组
  7.   }
  8.   const copy = {};
  9.   for (const key in obj) {
  10.     if (obj.hasOwnProperty(key)) {
  11.       copy[key] = deepCopy(obj[key]); // 递归拷贝
  12.     }
  13.   }
  14.   return copy;
  15. };
复制代码
优点


缺点


3. 使用 Lodash 库的 cloneDeep

代码示例

  1. // 需要安装 lodash
  2. const _ = require('lodash');
  3. const deepCopy = (obj) => _.cloneDeep(obj);
复制代码
优点


缺点


4. 使用 Object.assign(得当浅拷贝)

代码示例

  1. const shallowCopy = (obj) => Object.assign({}, obj);
复制代码
优点


缺点


5. 使用 structuredClone(现代浏览器)

代码示例

  1. const deepCopy = (obj) => structuredClone(obj);
复制代码
优点


缺点


6. 总结

适用场景和总结


9.手写函数柯里化工具函数、并明白其应用场景和上风

1. 手写柯里化函数

代码示例

  1. function curry(fn) {
  2.   // 获取函数的参数数量
  3.   const arity = fn.length;
  4.   // 内部递归函数实现柯里化
  5.   function curried(...args) {
  6.     // 如果传入的参数数量满足要求,调用原函数
  7.     if (args.length >= arity) {
  8.       return fn(...args);
  9.     }
  10.     // 否则,返回一个新函数,继续接收参数
  11.     return (...next) => curried(...args, ...next);
  12.   }
  13.   return curried;
  14. }
复制代码
使用示例

  1. // 一个简单的加法函数
  2. function add(x, y, z) {
  3.   return x + y + z;
  4. }
  5. // 使用柯里化工具函数
  6. const curriedAdd = curry(add);
  7. console.log(curriedAdd(1)(2)(3)); // 6
  8. console.log(curriedAdd(1, 2)(3));  // 6
  9. console.log(curriedAdd(1, 2, 3));  // 6
复制代码
2. 应用场景

2.1 参数复用

柯里化可以让你创建一个新的函数,固定某些参数。如允许以避免重复传递雷同的参数。
  1. const multiply = (x, y) => x * y;
  2. const curriedMultiply = curry(multiply);
  3. const double = curriedMultiply(2); // 固定第一个参数为 2
  4. console.log(double(5)); // 10
复制代码
2.2 函数组合

柯里化使得函数组合变得更加简朴。可以将多个小函数组合成一个复杂的函数。
  1. const add = (x, y) => x + y;
  2. const multiply = (x, y) => x * y;
  3. const curriedAdd = curry(add);
  4. const curriedMultiply = curry(multiply);
  5. const incrementAndDouble = (num) => curriedMultiply(2)(curriedAdd(1)(num));
  6. console.log(incrementAndDouble(3)); // 8
复制代码
2.3 耽误执行

柯里化可以用于实现耽误执行,直到满足特定条件时才调用函数。
  1. const logMessage = (level) => (message) => {
  2.   console.log(`[${level}] ${message}`);
  3. };
  4. const infoLogger = logMessage('INFO');
  5. infoLogger('This is an info message.'); // [INFO] This is an info message.
复制代码
3. 上风


10.手写防抖和节省工具函数、并明白其内部原理和应用场景

1. 防抖(Debouncing)

1.1 原理

防抖的核心思想是:在变乱被触发后,设定一个耽误时间,假如在这个时间内再次触发变乱,则重新计时。只有在变乱触发结束后的耽误时间内没有再次触发,才会执行回调函数。
1.2 代码示例

  1. function debounce(func, delay) {
  2.   let timer;
  3.   return function (...args) {
  4.     const context = this;
  5.     clearTimeout(timer); // 清除之前的定时器
  6.     timer = setTimeout(() => {
  7.       func.apply(context, args); // 在延迟时间后执行回调
  8.     }, delay);
  9.   };
  10. }
复制代码
1.3 应用场景


2. 节省(Throttling)

2.1 原理

节省的核心思想是:规定在一定时间内只允许函数执行一次,无论该变乱触发多少次,回调函数只会在规定的时间间隔内被调用一次。
2.2 代码示例

  1. function throttle(func, limit) {
  2.   let lastFunc;
  3.   let lastRan;
  4.   return function (...args) {
  5.     const context = this;
  6.     if (!lastRan) {
  7.       func.apply(context, args); // 立即执行
  8.       lastRan = Date.now(); // 记录执行时间
  9.     } else {
  10.       clearTimeout(lastFunc); // 清除之前的定时器
  11.       lastFunc = setTimeout(() => {
  12.         if (Date.now() - lastRan >= limit) {
  13.           func.apply(context, args); // 在限制时间后执行
  14.           lastRan = Date.now(); // 更新上次执行时间
  15.         }
  16.       }, limit - (Date.now() - lastRan));
  17.     }
  18.   };
  19. }
复制代码
2.3 应用场景


3. 总结

3.1 防抖与节省的区别

特性防抖(Debounce)节省(Throttle)触发时机变乱触发后耽误执行在规定时间间隔内只执行一次应用场景得当处置惩罚用户输入、搜索等需要耽误的操作得当处置惩罚高频率的变乱,如滚动、窗口调解 3.2 选择使用


11.实现一个sleep函数

1. 使用 Promise 实现 sleep 函数

代码示例

  1. function sleep(ms) {
  2.   return new Promise(resolve => setTimeout(resolve, ms));
  3. }
复制代码
使用示例

你可以通过 async/await 语法来使用这个 sleep 函数:
  1. async function demo() {
  2.   console.log("Start sleeping...");
  3.   await sleep(2000); // 暂停 2 秒
  4.   console.log("Awake after 2 seconds!");
  5. }
  6. demo();
复制代码
2. 表明

2.1 如何工作


2.2 上风


12.手动实现call、apply、bind

实现 call 方法

  1. Function.prototype.call = function(context, ...args) {
  2.   // 若没有传入上下文或者传入的上下文为null,则默认上下文为window
  3.   if (typeof context !== 'object' && typeof context !== 'function') {
  4.     context = window;
  5.   }
  6.   
  7.   // 给 context 添加一个属性,值为函数本身,然后执行函数
  8.   const fnSymbol = Symbol(); // 使用Symbol保证不会重复
  9.   context[fnSymbol] = this;
  10.   // 执行函数
  11.   const result = context[fnSymbol](...args);
  12.   // 删除刚才添加的属性
  13.   delete context[fnSymbol];
  14.   // 返回执行结果
  15.   return result;
  16. };
复制代码
实现 apply 方法

  1. Function.prototype.apply = function(context, argsArray) {
  2.   // 若没有传入上下文或者传入的上下文为null,则默认上下文为window
  3.   if (typeof context !== 'object' && typeof context !== 'function') {
  4.     context = window;
  5.   }
  6.   
  7.   // 给 context 添加一个属性,值为函数本身,然后执行函数
  8.   const fnSymbol = Symbol();
  9.   context[fnSymbol] = this;
  10.   // 执行函数
  11.   let result;
  12.   if (argsArray) {
  13.     result = context[fnSymbol](...argsArray);
  14.   } else {
  15.     result = context[fnSymbol]();
  16.   }
  17.   // 删除刚才添加的属性
  18.   delete context[fnSymbol];
  19.   // 返回执行结果
  20.   return result;
  21. };
复制代码
实现 bind 方法

  1. Function.prototype.bind = function(context, ...args) {
  2.   // 保存原函数
  3.   const fn = this;
  4.   // 绑定函数
  5.   return function(...newArgs) {
  6.     // 若传入的上下文为null或undefined,则默认上下文为window
  7.     if (typeof context !== 'object' && typeof context !== 'function') {
  8.       context = window;
  9.     }
  10.     // 如果原函数是构造函数,则无法使用bind
  11.     if (this instanceof fn.bind) {
  12.       return new fn(...args, ...newArgs);
  13.     }
  14.     // 执行原函数
  15.     return fn.apply(context, args.concat(newArgs));
  16.   };
  17. };
复制代码
表明


注意事项


 13.手写一个EventEmitter实现变乱发布、订阅


1. EventEmitter 实现

代码示例

  1. class EventEmitter {
  2.   constructor() {
  3.     this.events = {}; // 存储事件及其对应的回调函数
  4.   }
  5.   // 订阅事件
  6.   on(event, listener) {
  7.     if (!this.events[event]) {
  8.       this.events[event] = []; // 创建事件数组
  9.     }
  10.     this.events[event].push(listener); // 添加回调函数
  11.   }
  12.   // 发布事件
  13.   emit(event, ...args) {
  14.     if (this.events[event]) {
  15.       this.events[event].forEach(listener => {
  16.         listener(...args); // 调用所有回调函数
  17.       });
  18.     }
  19.   }
  20.   // 取消订阅
  21.   off(event, listener) {
  22.     if (!this.events[event]) return;
  23.     this.events[event] = this.events[event].filter(l => l !== listener); // 移除指定的回调函数
  24.   }
  25.   // 只监听一次的事件
  26.   once(event, listener) {
  27.     const onceListener = (...args) => {
  28.       listener(...args); // 调用原回调函数
  29.       this.off(event, onceListener); // 取消订阅
  30.     };
  31.     this.on(event, onceListener); // 注册一次性回调
  32.   }
  33. }
复制代码
2. 使用示例

  1. const emitter = new EventEmitter();
  2. // 订阅事件
  3. const greet = (name) => {
  4.   console.log(`Hello, ${name}!`);
  5. };
  6. emitter.on('greet', greet);
  7. // 发布事件
  8. emitter.emit('greet', 'Alice'); // Hello, Alice!
  9. emitter.emit('greet', 'Bob');   // Hello, Bob!
  10. // 取消订阅
  11. emitter.off('greet', greet);
  12. emitter.emit('greet', 'Charlie'); // 没有输出,因为回调已被取消
  13. // 只监听一次的事件
  14. emitter.once('onceEvent', (msg) => {
  15.   console.log(`This will be logged only once: ${msg}`);
  16. });
  17. emitter.emit('onceEvent', 'First Call'); // This will be logged only once: First Call
  18. emitter.emit('onceEvent', 'Second Call'); // 没有输出
复制代码
3. 总结

3.1 功能概述


3.2 扩展功能


14.说出两种实现双向绑定的方案

1. Object.defineProperty 实现双向绑定

原理

通过 Object.defineProperty 方法,可以劫持对象的属性访问和赋值,进而实现数据变革时主动更新视图。
实现步骤

优点


缺点


2. Proxy 实现双向绑定

原理

使用 Proxy 对对象进行代理,可以拦截对对象的根本操作,如读取和写入,提供更灵活的方式来实现双向绑定。
实现步骤

优点


缺点


15.手动实现双向绑定

HTML 结构

  1. <div>
  2.   <input type="text" id="inputElement" />
  3.   <p>Value: <span id="textElement"></span></p>
  4. </div>
复制代码
JavaScript 实现

  1. // 获取 DOM 元素
  2. const inputElement = document.getElementById('inputElement');
  3. const textElement = document.getElementById('textElement');
  4. // 初始化数据
  5. let data = '';
  6. // 观察者对象
  7. const observer = {
  8.   subscribe(callback) {
  9.     this._callbacks = callback;
  10.   },
  11.   notify() {
  12.     if (this._callbacks) {
  13.       this._callbacks();
  14.     }
  15.   }
  16. };
  17. // 将数据和视图绑定
  18. function bindData(dataInitialValue) {
  19.   data = dataInitialValue;
  20.   // 当输入框的内容改变时,更新数据
  21.   inputElement.addEventListener('input', (event) => {
  22.     data = event.target.value;
  23.     observer.notify();
  24.   });
  25.   // 更新视图
  26.   function updateView() {
  27.     textElement.textContent = data;
  28.   }
  29.   // 订阅并更新视图
  30.   observer.subscribe(updateView);
  31.   // 初始更新视图
  32.   updateView();
  33. }
  34. // 初始化绑定
  35. bindData('Initial Value');
复制代码
表明

工作原理

扩展

为了使其更加通用,我们可以创建一个更加灵活的双向绑定函数:
  1. function twoWayBind(inputElement, viewElement, initialValue) {
  2.   let data = initialValue;
  3.   const observer = {
  4.     subscribe(callback) {
  5.       this._callbacks = callback;
  6.     },
  7.     notify() {
  8.       if (this._callbacks) {
  9.         this._callbacks();
  10.       }
  11.     }
  12.   };
  13.   inputElement.value = data;
  14.   viewElement.textContent = data;
  15.   function updateData(event) {
  16.     data = event.target.value;
  17.     observer.notify();
  18.   }
  19.   function updateView() {
  20.     viewElement.textContent = data;
  21.   }
  22.   inputElement.addEventListener('input', updateData);
  23.   observer.subscribe(updateView);
  24.   updateView(); // 初始更新视图
  25. }
  26. const inputElement = document.getElementById('inputElement');
  27. const textElement = document.getElementById('textElement');
  28. twoWayBind(inputElement, textElement, 'Initial Value');
复制代码
表明


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




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4