网站产品推广,旅游电子商务 网站建设,公司宣传片制作公司,腾讯云服务器 学生目录 系列文章目录JavaScript知识系列#xff08;1#xff09;每天10个小知识点JavaScript知识系列#xff08;2#xff09;每天10个小知识点JavaScript知识系列#xff08;3#xff09;每天10个小知识点 知识点**31. Promise** 的概念、作用、原理、特性、优点、缺点、区… 目录 系列文章目录JavaScript知识系列1每天10个小知识点JavaScript知识系列2每天10个小知识点JavaScript知识系列3每天10个小知识点 知识点**31. Promise** 的概念、作用、原理、特性、优点、缺点、区别、使用场景**32. Promise 解决了什么问题****33. async/await** 的概念、作用、原理、特性、优点、缺点、区别、使用场景34.****和 有什么不同******35. async/await 对比 Promise 的优势****36. 对象创建的方式有哪些****37. 对象继承的方式有哪些****38. 哪些情况会导致内存泄漏**39.在 **JavaScript** 中 **0.1 0.2 0.3** 吗**?** 请阐述原因并给出解决⽅案40.**Event Loop**的概念、作用、原理、特性、优点、缺点、区别、使用场景 点赞你的认可是我创作的动力
⭐️ 收藏你的青睐是我努力的方向
✏️ 评论你的意见是我进步的财富 系列文章目录
JavaScript知识系列1每天10个小知识点
JavaScript知识系列2每天10个小知识点
JavaScript知识系列3每天10个小知识点
知识点
31. Promise 的概念、作用、原理、特性、优点、缺点、区别、使用场景
Promise 是 JavaScript 中用于处理异步操作的对象它具有以下特性和用途
概念
Promise 是一个代表异步操作的对象可以是已完成、未完成或失败状态。它提供了一种更可控和清晰的方式来处理异步操作避免了回调地狱。
作用
主要用于处理异步操作如网络请求、文件读取、定时器等。Promise 可以更好地管理和组织异步代码提供了更好的错误处理机制。
原理
Promise 对象包含三种状态未完成pending、已完成fulfilled、失败rejected。当异步操作完成时Promise 变为已完成状态并触发 .then() 方法如果出现错误它变为失败状态并触发 .catch() 方法。
特性
Promise 是一个对象具有 .then()、.catch() 和 .finally() 方法用于处理成功、失败和无论成功失败都要执行的情况。Promise 是不可变的一旦状态改变就不会再变。
优点
更清晰的异步代码结构避免了回调地狱。提供了良好的错误处理机制可以通过 .catch() 捕获和处理错误。支持链式操作允许按顺序执行多个异步任务。可以在多个异步操作之间共享和传递数据。
缺点
对于一些简单的异步任务使用 Promise 可能会显得繁琐因为需要创建新的 Promise 对象。Promise 无法取消一旦创建就无法中途终止异步操作。需要学习 Promise 的用法有一定的学习曲线。
区别
Promise 与回调函数相比更容易管理异步操作可以更好地控制和组织代码。Promise 与事件监听相比更适用于单次异步操作的处理而事件监听适用于多次事件的触发。Promise 与 async/await 相比提供了更底层的异步控制而 async/await 是 Promise 的一种更高级的语法糖。
使用场景
处理网络请求、文件读取、定时器等异步操作。在需要顺序执行多个异步任务的情况下可以使用 Promise 链。与其他异步库如axios一起使用以获取更好的代码组织和错误处理。
32. Promise 解决了什么问题
Promise 解决了异步编程中的一些常见问题主要包括以下几个方面
回调地狱Callback Hell 在传统的回调函数中多个嵌套的回调函数容易导致代码的可读性差难以维护和调试。Promise 通过链式调用 .then() 方法提供了更清晰的异步代码结构避免了回调地狱。 错误处理Error Handling 在回调函数中错误处理通常通过传递错误对象给回调函数来实现容易忽略错误。Promise 提供了 .catch() 方法专门用于捕获和处理异步操作中的错误提高了错误处理的可靠性。 多个异步操作的同步控制 在需要依次执行多个异步任务并等待它们全部完成时回调函数方式会变得复杂。Promise 允许使用 Promise.all() 或 Promise.race() 来控制多个异步操作的执行提供了更好的同步控制能力。 可复用性和组合性 Promise 对象是不可变的可以在多个地方共享和传递提高了代码的可复用性和组合性。可以将多个 Promise 链式连接构建复杂的异步操作流程。 传递数据 在回调函数中需要通过回调函数参数来传递数据容易引发回调地狱。Promise 允许异步操作的结果在不同的 .then() 方法之间传递使数据传递更直观和可控。
总之Promise 解决了异步编程中的可读性、错误处理、同步控制、可复用性和数据传递等问题使异步代码更容易理解、维护和扩展。它成为现代 JavaScript 中处理异步操作的一种标准方式。
33. async/await 的概念、作用、原理、特性、优点、缺点、区别、使用场景
async/await 是 JavaScript 中用于处理异步操作的现代语法特性它具有以下特性和用途
概念
async/await 是 ES6 引入的异步编程模型旨在简化和改进 Promise 的使用。async 用于声明一个异步函数该函数返回一个 Promise 对象。在异步函数中可以使用 await 关键字来等待其他 Promise 解决。
作用
主要用于更清晰和可读的方式来处理异步操作避免了回调地狱和 Promise 链。async/await 提供了一种类似于同步代码的写法使异步代码更易于理解和维护。
原理
async 函数返回一个 Promise它内部包含了异步操作的执行逻辑。await 关键字用于等待一个 Promise 解决并返回其结果。在 await 后面的代码会等待这个 Promise 完成后再执行。
特性
async/await 语法更直观代码结构更清晰提供了更好的可读性。异步函数内部可以使用 try...catch 来捕获和处理错误提供了更好的错误处理机制。
优点
提供了更直观和易于理解的异步代码结构。支持错误处理可以使用传统的 try...catch 来捕获异步操作中的错误。允许在异步函数中使用同步式的编程风格减少了回调函数和 Promise 链的复杂性。
缺点
async/await 只能在异步函数内部使用不能在全局作用域中使用。相对于传统的回调函数和 Promise需要更多的代码和更多的控制流结构。
区别
async/await 语法更加直观和易于理解与传统的回调函数和 Promise 链相比提供了更好的可读性。与 Promise 不同async/await 支持使用传统的 try...catch 来捕获和处理异常使错误处理更加容易。
使用场景
async/await 适用于几乎所有需要处理异步操作的场景特别是网络请求、文件读取、数据库查询等等。在 Node.js 和浏览器端都广泛使用可以用于简化异步代码的编写提高代码的可维护性。尤其在需要依次执行多个异步操作、处理复杂异步逻辑、提高代码可读性的情况下async/await 是一种非常有用的工具。
总之async/await 是一种用于处理异步操作的现代语法特性提供了更好的代码可读性和错误处理机制适用于几乎所有需要处理异步操作的 JavaScript 项目。
34.和 有什么不同 和 是 JavaScript 中用于比较两个值的运算符它们之间有重要的不同 类型比较 严格相等会比较两个值的类型和值。只有在类型和值都相等的情况下 才返回 true否则返回 false。松散相等会尝试在比较之前进行类型转换然后再比较值。这可能导致一些意外的结果因为它会自动转换数据类型。 类型转换 不进行类型转换严格比较只有在类型和值都相等时才返回 true。 会进行类型转换尝试将两个操作数转换为相同的类型然后再进行比较。例如如果比较一个字符串和一个数字 会尝试将字符串转换为数字然后再比较。 优先使用 通常推荐使用 因为它更严格避免了类型转换可能带来的意外行为。在比较时首先考虑类型是否相同然后再比较值。尽量避免使用 因为它的类型转换规则复杂可能会导致代码不易理解和维护。 示例 5 5 // true类型和值都相等
5 5 // false类型不相等
5 5 // true值相等进行类型转换
5 5 // true值相等进行类型转换
5 5 // true类型和值都相等进行类型转换
0 false // true进行类型转换
总之 是一种更严格的相等比较运算符而 是一种松散的相等比较运算符它们的选择取决于你的需求和代码规范。通常情况下建议优先使用 以避免类型转换带来的问题。
35. async/await 对比 Promise 的优势
async/await 是基于 Promise 的一种更高级、更直观的异步编程模型它相对于直接使用 Promise 具有以下优势
可读性和可维护性 async/await 提供了更直观和类似同步代码的语法使代码更易于理解和维护。不需要嵌套的 .then() 方法链。异步操作的流程更清晰不容易出现回调地狱Callback Hell。 错误处理 在异步函数内部可以使用传统的 try...catch 来捕获和处理异常使错误处理更容易不需要使用 .catch() 方法。通过 try...catch 可以一次性处理整个异步函数中的错误而不需要多个 .catch() 语句。 同步编程风格 async/await 允许在异步函数中使用类似于同步代码的编程风格将异步操作与同步操作更好地结合在一起。这有助于减少深层嵌套和提高代码的可读性。 变量作用域 async/await 不会改变变量作用域使得在异步函数内部可以轻松访问和操作外部变量不需要额外的操作。 更多的控制流结构 async/await 允许使用传统的控制流结构如条件语句、循环语句等来更精确地控制异步操作的执行顺序。 链式调用 虽然 async/await 不直接支持链式调用但可以将多个异步操作按顺序组织在一起形成清晰的代码结构。
总之async/await 提供了更加直观、可读性更高、错误处理更容易的异步编程方式相对于直接使用 Promise它更适合处理异步操作。然而需要注意的是async/await 本质上仍然是基于 Promise 的因此它们并不是互斥的可以在项目中根据需求选择使用哪种方式。通常情况下async/await 更适合处理较为复杂的异步逻辑而 Promise 更适合简单的异步操作。
36. 对象创建的方式有哪些
在 JavaScript 中有多种方式可以创建对象以下是一些常见的对象创建方式 字面量方式 使用对象字面量 {} 创建对象。 示例 const person {name: John,age: 30
}; 构造函数方式 使用构造函数创建对象通常配合 new 操作符。 示例 function Person(name, age) {this.name name;this.age age;
}const person new Person(John, 30); Object.create() 方法 使用 Object.create() 方法创建对象允许指定原型对象。 示例 const personPrototype {greet: function() {console.log(Hello, my name is ${this.name}.);}
};const person Object.create(personPrototype);
person.name John;
person.age 30; 工厂函数方式 使用工厂函数创建对象函数内部返回一个对象字面量。 示例 function createPerson(name, age) {return {name: name,age: age};
}const person createPerson(John, 30); 类ES6方式 使用 class 关键字定义类并通过 new 操作符创建对象。 示例 class Person {constructor(name, age) {this.name name;this.age age;}
}const person new Person(John, 30); 单例模式 创建一个全局唯一的对象实例确保只有一个对象存在。 示例 const singleton (function() {let instance;function createInstance() {const object new Object();return object;}return {getInstance: function() {if (!instance) {instance createInstance();}return instance;}};
})();const obj1 singleton.getInstance();
const obj2 singleton.getInstance();console.log(obj1 obj2); // trueobj1 和 obj2 是同一个对象
这些是常见的对象创建方式根据不同的需求和编码风格你可以选择适合你的方式来创建对象。 ES6 引入的类方式和字面量方式在现代 JavaScript 中被广泛使用。
37. 对象继承的方式有哪些
在 JavaScript 中有多种方式可以实现对象之间的继承。以下是一些常见的对象继承方式 原型链继承 通过将一个对象的原型设置为另一个对象来实现继承。 示例 function Parent() {this.name Parent;
}Parent.prototype.sayHello function() {console.log(Hello, Im ${this.name}.);
};function Child() {}Child.prototype new Parent();const child new Child();
child.sayHello(); // Hello, Im Parent. 构造函数继承借用构造函数 在子类的构造函数内部调用父类的构造函数以继承父类的属性。 示例 function Parent(name) {this.name name;
}function Child(name, age) {Parent.call(this, name); // 借用父类构造函数this.age age;
}const child new Child(John, 30); 组合继承 结合原型链继承和构造函数继承既继承了原型上的方法又继承了构造函数内的属性。 示例 function Parent(name) {this.name name;
}Parent.prototype.sayHello function() {console.log(Hello, Im ${this.name}.);
};function Child(name, age) {Parent.call(this, name); // 借用父类构造函数this.age age;
}Child.prototype new Parent(); // 继承原型上的方法const child new Child(John, 30); 原型式继承 使用一个已有对象作为基础创建一个新对象通过修改新对象的属性来实现继承。 示例 const parent {name: Parent,sayHello: function() {console.log(Hello, Im ${this.name}.);}
};const child Object.create(parent);
child.name Child;
child.sayHello(); // Hello, Im Child. 寄生式继承 在原型式继承的基础上对新对象进行扩展添加额外的属性或方法。 示例 const parent {name: Parent,sayHello: function() {console.log(Hello, Im ${this.name}.);}
};function createChild(name) {const child Object.create(parent);child.name name;return child;
}const child createChild(Child); 寄生组合式继承 结合组合继承和寄生式继承避免了原型链上的属性重复创建。 示例 function Parent(name) {this.name name;
}Parent.prototype.sayHello function() {console.log(Hello, Im ${this.name}.);
};function Child(name, age) {Parent.call(this, name); // 借用父类构造函数this.age age;
}Child.prototype Object.create(Parent.prototype); // 继承父类原型const child new Child(John, 30);
这些是常见的对象继承方式每种方式都有其适用的场景和特点。在选择继承方式时需要根据项目的需求和设计考虑以便选择最合适的方式。在现代 JavaScript 中通常推荐使用类ES6 中引入的来实现面向对象的编程因为它提供了更清晰和强大的语法特性。
38. 哪些情况会导致内存泄漏
内存泄漏是指程序中的某些对象或数据被分配了内存空间但在不再需要时没有被释放导致占用的内存无法被垃圾回收最终可能导致内存耗尽的问题。以下是一些可能导致内存泄漏的情况
未释放的引用 如果一个对象仍然存在对其他对象的引用即使你认为该对象不再需要了它也不会被垃圾回收。这种情况通常发生在闭包、事件监听、全局变量等地方如果不小心持有了不再需要的引用就可能导致内存泄漏。 循环引用 当两个或多个对象互相引用形成了循环引用关系这些对象就不会被垃圾回收。例如一个对象引用了另一个对象的属性而另一个对象又引用了第一个对象这种情况可能会导致内存泄漏。 未关闭的资源 未关闭的文件、数据库连接、网络连接等资源会一直占用内存直到应用程序终止或显式关闭这些资源。如果忘记关闭这些资源就会导致内存泄漏。 定时器和事件监听 定时器例如 setInterval和事件监听器例如 addEventListener可能会在不再需要时仍然存在因此需要及时取消或移除它们。如果忘记取消定时器或移除事件监听器可能会导致内存泄漏。 大量数据的缓存 缓存大量数据尤其是长期不使用的数据可能会导致内存泄漏。需要在适当的时候清理或限制缓存中的数据量。 第三方库和框架问题 使用第三方库或框架时如果其内部存在内存泄漏问题可能会影响整个应用程序。需要谨慎选择和使用第三方工具并关注其更新和维护情况。 循环引用的DOM元素 在JavaScript中DOM元素也可以引发内存泄漏。如果DOM元素之间存在循环引用垃圾回收器无法释放它们。使用事件委托和小心管理DOM元素的引用可以减少这种情况的发生。 Web Workers和其他特殊情况 在Web Workers等特殊环境中内存泄漏问题可能会更加复杂。需要仔细了解和管理这些环境中的内存使用情况。
为了避免内存泄漏开发者应该定期检查代码特别是涉及到长时间运行的应用程序以确保释放不再需要的资源和引用。工具如浏览器的开发者工具和内存分析器也可以帮助检测和解决内存泄漏问题。
39.在 JavaScript 中 0.1 0.2 0.3 吗**?** 请阐述原因并给出解决⽅案
在 JavaScript 中0.1 0.2 并不等于 0.3。这是因为 JavaScript 使用基于 IEEE 754 标准的浮点数表示法来处理数字而浮点数有时会导致精度问题。
具体来说0.1 和 0.2 在二进制浮点表示法中是无限循环的分数因此它们的精确表示是不可能的。当进行浮点数运算时通常会出现微小的舍入误差这就是为什么 0.1 0.2 不等于 0.3 的原因。
为了解决这个问题可以采用以下方法 四舍五入 使用 toFixed() 方法将结果四舍五入到指定的小数位数。 示例 const result (0.1 0.2).toFixed(1); // 0.3 精确计算库 使用第三方的精确计算库如 decimal.js 或 big.js来执行精确的浮点数运算。 示例使用 decimal.js const Decimal require(decimal.js);
const result new Decimal(0.1).plus(0.2); // 0.3 比较时考虑误差范围 当比较两个浮点数是否相等时考虑到浮点数误差可以定义一个误差范围来比较。 示例 const tolerance 1e-10; // 定义一个足够小的误差范围
const result Math.abs(0.1 0.2 - 0.3) tolerance; // true 整数运算 将浮点数转换为整数进行整数运算然后再转换回浮点数。 示例 const result (10 20) / 10; // 3
这些方法中的选择取决于你的需求。如果只是在显示结果时需要精确到小数点后几位使用 toFixed() 是一个简单的解决方案。如果需要在计算中保持高精度可以考虑使用精确计算库。如果只是比较浮点数是否接近可以使用误差范围。
40.Event Loop的概念、作用、原理、特性、优点、缺点、区别、使用场景
Event Loop事件循环 是 JavaScript 中用于处理异步操作的核心机制之一。它是一种事件驱动的执行模型用于管理任务队列和执行任务。以下是关于 Event Loop 的概念、作用、原理、特性、优点、缺点、区别和使用场景的详细解释
概念
Event Loop 是 JavaScript 运行时环境中的一个机制用于处理异步任务和事件。它使得 JavaScript 单线程执行模型下能够处理非阻塞的异步操作同时保持代码执行的顺序。
作用
处理异步操作包括定时器、事件监听、网络请求等。保持单线程JavaScript 是单线程语言Event Loop 保证了单线程下的并发执行。
原理
执行同步任务从调用栈中执行函数。检查消息队列任务队列是否有待处理的任务。如果消息队列有任务将一个任务移出队列并执行。重复步骤1和步骤2直到消息队列为空。
特性
单线程执行JavaScript 是单线程的Event Loop 确保了在单线程下执行异步操作。非阻塞异步任务不会阻塞后续代码的执行。事件驱动基于事件的回调机制响应外部事件和定时器等。微任务和宏任务任务队列分为微任务队列如 Promise 的回调和宏任务队列如 setTimeout、事件监听器的回调微任务优先级高于宏任务。
优点
避免了多线程编程的复杂性。单线程执行使得代码更加简单和可控。事件驱动的非阻塞模型适用于高并发环境。
缺点
单线程执行限制了 CPU 利用率不能充分利用多核处理器。长时间运行的任务会阻塞事件循环导致 UI 响应迟缓。由于单线程某些 CPU 密集型计算可能会影响性能。
区别
进程 vs. 线程 vs. 事件循环 进程是独立的应用程序实例可以包含多个线程。线程是操作系统的执行单元一个进程可以包含多个线程。事件循环是单线程的 JavaScript 运行时环境下处理异步任务的机制。 同步 vs. 异步 同步操作是阻塞的需要等待操作完成。异步操作是非阻塞的可以继续执行其他任务。
使用场景
处理网络请求和服务器响应。处理用户界面事件和交互。处理定时器和延时任务。处理文件读写和数据库操作。
总之Event Loop 是 JavaScript 异步编程的核心它通过非阻塞的方式处理异步操作使得 JavaScript 在单线程下能够处理高并发的情况。了解 Event Loop 的工作原理和特性对于编写高效和响应性的 JavaScript 应用程序至关重要。