HarmonyOS 鸿蒙应用开辟(十一、面向鸿蒙开辟的JavaScript底子)

[复制链接]
发表于 2026-2-22 07:55:17 | 显示全部楼层 |阅读模式
ArkTS 是HarmonyOS(鸿蒙利用体系)原生应用开辟的首选语言。它是用于构建用户界面的一种TypeScript方言,扩展了TypeScript以顺应HarmonyOS生态体系的UI开辟需求。ArkTS 融合了TypeScript的静态范例体系和当代UI框架的筹划理念,为开辟者提供了一种更安全高效的方式来编写HarmonyOS应用。
  目次
前言
TypeScript汗青简介
为什么要有JavaScript底子
TypeScript 和 JavaScript 紧张区别
JavaScript底子知识
1、JavaScript的单线程特性及异步处理惩罚机制
2、当代欣赏器中JavaScript引擎的运作机制
3、JavaScript中的事故循环机制
4、明白 var, let, 和 const 区别
5、JavaScript中有哪些差别的数据范例?
6、什么是回调函数和回调地狱?
7、JavaScript中的Promise及其链式调用
8、怎样明白Async/Await
9、== 与 === 有啥区别
10、有哪些创建JavaScript对象的方法
11、什么是 Rest运算符 和 Spread运算符 ?
12、什么是高阶函数?
其他资源
前言

网络上先容鸿蒙应用TypeScript语言学习的文章已经很多了,但唯独对JavaScript底子先容偏少。这里增补先容一下,以为有资助的小同伴可以点击收藏。
ArkTS 是 TypeScript 的一种扩展版本,而 TypeScript 本身就是 JavaScript 的超集。这意味着 ArkTS 保存了大部分 JavaScript 的语法和编程范式。因此JavaScript 不但是前端开辟的焦点,还在鸿蒙应用中饰演偏紧张脚色。
ArkTS是HarmonyOS优选的主力应用开辟语言。它在TypeScript(简称TS)的底子上,匹配ArkUI框架,扩展了声明式UI、状态管理等相应的本领,让开辟者以更简便、更自然的方式开辟跨端应用。
ArkTS、TypeScript和JavaScript之间的关系:
TypeScript是JavaScript的超集,ArkTS则是TypeScript的超集,他们的关系如下图所示:

相比于JavaScript(JS),ArkTS 和 TypeScript(TS)的紧张区别在于:
1.范例体系:
JavaScript 是一种动态范例语言,变量在运行时可以改变其数据范例。
ArkTS/TypeScript 是JavaScript的超集,是一种静态范例语言,要求在编译阶段就确定变量的范例,这有助于在编码阶段发现埋伏的范例错误,进步代码质量和可维护性。
2.接口和范例注解:
ArkTS/TypeScript 提供了接口、范例注解等特性,允许开辟者明确声明函数参数、对象属性以及组件 Props 的范例,使得IDE和编译器可以大概提供智能提示和范例查抄。
3.面向对象加强:
TypeScript 具有更多的面向对象编程特性,如类、接口、罗列等,这些在ArkTS中同样实用,可以资助开辟者更好地构造大型应用的布局。
4.工具链支持:
ArkTS 针对HarmonyOS平台举行了定制化,提供了相应的编译工具链,将ArkTS代码编译成可以在HarmonyOS上运行的JavaScript代码
TypeScript汗青简介

TypeScript劈头于利用JavaScript开辟的大型项目。由于JavaScript语言本身的范围性,难以胜任和维护大型项目开辟,因此微软开辟了TypeScript,使得其可以大概胜任开辟大型项目。
TypeScript是微软开辟的一个开源的编程语言,通过在JavaScript的底子上添加静态范例界说构建而成。TypeScript通过TypeScript编译器或Babel转译为JavaScript代码,可运行于任何欣赏器,任何利用体系。
2012年10月,微软发布了首个公开版本的TypeScript。2013年6月19日,在履历了一个预览版之后,微软发布了正式版的TypeScript。
TypeScript的作者是安德斯·海尔斯伯格,他也是C#的首席架构师。 TypeScript是一种给JavaScript添加特性的语言扩展,是JavaScript 的一个超集。
详细特性包罗:范例讲明、接口、装饰器、模块、类、泛型等。
为什么要有JavaScript底子

学习鸿蒙ArkTS应用开辟,须要具备JavaScript底子。
缘故起因如下:
1.语法底子:
ArkTS 是 TypeScript 的一种扩展版本,而 TypeScript 本身就是 JavaScript 的超集。这意味着 ArkTS 保存了大部分 JavaScript 的语法和编程范式,比方变量声明、函数界说、流程控制布局等。把握JavaScript的底子语法是明白ArkTS语言特性的条件。
TypeScript 是 JavaScript 的超集,它在 JavaScript 的底子上添加了范例体系、接口、类等更强大的面向对象编程特性。这意味着全部的合法 JavaScript 代码都是合法的 TypeScript 代码,你可以直接将 JavaScript 中的根本语法、控制布局、函数、变量声明、内置对象等知识应用到 TypeScript 中。
假如你已经熟悉 JavaScript,那么明白 TypeScript 中的概念会更容易,由于很多高级特性是基于 JavaScript 原有的功能扩展而来。同时,当你从 JavaScript 迁移到 TypeScript 时,相识它们之间的共通点可以资助你快速顺应 TypeScript 的开辟模式。
2.运行机制:
固然ArkTS在编译阶段举行了范例查抄和转换,但它终极会被编译成可以大概在HarmonyOS平台上运行的JavaScript代码。因此,明白JavaScript的运行机制有助于开辟者更好地调试和优化ArkTS应用步伐。
3.异步编程与事故处理惩罚:
JavaScript 在前端开辟中广泛用于实现异步编程模子和事故驱动编程,这些概念和技能同样实用于ArkTS开辟情况中的UI渲染和用户交互处理惩罚。
4.类库和生态兼容性:
鸿蒙ArkTS固然针对鸿蒙体系举行了特定优化,但依然保持了对现有JavaScript生态体系的兼容性。很多现有的JavaScript工具、框架、API筹划思绪都可以迁移到ArkTS开辟过程中。
5.渐进式加强:
开辟者可以利用已有的JavaScript知识,在原有项目标底子上渐渐引入TypeScript(包罗ArkTS)的特性,举行更加安全和高效的开辟。
由于ArkTS基于JavaScript并对其举行加强以顺应鸿蒙利用体系的要求,以是拥有踏实的JavaScript底子知识对于快速把握ArkTS开辟本领至关紧张。
TypeScript 和 JavaScript 紧张区别

范例体系:
TypeScript 引入了静态范例体系,允许开辟者在编译阶段就查抄变量的数据范例,这有助于提前发现埋伏的范例错误,而且通过IDE智能提示和主动补全进步编码服从。而 JavaScript 是动态范例的语言,变量范例可以在运行时改变。
工具支持:
TypeScript 提供了丰富的编译器工具,可以举行范例查抄、转换以及一些其他代码优化利用,产出可被欣赏器辨认的纯 JavaScript 代码。
面向对象加强:
TypeScript 支持更多的面向对象编程特性,如接口、泛型、罗列、类成员修饰符等,这些在 JavaScript ES6 及更高版本中虽有所实现,但在 TypeScript 中更加全面和严酷。
工程化本领:
TypeScript 更适当构建大型、复杂的应用步伐,其提供的模块体系、定名空间等功能加强了代码构造本领和团队协作服从。
总结来说,固然 TypeScript 在很多方面加强了 JavaScript 的本领,但其焦点仍旧是创建在 JavaScript 之上的。因此,具备踏实的 JavaScript 底子对于学习和利用 TypeScript 非常紧张。
JavaScript底子知识

1、JavaScript的单线程特性及异步处理惩罚机制

JavaScript确实是一种单线程编程语言。这意味着它只有一个调用栈和一个内存堆。在任何时间,只能实验一组指令。
同步和壅闭的本质
JavaScript本质上是同步和壅闭的。这意味着代码会按行实验,一个任务必须完成后才气开始下一个任务。这种特性在处理惩罚复杂或耗时的利用时大概导致用户界面的相应迟钝或冻结。
JavaScript的异步本领
只管JavaScript是单线程的,但它也具有异步处理惩罚本领。这允许某些利用独立于主实验线程举行。这通常通过回调函数、Promise、async/await和事故监听器等机制实现。这些异步特性使JavaScript可以大概处理惩罚诸如数据获取、用户输入处理惩罚和I/O利用等任务,而不会壅闭主线程。这对于构建相应性强和交互性强的Web应用步伐非常紧张。
回调函数
回调函数是异步编程中最根本的方法。它是在某个任务完成后才被调用的函数。比方:
  1. // 异步操作:读取文件
  2. fs.readFile('example.txt', 'utf-8', function(err, data) {
  3.     if (err) {
  4.         throw err;
  5.     }
  6.     console.log(data); // 文件读取完成后输出内容
  7. });
复制代码
Promise
Promise是处理惩罚异步利用的一种更优雅的方式。
  1. // 创建一个Promise
  2. let promise = new Promise(function(resolve, reject) {
  3.     // 异步操作
  4.     setTimeout(function() {
  5.         resolve('操作成功完成');
  6.     }, 1000);
  7. });
  8. // 使用Promise
  9. promise.then(function(value) {
  10.     console.log(value); // 1秒后输出“操作成功完成”
  11. });
复制代码
async/await
async/await是基于Promise的一种更简便的异步处理惩罚方式。它让异步代码看起来更像同步代码。
  1. // 定义一个异步函数
  2. async function fetchData() {
  3.     let response = await fetch('https://api.example.com/data');
  4.     let data = await response.json();
  5.     return data;
  6. }
  7. // 调用异步函数
  8. fetchData().then(data => console.log(data));
复制代码
JavaScript固然是单线程且同步的,但其强大的异步处理惩罚本领使其成为构建当代Web应用的理想选择。通过明白和公道运用JavaScript的异步机制,我们可以打造出既高效又用户友爱的应用步伐。
2、当代欣赏器中JavaScript引擎的运作机制


在探索网页和网络应用的天下时,JavaScript引擎饰演着不可或缺的脚色。
当你在欣赏器中输入一个网址,背后着实发生了连续串复杂的过程。这此中,JavaScript代码从输入到实验,履历了以下几个阶段:

  • 分析阶段(Parser): 欣赏器起首将JavaScript代码读入,并转换成一个称为“抽象语法树(AST)”的布局,这个过程就像是将句子分解成词汇和语法布局。
  • 表明实验(Interpreter): 有了AST,表明器开始工作,将其转换成盘算性能明白的字节码。这个过程有点像翻译工作,将一种语言转换为另一种。
  • 性能分析(Profiler): 在代码实验的同时,性能分析器监督着哪些部分被频仍利用,以便举行优化。
  • 优化编译(Optimizing Compiler): 通过“即时编译(JIT)”技能,根据分析数据对代码举行优化,使其运行更快。
  • 去优化(Deoptimization): 假如优化假设错误,体系将取消该优化,返回到未优化的状态,固然这会造成肯定的性能消耗,但可以确保代码精确实验。
  • 热函数和内联缓存: 引擎会对“热函数”即频仍实验的函数举行优化,并利用内联缓存技能来提拔性能。
  • 内存管理: 调用栈负责跟踪当前实验的函数,而内存堆用于分配内存。末了,垃圾接纳器负责整理不再利用的对象,开释内存空间。
谷歌Chrome的V8引擎
在谷歌Chrome欣赏器中,它利用的JavaScript引擎名为V8,具有一些特殊的组件:


  • “Ignition”:表明器的名字。
  • “TurboFan”:优化编译器的名字。
  • 在分析器之外,另有一个“预分析器”,用于查抄语法和符号。
  • 引入了“Sparkplug”,位于“Ignition”和“TurboFan”之间,它是一个快速编译器,可以加快代码实验。
通过这些组件的协同工作,V8可以大概在欣赏器中快速、高效地实验JavaScript代码。
JavaScript引擎的运作是当代网络体验的焦点。它确保了我们欣赏的网页不但仅是静态的文档,而是布满了互动性和动态内容的生动天下。在这个过程中,从分析器到优化编译器的每一个环节都至关紧张。它们相助确保了代码不但可以大概被实验,而且能以最优化的方式实验,使得用户体验流通且高效。无论是初学者照旧资深开辟者,明白这些过程都是把握前端技能的紧张一环。
3、JavaScript中的事故循环机制

事故循环(Event Loop)是JavaScript运行时情况中的焦点组件。在先容这个概念之前,我们须要相识JavaScript是单线程实验的,这意味着它一次只能实验一个任务。然而,这并不意味着它不能实验异步利用——这正是事故循环发挥作用的地方。
一、事故循环的脚色
事故循环的紧张职责是监控监控调用栈和队列,并安排异步任务的实验。它确保主线程上的代码实验流通,同时也能处理惩罚那些须要一些时间才气完成的任务。
二、事故循环的工作流程
事故循环的工作流程可以分为以下几个步调:

  • 调用栈(Call Stack): 这是一个后进先出(LIFO)的数据布局,用来存储当前正在实验的函数。一旦一个函数实验完成,它就会被从栈中弹出。
  • Web API: 当实验到异步利用(如setTimeout、fetch哀求、Promise)时,这些利用会被移至Web API情况中,而且在那里等候利用完成。完成后,回调函数会被推入任务队列中,等候实验。
  • 任务队列(Task Queue/Macrotasks): 这是一个先辈先出(FIFO)的布局,用来存储预备好实验的回调函数,好比setTimeout和setInterval的回调。
  • 微任务队列(Job Queue/Microtasks): 与任务队列雷同,这也是一个FIFO布局,但它专门用于处理惩罚如Promise的resolve或reject回调、async/await等微任务。
  • 事故循环(Event Loop): 当调用栈为空时,事故循环会起首查抄微任务队列。假如微任务队列中有任务,它会优先实验这些任务。只有当微任务队列为空时,事故循环才会查抄任务队列。任务队列中的任务会一个接一个地被实验,但在每个宏任务之间,事故循环都会再次查抄微任务队列,以确保新的微任务可以被及时处理惩罚。
三、实验序次的紧张性
在JavaScript中,微任务总是优先于宏任务实验。这意味着Promise的回调会在setTimeout的回调之前实验。明白这一点对于编写高效且无错误的异步代码至关紧张。
四、示例
想象下面的情况:
  1. console.log('1');
  2. setTimeout(function() {
  3.     console.log('2');
  4. }, 0);
  5. Promise.resolve().then(function() {
  6.     console.log('3');
  7. });
  8. console.log('4');
复制代码
输出的序次会是:
  1. 1
  2. 4
  3. 3
  4. 2
复制代码
这是由于纵然setTimeout的耽误时间设置为0,它的回调也会被放入任务队列中,而`Promise.then` 的回调则会被放入微任务队列中,而且微任务队列的实验总是在当前宏任务(包罗调用栈中全部的同步任务)实验完毕后,下一个宏任务开始之前。
事故循环机制是明白JavaScript异步编程的焦点。它不但确保了同步代码的顺遂实验,还管理着异步利用的调治,这使得JavaScript可以大概处理惩罚复杂的场景,如用户交互、脚本加载、网络哀求等,而不会造成界面的冻结。
把握事故循环的工作原理,对于编写高性能的JavaScript代码是至关紧张的。这不但能资助你制止常见的陷阱,好比“壅闭主线程”的标题,还能让你更好地利用JavaScript的异步特性,编写出相应敏捷、用户体验精良的网页应用。
4、明白 var, let, 和 const 区别


1. var
作用域: var声明的变量拥有函数作用域,假如在函数外部声明,它将具有全局作用域。在全局作用域下利用var声明的变量会被附加到window对象上。


  • 变量提拔: var声明的变量会发生变量提拔(hoisting),意味着无论在函数的哪个部分声明,它们都会被移动到函数的顶部。
  • 重复声明: 利用var可以重复声明同一个变量。
  • 重新赋值: 利用var声明的变量可以被重新赋值。
2. let


  • 作用域: let声明的变量具有块级作用域(block scope),仅在声明它的代码块内有用。
  • 变量提拔: let声明的变量也会提拔,但它们不会被初始化。在代码实验到声明之前,它们是不可访问的,这个区间被称为“临时性死区”(Temporal Dead Zone, TDZ)。
  • 重复声明: 在同一个作用域中,let不允许重新声明已经存在的变量。
  • 重新赋值: 利用let声明的变量可以被重新赋值,但不能重复声明。
3. const


  • 作用域: 与let雷同,const声明的变量也具有块级作用域。
  • 变量提拔: const同样会提拔到块的顶部,但是在声明语句之前它们也是不可访问的,存在于“临时性死区”中。
  • 重复声明: const不允许在雷同作用域内重复声明变量。
  • 重新赋值: const声明的变量不能被重新赋值,它们必须在声明时初始化,而且声明后值是固定的。但是,假如const变量指向的是一个对象或数组,那么对象或数组的内容是可以被修改的。
附加在window对象上
在欣赏器情况中,全局作用域下利用var声明的变量会成为window对象的属性。这意味着,假如你声明白var dog = 'bowser',现实上你添加了一个新的全局变量dog到window对象上,你可以通过window.dog访问到它,而且会得到'bowser'这个值。
相比之下,let和const声明的变量则不会被添加到window对象。这有助于制止全局定名空间的污染,也让变量的控制范围更加严酷。
5、JavaScript中有哪些差别的数据范例?



JavaScript中的数据范例紧张分为两大类:原始数据范例(Primitive Data Types)和引用数据范例(Reference Data Types)。每种范例有其特定的特性和用途,明白它们对于编写高质量的代码至关紧张。
原始数据范例
原始数据范例是底子的数据范例,直接存储值,它们是不可变的。JavaScript提供了以下几种原始数据范例:

  • 数值(Numbers):用于体现整数和浮点数。比方:42、3.14。
  • 字符串(Strings):由字符构成,用单引号、双引号或模板字面量困绕。比方:'hello'、"world"、`hello world`。
  • 布尔值(Booleans):只有两个值true和false,用于逻辑判定。
  • 空值(Null):体现一个明确的空值。
  • 未界说(Undefined):变量已声明但未初始化时的状态。
  • 符号(Symbols):ES6中新增,每个符号值都是唯一稳定的,常用尴尬刁难象属性的键。
引用数据范例
引用数据范例可以包罗多个值或复杂的实体,它们存储的是对数据的引用,而非数据本身。在JavaScript中,引用数据范例紧张包罗:

  • 对象(Objects):键值对的聚集,值可以是任何范例,包罗其他对象或函数。
  • 数组(Arrays):有序的数据聚集,数组中的每个元素都可以是差别的数据范例。
特殊的原始数据范例
在很多讨论中,null和undefined通常被特殊对待,偶然被视为特殊的原始范例:


  • Null:在逻辑上体现“无值”,通常用来体现一个变量应该有值,但不是任何其他数据范例。
  • Undefined:体现变量已声明,但尚未赋值。
Symbol的独特性


  • 唯一性:每个Symbol的值都是全局
唯一的,即便创建多个雷同形貌的Symbol,它们也代表差别的值。


  • 利用场景:紧张用于对象属性名,以包管属性名的唯一性,防止属性名的辩说。
  • 属性潜伏:Symbol作为属性键的对象属性不会出现在传统的遍历中,如for...in循环。
新增原始数据范例


  • BigInt:ES2020中新增的原始数据范例,用于体现大于2^53 - 1的整数。
数据范例的选择
选择适当的数据范例对于性能和内存管理至关紧张。原始范例通常占用较少内存,而且它们的利用速率更快。引用范例则允许构建更复杂的数据布局,但须要更多的内存,而且在处理惩罚时大概会更慢。
数据范例转换
JavaScript是一种动态范例语言,这意味着变量的数据范例不是固定的。在运算过程中,变量的数据范例大概会主动转换,这称为范例转换(Type Coercion)。
6、什么是回调函数和回调地狱?

在JavaScript中,回调函数是异步利用中常用的概念。一个回调函数是通报给另一个函数的函数,通常在特定任务完成后或在预定时间实验。
回调函数的例子
  1. function fetchData(url, callback) {
  2.   // 模拟从服务器获取数据
  3.   setTimeout(() => {
  4.     const data = 'Some data from the server';
  5.     callback(data);
  6.   }, 1000);
  7. }
  8. function processData(data) {
  9.   console.log('Processing data:', data);
  10. }
  11. fetchData('https://example.com/data', processData);
复制代码
在这个例子中,fetchData函数继承一个URL和一个回调函数作为参数。在模拟获取服务器数据之后(利用setTimeout),它调用回调函数并通报检索到的数据。
回调地狱(Callback Hell)
回调地狱,也称为“厄运金字塔”(Pyramid of Doom),是JavaScript编程中用来形貌多个嵌套回调函数在异步函数中利用的情况。
回调地狱的例子:
  1.  fs.readFile('file1.txt', 'utf8', function (err, data) {
  2.   if (err) {
  3.     console.error(err);
  4.   } else {
  5.     fs.readFile('file2.txt', 'utf8', function (err, data) {
  6.       if (err) {
  7.         console.error(err);
  8.       } else {
  9.         fs.readFile('file3.txt', 'utf8', function (err, data) {
  10.           if (err) {
  11.             console.error(err);
  12.           } else {
  13.             // 继续更多的嵌套回调...
  14.           }
  15.         });
  16.       }
  17.     });
  18.   }
  19. });
复制代码
在这个例子中,我们利用`
fs.readFile`函数序次读取三个文件,每个文件读取利用都是异步的。效果是,我们不得不将回调函数嵌套在相互之内,创建了一个回调函数的金字塔布局。
制止回调地狱
为了制止回调地狱,当代JavaScript提供了如Promise和async/await等替换方案。下面是利用Promise重写上述代码的例子:
  1. const readFile = (file) => {
  2.   return new Promise((resolve, reject) => {
  3.     fs.readFile(file, 'utf8', (err, data) => {
  4.       if (err) {
  5.         reject(err);
  6.       } else {
  7.         resolve(data);
  8.       }
  9.     });
  10.   });
  11. };
  12. readFile('file1.txt')
  13.   .then((data1) => {
  14.     console.log('Read file1.txt successfully');
  15.     return readFile('file2.txt');
  16.   })
  17.   .then((data2) => {
  18.     console.log('Read file2.txt successfully');
  19.     return readFile('file3.txt');
  20.   })
  21.   .then((data3) => {
  22.     console.log('Read file3.txt successfully');
  23.     // 继续使用基于Promise的代码...
  24.   })
  25.   .catch((err) => {
  26.     console.error(err);
  27.   });
复制代码
在这个改进后的例子中,我们通过链式调用.then()方法来序次处理惩罚异步读取文件的利用,并通过.catch()方法捕捉任何大概发生的错误。如许的代码布局更加清楚,也更容易明白和维护。
7、JavaScript中的Promise及其链式调用

Promise简介
在JavaScript异步编程中,Promise是一个非常关键的概念。它代表了一个异步利用的终极完成(或失败)及其效果值。
Promise的状态
一个Promise对象有以下三种状态:

  • Pending(等候):这是Promise的初始状态,意味着异步利用尚未完成。
  • Fulfilled(已办理):当异步利用乐成完成,Promise被办理,而且有一个可用的终极效果值时的状态。
  • Rejected(已拒绝):当异步利用失败或Promise被拒绝,没有可用的效果值时的状态。
Promise构造器
Promise构造器继承一个实验器函数作为参数,这个函数有两个参数:resolve和reject,它们都是函数。


  • resolve:当异步利用乐成时,将调用此函数,并通报效果值。
  • reject:当异步利用失败时,将调用此函数,并通报错误或拒绝的缘故起因。
利用Promise
我们可以通过.then()方法来访问Promise的效果,通过.catch()方法来捕捉大概出现的错误。
  1. // 创建一个Promise
  2. const fetchData = new Promise((resolve, reject) => {
  3.   // 模拟从服务器获取数据
  4.   setTimeout(() => {
  5.     const data = 'Some data from the server';
  6.     // 使用获取的数据解决Promise
  7.     resolve(data);
  8.     // 也可以用一个错误拒绝Promise
  9.     // reject(new Error('Failed to fetch data'));
  10.   }, 1000);
  11. });
  12. // 消费Promise
  13. fetchData
  14.   .then((data) => {
  15.     console.log('Data fetched:', data);
  16.   })
  17.   .catch((error) => {
  18.     console.error('Error fetching data:', error);
  19.   });
复制代码
Promise链式调用
当我们须要按序次实验一系列异步任务时,可以利用Promise链式调用。这涉及到将多个.then()方法链接到一个Promise上,以便按特定序次实验一系列任务。
  1. new Promise(function (resolve, reject) {
  2.   setTimeout(() => resolve(1), 1000);
  3. })
  4.   .then(function (result) {
  5.     console.log(result); // 1
  6.     return result * 2;
  7.   })
  8.   .then(function (result) {
  9.     console.log(result); // 2
  10.     return result * 3;
  11.   })
  12.   .then(function (result) {
  13.     console.log(result); // 6
  14.     return result * 4;
  15.   });
复制代码
在这个链式调用中,每个`.then()`处理惩罚函数都会序次实验,并将其效果通报给下一个`.then()`。假如任何一个`.then()`中发生非常或返回一个拒绝的`Promise`,链式调用将会制止,并跳到近来的`.catch()`处理惩罚步伐。
链式调用的上风:利用Promise链式调用的上风在于可以大概提供清楚的异步代码布局,相比传统的回调函数(callback hell),它可以大概更加直观地表达异步利用之间的依靠关系,而且可以大概更简单地处理惩罚错误。
8、怎样明白Async/Await

Async/Await 的本质
async/await 是一种编写异步代码的新方式,它创建在Promise之上,但提供了一种更直观和更符条约步编程模式的语法。async/await 使得异步代码的编写、阅读和调试变得和同步代码一样简单。
利用 Async/Await


  • async 关键字:用于声明一个异步函数,这个函数会隐式地返回一个Promise对象。
  • await 关键字:只能在async函数中利用,它会停息async函数的实验,等候Promise办理(或拒绝),然后继续实验async函数并返回办理的效果。
  1. // 声明一个 async 函数
  2. async function fetchData() {
  3.   try {
  4.     // 等待fetch请求完成,并获取响应
  5.     const response = await fetch('https://example.com/data');
  6.     // 等待将响应解析为JSON,并获取数据
  7.     const data = await response.json();
  8.     // 返回获取到的数据
  9.     return data;
  10.   } catch (error) {
  11.     // 如果有错误,抛出异常
  12.     throw error;
  13.   }
  14. }
  15. // 使用 async 函数
  16. fetchData()
  17.   .then((jsonData) => {
  18. // 处理获取到的数据
  19. console.log(jsonData);
  20. })
  21. .catch((error) => {
  22. // 处理错误
  23. console.error("An error occurred:", error);
  24. });
复制代码
在上面的例子中,`fetchData` 函数被声明为 `async` 函数,它利用了 `await` 关键字来停息函数的实验,并等候 `fetch` 哀求和 `.json()` 方法的 Promise 办理。如许做可以使我们像编写同步代码一样处理惩罚异步利用。 #### 错误处理惩罚 在 `async` 函数中,可以利用 `try...catch` 布局来捕捉并处理惩罚函数实验过程中的错误。这与同步代码中利用 `try...catch` 的方式雷同。
Async/Await 的优点
可读性:代码更直观,看起来就像是同步代码。
错误处理惩罚:传统的 `.then().catch()` 可以大概处理惩罚错误,但 `async/await` 允许利用更熟悉的 `try...catch` 语法。
制止回调地狱:`async/await` 让代码制止了深条理的嵌套。
留意事项
只管 `async/await` 提供了很多便利,但是它不会改变JavaScript事故循环的工作方式。`await` 关键字会导致 `async` 函数的实验停息,但不会壅闭其他代码的实验,由于在底层,它们照旧基于非壅闭的Promises工作。
9、== 与 === 有啥区别

在JavaScript中,==(宽松相当)和===(严酷相当)是用于比力两个值的运算符,但它们在比力时的运动和效果大概会非常差别。
宽松相当 ==


  • 范例转换:在比力前,==会将利用数转换为雷同的范例。这个过程被称为范例逼迫转换(type coercion)。
  • 值比力:只要利用数的值相当,即返回true。
  • 比力例子:0 == false 返回 true,由于 0 被逼迫转换为 false。1 == "1" 返回 true,由于字符串 "1" 被逼迫转换为数字 1。null == undefined 返回 true,这是语言规范中界说的特殊情况。
严酷相当 ===


  • 无范例转换:===在比力时不会举行范例转换,假如利用数的范例差别,则直接返回false。
  • 值和范例比力:利用数必须在值和范例上都相当,才返回true。
  • 比力例子:0 === false 返回 false,由于它们的范例差别:一个是 number,另一个是 boolean。1 === "1" 返回 false,只管它们的值相似,但范例差别。null === undefined 返回 false,由于 null 和 undefined 是差别的范例。
实验速率


  • 实验速率:通常以为 === 会比 == 快,由于 === 不须要举行额外的范例转换。但在当代JavaScript引擎中,这种差别通常可以忽略不计。
对象的比力


  • 对象内存引用:无论是 == 照旧 ===,对象比力时都是基于它们是否引用同一个内存地点,而不是基于它们的布局或内容。[] == [] 或 `[]=== []返回false`,每个空数组都是一个差别的对象实例,它们在内存中有差别的引用。
  • {} == {} 或 {} === {} 也返回 false,缘故起因同上。
  1. 0 == false   // true
  2. 0 === false  // false
  3. 1 == "1"     // true
  4. 1 === "1"    // false
  5. null == undefined // true
  6. null === undefined // false
  7. '0' == false // true
  8. '0' === false // false
  9. []==[] or []===[] //false, refer different objects in memory
  10. {}=={} or {}==={} //false, refer different objects in memory
复制代码
在JavaScript编程中,保举利用 === 来举行比力,由于它可以制止因范例转换导致的不测效果,使代码的逻辑更加清楚和可推测。在须要明确思量范例的场景下,利用 === 是最佳实践。当你确实须要范例逼迫转换时,才利用 ==,但这通常应当只管制止。
10、有哪些创建JavaScript对象的方法

在JavaScript中创建对象有多种方法,每种方法都实用于差别的场景:
a) 对象字面量
这是创建对象最直接的方式,通过在花括号中直接界说属性和方法。
  1. let person = {
  2.     firstName: 'John',
  3.     lastName: 'Doe',
  4.     greet: function() {
  5.         return 'Hello, ' + this.firstName + ' ' + this.lastName;
  6.     }
  7. };
复制代码
b) 构造函数
利用构造函数创建对象允许你实例化多个对象。利用new关键字调用构造函数。
  1. function Person(firstName, lastName) {
  2.     this.firstName = firstName;
  3.     this.lastName = lastName;
  4.     this.greet = function() {
  5.         return 'Hello, ' + this.firstName + ' ' + this.lastName;
  6.     };
  7. }
  8. let person1 = new Person('John', 'Doe');
  9. let person2 = new Person('Jane', 'Smith');
复制代码
c) Object.create()
Object.create()方法允许你指定一个原型对象来创建一个新对象。
  1. let personProto = {
  2.        greet: function() {
  3.            return 'Hello, ' + this.firstName + ' ' + this.lastName;
  4.        }
  5.    };
  6.    let person = Object.create(personProto);
  7.    person.firstName = 'John';
  8.    person.lastName = 'Doe';
复制代码
d) 类语法(ES6)
ES6引入了类的概念,利用`class`关键字来界说对象的构造函数和方法。
  1. class Person {
  2.        constructor(firstName, lastName) {
  3.            this.firstName = firstName;
  4.            this.lastName = lastName;
  5.        }
  6.        greet() {
  7.            return 'Hello, ' + this.firstName + ' ' + this.lastName;
  8.        }
  9.    }
  10.    let person = new Person('John', 'Doe');
复制代码
e) 工厂函数
工厂函数是返回一个对象的函数。这种方法允许您封装对象的创建过程,并轻松创建具有自界说属性的多个实例。
  1. function createPerson(firstName, lastName) {
  2.     return {
  3.         firstName: firstName,
  4.         lastName: lastName,
  5.         greet: function() {
  6.             return 'Hello, ' + this.firstName + ' ' + this.lastName;
  7.         }
  8.     };
  9. }
  10. let person1 = createPerson('John', 'Doe');
  11. let person2 = createPerson('Jane', 'Smith');
复制代码
f) Object.setPrototypeOf()
Object.setPrototypeOf()方法用于在对象创建后设置其原型。
  1. let personProto = {
  2.     greet: function() {
  3.         return 'Hello, ' + this.firstName + ' ' + this.lastName;
  4.     }
  5. };
  6. let person = { firstName: 'John', lastName: 'Doe' };
  7. Object.setPrototypeOf(person, personProto);
复制代码
g) Object.assign()
Object.assign()方法用于将一个或多个源对象的可罗列属性复制到目标对象,常用于对象的归并或创建浅副本。
  1. let target = { a: 1, b: 2 };
  2. let source = { b: 3, c: 4 };
  3. let mergedObject = Object.assign({}, target, source);
复制代码
h) 原型继续
JavaScript接纳原型继续模式,可以通过设置原型链来使对象继续其他对象的属性和方法。
  1. function Animal(name) {
  2.     this.name = name;
  3. }
  4. Animal.prototype.greet = function() {
  5.     return 'Hello, I am ' + this.name;
  6. };
  7. function Dog(name, breed) {
  8.     Animal.call(this, name); // 继承属性
  9.     this.breed = breed;
  10. }
  11. Dog.prototype = Object.create(Animal.prototype);
  12. Dog.prototype.constructor = Dog;
  13. let myDog = new Dog('Max', 'Poodle');
复制代码
i) 单例模式
单例模式用于创建一个类的唯一实例,通过闭包和自实验函数实现。
  1. let singleton = (() => {
  2.     let instance;
  3.     function createInstance() {
  4.         return {
  5.             // 属性和方法
  6.         };
  7.     }
  8.     return {
  9.         getInstance: () => {
  10.             if (!instance) {
  11.                 instance = createInstance();
  12.             }
  13.             return instance;
  14.         }
  15.     };
  16. })();
复制代码
11、什么是 Rest运算符 和 Spread运算符 ?

Rest运算符
Rest运算符(...)使得函数可以大概继承不定命量的参数作为数组。这种方式允许我们在调用函数时通报恣意数目的参数,而不须要事先界说具名参数。
Rest运算符的例子
  1. function sum(...numbers) {
  2.     return numbers.reduce((total, num) => total + num, 0);
  3. }
  4. console.log(sum(1, 2, 3, 4)); // 输出 10
复制代码
在这个例子中,sum函数利用Rest运算符...numbers来网络全部传入的参数,并将它们作为数组处理惩罚。然后利用reduce方法来盘算全部参数的总和。
Spread运算符
Spread运算符同样由三个点(...)体现,它用于将数组或对象的元素睁开到另一个数组或对象中。Spread运算符可以轻松实现数组的克隆、数组的归并以及对象的归并。
Spread运算符的例子
  1. // 数组合并
  2. const array1 = [1, 2, 3];
  3. const array2 = [4, 5, 6];
  4. const mergedArray = [...array1, ...array2];
  5. // mergedArray 现在是 [1, 2, 3, 4, 5, 6]
  6. // 对象合并
  7. const obj1 = { a: 1, b: 2 };
  8. const obj2 = { b: 3, c: 4 };
  9. const mergedObject = { ...obj1, ...obj2 };
  10. // mergedObject 现在是 { a: 1, b: 3, c: 4 }
复制代码
在归并对象的例子中,`obj2`的属性会覆盖`obj1`中的同名属性。在这里,`b: 2` 被 `b: 3` 所覆盖。
Rest运算符和Spread运算符固然利用雷同的符号(...),但用途完全相反:
Rest运算符:用于将通报给函数的多个参数组合成一个数组。
Spread运算符:用于将一个数组或对象的全部元素/属性睁开到另一个数组或对象中。
这两个运算符极大地加强了JavaScript在处理惩罚数组和对象时的机动性,简化了很多原来须要通过循环或库函数来实现的利用。
12、什么是高阶函数?

在JavaScript中,高阶函数(Higher-order function)是指可以汲取函数作为参数或将函数作为返回值的函数。简而言之,它可以对函数举行利用,包罗将函数作为参数汲取,返回一个函数,大概两者都有。
高阶函数的例子
  1. // 这个高阶函数接收一个数组和一个操作函数作为参数
  2. function operationOnArray(arr, operation) {
  3.   let result = [];
  4.   for (let element of arr) {
  5.     result.push(operation(element));
  6.   }
  7.   return result;
  8. }
  9. // 这是一个简单的函数,将会被用作高阶函数的参数
  10. function double(x) {
  11.   return x * 2;
  12. }
  13. // 使用高阶函数
  14. let numbers = [1, 2, 3, 4];
  15. let doubledNumbers = operationOnArray(numbers, double);
  16. console.log(doubledNumbers); // 输出: [2, 4, 6, 8]
复制代码
在这个例子中,operationOnArray 是一个高阶函数,它继承一个数组和一个函数 double 作为参数。double 函数将传入的每个元素翻倍,并将效果返回给 operationOnArray 函数,后者利用这个效果来构造一个新数组。
高阶函数的应用
高阶函数在JavaScript中有很多应用,好比:


  • 数组方法:map, filter, reduce 等数组方法都是高阶函数的例子,它们汲取一个函数作为参数。
  • 函数组合:可以将多个函数组合成一个新的函数。
  • 柯里化:一个函数汲取少于其声明的参数数目,返回一个汲取剩余参数的新函数。
  • 异步利用:好比setTimeout或addEventListener,这些函数汲取一个将在未来某个时间实验的回调函数。
一元函数(单参数函数)
一元函数是只继承一个参数的函数。在函数式编程中,一元函数因其简单性而受到青睐,由于它们易于链式调用和组合。
高阶函数与一元函数的关系
高阶函数可以返回一元函数,大概汲取一元函数作为参数,这使得在函数式编程中,高阶函数和一元函数常常一起利用,以创建简便且模块化的代码。
写在末了



  • 假如你以为这篇内容对你还蛮有资助,我想约请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和品评』,才是我创造的动力。
  • 关注博主,同时可以等候后续文章ing🚀,不定期分享原创知识。

其他资源

harmonyOS鸿蒙官网教程-TypeScript入门语言_鸿蒙 typescript-CSDN博客
鸿蒙Harmony学习(三)TypeScript语言学习
HarmonyOS开辟预备 TypeScript 根本语法-CSDN博客
鸿蒙4.0开辟教程1——TypeScript底子语法_鸿蒙 typescript打开pdf文件-CSDN博客
https://www.toutiao.com/article/7309099399228047911
鸿蒙HarmonyOS教程-TypeScript语言简介【入门篇】-CSDN博客
https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/quick-start/typescript-to-arkts-migration-guide.md
TypeScript 快速学习 ArkTs是Ts(TypeScript)的扩展_arkts有须要学吗-CSDN博客



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表