文将为您提供对如何迭代JavaScript中的Array数据结构的扎实理解。无论您是刚刚开始学习JavaScript还是在这里学习复习,任何一种方式都将为您带来价值。本文将引导您完成使用最广泛的JavaScript概念之一。
上面是一个用于存储多个值的JavaScript数组。这是数组的最简单形式之一。它在数组内部包含4个“元素”,所有字符串。如您所见,每个元素都用逗号分隔。此示例数组包含不同品牌的汽车,并且可以用cars变量引用。
我们可以通过多种方法来迭代此数组。JavaScript具有令人难以置信的丰富功能,因此我们可以选择最佳的方法来解决问题。
这是解决JavaScript中数组迭代的方法:
1、重点介绍5种遍历数组的常用方法
2、对每种迭代方法显示一些见解
3、提供一些代码,您也可以使用它进行测试!
什么是For循环?维基百科将For循环定义为:
“在计算机科学中,for循环(或简称为for循环)是用于指定迭代的控制流 语句,该语句允许重复执行代码。”for循环是一种重复执行代码的方法。console.log(“hi”)您可以将其包装在for循环中,而不必键入5次。在第一个示例中,我们将学习如何遍历上面看到的cars数组,并打印出每个元素。迭代器或计数器将在第一个索引“ Tesla”处开始,并在最后一个“ Audi”处结束。它遍历数组并一次打印一个元素。
输出:
深入研究代码,我们将三个选项传递给for循环
1、迭代器变量- let i = 0;
2、迭代器应在何处停止- i < card.length
3、每个循环增加多少迭代器- i++
此循环从开始于0,每个循环将变量增加一个,并在我们击中数组中的最后一个元素时停止。传统的for循环的主要好处是您拥有更多的控制权。可以访问数组中的不同元素,或者以复杂的方式遍历数组以解决复杂的问题。例如,使用传统的for循环可以很容易地跳过数组中的所有其他元素。
什么是forEach方法?该forEach方法用于为数组的每个元素执行一个函数。如果数组的长度是“未知”或保证会改变,则此方法是一个不错的选择。此方法只能与数组,集合和映射一起使用。
forEach循环的最大好处是即使数组的大小可能会增加,也能够访问每个项目。它是适用于许多用例的可扩展解决方案,比传统的for循环更易于阅读和理解,因为我们知道我们将对每个元素进行精确的迭代一次。
什么是While循环?维基百科将While循环定义为:“ while循环是一个控制流 语句,它允许根据给定的布尔条件重复执行代码。在同时循环可以被认为是一个重复的if语句。”一while环是,如果一个条件是真还是假反复执行代码来检查的方式。因此,我们可以使用while循环,而不是使用带有嵌套if语句的for循环。或者,如果我们无法找到数组的长度,则while循环是一个不错的选择。while循环通常由计数器控制。在下面的示例中,我们显示了遍历数组的基本while循环。关键是要控制正在创建的while循环。
While循环示例(良好):
输出:
while循环的if语句为i < 5,或大声说“ i小于5”。i每次循环运行时,变量都会增加。简单来说,这意味着i每次循环执行完整迭代时,都会将1加到变量中。在第一次迭代中,i它等于0,然后在控制台上打印“ 0”。使用while循环的最大风险是编写从未满足的条件。在现实世界中,这种情况经常发生,有人编写了while循环,却忘记测试他们的循环,并且在代码库中引入了无限循环。当永不满足条件时,将发生无限循环,并且该循环将永远运行。这通常会导致更改中断,然后导致整个软件应用程序中断并停止工作。警告:请勿运行此代码。
输出:结果可能会有所不同。
什么是map?维基百科将map定义为:“在许多编程语言中,map是将给定函数应用于函子的每个元素的高阶函数的名称,例如list,以相同顺序返回结果列表。以功能形式考虑时,它通常被称为“ 适用于所有人 ”。它是如何工作的?mapJavaScript中的函数将函数应用于数组内的每个元素。请花一点时间重新阅读该句子。然后,该map函数返回一个新数组,并将该函数应用于该数组中的每个元素。
map示例:
输出:
我们已将该map函数应用于包含四个1的数组。然后,该函数将每个元素乘以2,即x * 2,并返回一个新数组。然后将新数组存储在results变量中。
通过查看我们的输出,我们可以看到此方法成功完成。数组中的每个元素都已乘以2。在某些情况下,该方法可以替代循环,并且功能非常强大。
您已经了解了五种遍历JavaScript中数组的不同方法。这些是基本的构建块,可帮助您成功完成JavaScript编程之旅。您还将接触到高级概念map,该概念经常在大型软件应用程序中使用。因此,您将如何在项目中使用数组?您觉得哪种迭代方法最令人兴奋?
谢谢阅读!如果您喜欢我的文章,请关注我和/或给我发送消息!
Spring Boot编程中,我们可以使用多种方式返回HTML页面。下面是几种常用的方法:
Thymeleaf是一款流行的模板引擎,Spring Boot默认集成了它。使用Thymeleaf可以方便地生成HTML页面,并且支持模板继承、条件判断、循环等常见功能。在Controller中,我们可以将模型数据传递给Thymeleaf模板,然后渲染生成HTML页面。
@GetMapping("/hello")
public String hello(Model model) {
model.addAttribute("name", "world");
return "hello";
}
上面的代码中,我们将一个名为"hello"的Thymeleaf模板返回给客户端,并且传递了一个名为"name"的模型属性。在模板中,可以使用Thymeleaf的语法进行渲染。
优点:
缺点:
Freemarker是另一款常见的模板引擎,它也支持模板继承、条件判断、循环等功能。在Spring Boot中,我们可以使用Freemarker作为模板引擎,生成HTML页面。
@GetMapping("/hello")
public String hello(Model model) {
model.addAttribute("name", "world");
return "hello";
}
上面的代码与Thymeleaf的使用方式类似。只需要将返回值改为模板的名称即可。
优点:
缺点:
JSP(JavaServer Pages)是一种常见的Java Web页面技术,也可以在Spring Boot中使用。在使用JSP时,需要在pom.xml文件中添加对jsp-api和jstl的依赖,并且需要配置视图解析器。
@GetMapping("/hello")
public String hello(Model model) {
model.addAttribute("name", "world");
return "hello";
}
上面的代码中,返回值为"hello",这意味着Spring Boot将查找名为"hello.jsp"的JSP文件,并且将模型数据传递给它进行渲染。
优点:
缺点:
在前后端分离的架构中,前端和后端是独立的,可以分别开发和部署。前端使用JavaScript等技术生成HTML页面,后端则提供API接口,返回JSON等数据格式。前端通过调用后端提供的API接口获取数据,并渲染生成HTML页面。
@GetMapping("/hello")
public ResponseEntity<Map<String, Object>> hello() {
Map<String, Object> data = new HashMap<>();
data.put("name", "world");
return ResponseEntity.ok(data);
}
上面的代码中,我们返回一个Map对象,包含一个名为"name"的属性。在前端中,可以通过调用"/hello"接口获取数据,并渲染生成HTML页面。
优点:
缺点:
在使用Spring Boot返回HTML页面时,可能会出现一些常见问题,下面是一些解决方法:
@RequestMapping(value = "/hello", produces = "text/html;charset=UTF-8")
选择哪种方法返回HTML页面取决于具体的需求和项目情况。在选择方法时,需要考虑开发成本、渲染速度、易用性等因素,并且需要注意常见问题,避免出现不必要的错误。
armonyOS 2提供了两种应用开发语言:Java和JS。Java线程特性能够让多任务并行,充分利用硬件资源开发出高性能的应用。而JS却是一个单线程语言,无法像Java一样创建新的Thread,用JS语言开发是否会导致硬件资源无法充分利用的情况呢?
本文给大家介绍“ACE JS的单线程异步机制”就是解决这个问题的。然而,说到 “单线程”与“异步”,大家可能会比较疑惑,因为单线程和异步在概念上是冲突的,单线程无法做到多任务并发,也就不会存在异步这种通信机制。
确实,JS语言本身是无法实现异步的,但是ACE JS框架却提供了多线程的宿主环境,通过消息通信机制让JS语言有了异步的属性,下面我们来详细描述其原理。
使用JS开发HarmonyOS应用,使用的开发框架名为ACE(Ability Cross-Platform Environment),该框架适用于手机、平板、智慧屏、智慧表、车机等设备,具备“一次开发,多端部署”的能力。
ACE框架包括应用层(Application)、前端框架层(Framework)、引擎层(Engine)和平台适配层(Porting Layer),如下图所示:
● Application
应用层表示开发者使用JS UI框架开发的FA应用,这里的FA应用特指JS FA应用。
● Framework
前端框架层主要完成前端页面解析,以及提供MVVM(Model-View-ViewModel)开发模式、页面路由机制和自定义组件等能力。
● Engine
引擎层主要提供动画解析、DOM(Document Object Model)树构建、布局计算、渲染命令构建与绘制、事件管理等能力。
● Porting Layer
适配层主要完成对平台层进行抽象,提供抽象接口,可以对接到系统平台。比如:事件对接、渲染管线对接和系统生命周期对接等。
每个HarmonyOS JS应用,都是通过上图所示的ACE开发框架进行加载渲染的。ACE开发框架包含了JS线程、UI线程、GPU线程、IO线程,并且在ACE框架外还会存在一类后台任务线程。
其中GPU线程与IO线程主要是ACE框架初始化与页面加载渲染的过程需要的,为ACE框架内部的专有线程,不会被应用直接操作到,应用不需要特别关注;UI线程、JS线程和后台任务线程会与应用开发代码相关,后面着重分析这三个线程的作用和关系。
● UI线程:负责应用界面的绘制刷新,与应用的进程号相同,又叫主线程。如果开发JS+JAVA的混合编程,JAVA PA(Particle Ability)的onStart/onConnect等Ability生命周期回调便是运行在主线程,若在这些生命周期回调上执行耗时操作则会导致JS UI的绘制刷新卡住。
● JS线程:应用的JS代码会被JS引擎解析执行,并运行在JS线程上,而JS又是单线程语言,所以目前我们工程中看到的所有的JS代码都会执行在这个进程下唯一的JS线程上。
● 后台任务线程:这里是对ACE框架外部的后台线程的一个统称,并不单指一个线程,也并不唯一。后台任务线程包含了Java PA线程、文件操作API、网络访问API内部实现等相关线程。
下面我们结合测试代码来看一下这3个线程之间的关系。
为了验证JS线程与UI线程的关系,我们准备了一个实验性质的Demo,主要代码以及运行过程的Log如下:
首先我们在IDE建立一个Empty Ablity(JS)模板的HelloWorld工程,在生命周期、按钮响应回调方法里增加Log以观察线程情况。刚创建的app.js中Application生命周期默认已经有Log,无需额外添加。
我们只需要在主界面index.js文件中onInit增加日志:
console.info(<span class="hljs-string">'page.default onInit'</span>);复制
然后在index.hml中增加一个button以及会一直进行动画的progress组件:
<button id='button1' onclick="onButtonClick">I'm a button</button>
<progress type="circular"/>复制
最后在index.js中增加按钮点击响应事件以及Log,并且尝试sleep阻塞js线程:
function sleep(delay) {
for (var t = Date.now(); Date.now() - t <= delay; );
}
onButtonClick() {
console.info('onButtonClick begin');
sleep(1000);
console.info('onButtonClick end');
}复制
将应用运行起来,点击两次按钮,得到如下Log:
从输出的Log中,我们可以看到这个JS FA进程号为22592,也就是说UI线程是22592;生命周期回调以及按钮响应均在24077线程,这个就是JS线程,所以JS线程与UI线程不是同一个线程。
并且我们尝试通过sleep方法阻塞JS线程,想观察JS线程阻塞是否会影响到UI线程的刷新。最终得出的结论是无论JS线程sleep多长时间,UI界面上的progress组件动画一直会不断刷新,按钮也会有按压效果变化,所以我们可以推测JS线程与UI线程的相互调用应该是通过某种消息机制完成的,而不是阻塞式的调用。
ACE JS框架提供了JS FA(Feature Ability)调用Java PA(Particle Ability)的机制,该机制提供了一种通道来传递方法调用、处理数据返回以及订阅事件上报。我们同样制作一个Demo来验证JS线程与Java PA线程的关系:
在JS中,我们通过FeatureAbility.callAbility拉起并调用了名为一个类名为ServiceAbility的Java PA,并拿到返回结果:
var action = {};
action.bundleName = <span class="hljs-string">'com.blancwu.test'</span>;
action.abilityName = <span class="hljs-string">'com.blancwu.test.ServiceAbility'</span>;
action.messageCode = <span class="hljs-number">1001</span>;
action.abilityType = <span class="hljs-number">0</span>;
action.syncOption = <span class="hljs-number">0</span>;
console.info(<span class="hljs-string">'FeatureAbility.callAbility begin'</span> + JSON.stringify(action));
FeatureAbility.callAbility(action).then(function (value) {
console.info(<span class="hljs-string">'FeatureAbility.callAbility async result '</span> + JSON.stringify(value));
})
console.info(<span class="hljs-string">'FeatureAbility.callAbility end'</span> + JSON.stringify(action));复制
在ServiceAbility的onRemoteRequest中增加Log输出,并sleep 1秒钟,以便观察线程情况与之间关系:
@Override
public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) throws RemoteException {
HiLog.info(LABEL_LOG, "onRemoteRequest begin " + code);
if (code == 1001) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Map<String, Object> result = new HashMap<String, Object>();
result.put("result", 1);
reply.writeString(ZSONObject.toZSONString(result));
}
HiLog.info(LABEL_LOG, "onRemoteRequest end " + code);
return super.onRemoteRequest(code, data, reply, option);
}复制
以上代码完成后,我们进行执行,得到的Log如下:
我们观察到本次运行主进程(UI线程)号为4133,JS代码执行在JS线程5887,Java PA响应onRemoteRequest执行在另一个后台任务线程5837。通过Log我们看到onRemoteRequst即使阻塞了后台任务线程1s也不会影响JS线程的并行执行以及主线程(UI线程)上动画的刷新,做到了JS线程与后台任务线程异步地执行事务。
上面从代码实验角度观察到了JS线程与其他线程的异步关系,那么JS线程是怎么处理来自其他多个线程的调用的呢?我们先来看一下传统的浏览器环境下的机制:
上图中,JS线程中的函数调用会存在于栈(stack)中,栈中的函数可以调用浏览器环境提供的WebAPIs,包含了DOM、ajax、timeout等API,这些API会在浏览器环境提供的另外一个外部线程执行,执行完成后会在任务队列(callback queue)中加入对应的回调事件(如onClick、onLoad、onDone)。当栈中的代码执行完毕,即栈清空后,JS线程又会通过event loop取出任务队列中的下一个任务进行执行,以此类推完成整个的程序执行。更具体的机制可以去看阮一峰老师介绍JS EventLoop的文章:
● JS EventLoop介绍
http://www.ruanyifeng.com/blog/2014/10/event-loop.html
HarmonyOS ACE开发框架同样遵循上述最基本的EventLoop调度机制,并且提供了更多的机制和API,让业务逻辑可以在外部线程执行,包含了上面提到的Java PA以及异步回调的系统能力API。其中,异步回调的系统能力API包含如文件系统操作和网络操作等,具体大家可以按照我们实验Demo的方法去尝试一下。
● 参考
https://developer.harmonyos.com/cn/docs/documentation/doc-references/js-apis-file-storage-0000000000629445
目前ACE JS应用内实现多线程的最佳方式是通过混合编程调用Java PA方式,但未来纯JS应用一定会越来越多,那么,只支持单线程的JS ACE框架的异步API能解决各种复杂场景的问题吗?
单线程的JS加上异步API能够很好解决单个I/O阻塞的问题,但是如果遇到大量的I/O事件,比如批删除大量文件,通过for循环发起了大量异步任务,也会降低执行效率,甚至阻塞其他异步任务的执行。并且如果要使用JS语言开发计算密集型的任务,也无法在唯一的JS线程上进行。
这时就需要一个真正的JS多线程处理机制了,虽然目前HarmonyOS 2还未支持,但未来HarmonyOS会考虑规划出与HTML5类似提供支持WebWorker机制,支持开发出多线程的JS代码,提供给应用开发者更多的发挥空间。
*请认真填写需求信息,我们会在24小时内与您取得联系。