js之 for循环


普通for 循环


语法

for ([initialization]; [condition]; [final-expression])
statement
initialization
一个表达式 (包含赋值语句) 或者变量声明。典型地被用于初始化一个计数器。该表达式可以使用var关键字声明新的变量。初始化中的变量不是该循环的局部变量,而是与for循环处在同样的作用域中。该表达式的结果无意义。
condition
一个条件表达式被用于确定每一次循环是否能被执行。如果该表达式的结果为true, statement 将被执行。 这个表达式是可选的。如果被忽略,那么就被认为永远为真。如果计算结果为假,那么执行流程将被跳到for语句结构后面的第一条语句。
final-expression
每次循环的最后都要执行的表达式。执行时机是在下一次condition的计算之前。通常被用于更新或者递增计数器变量。
statement
只要condition的结果为true就会被执行的语句。 要在循环体内执行多条语句,使用一个块语句({ ... })来包含要执行的语句。没有任何语句要执行,使用一个空语句(;)。

 事例

for (var i = 0; i < 9; i++) {
console.log(i);
// more statements
}

for await...of


语法

for await (variable of iterable) {
statement
}
variable在每次迭代时,将不同属性的值分配给变量
iterable迭代其可迭代属性的对象。 事例:
async function* asyncGenerator() {
var i = 0;
while (i < 3) {
yield i++;
}
} (async function() {
for await (num of asyncGenerator()) {
console.log(num);
}
})();
//
//
//

 for each...in


语法

for each (variable in object) {
statement
}
variable
用来遍历属性值的变量,前面的var关键字是可选的.该变量是函数的局部变量而不是语句块的局部变量.
object
该对象的属性值会被遍历.
statement
遍历属性值时执行的语句. 如果想要执行多条语句, 请用({ ... }) 将多条语句括住.

事例:

var sum = 0;
var obj = {prop1: 5, prop2: 13, prop3: 8}; for each (var item in obj) {
sum += item;
} print(sum); // 输出"26",也就是5+13+8的值

警告:永远不要使用for each...in语句遍历数组,仅用来遍历常规对象


 for...in


语法

for (variable in object) {...}
variable
在每次迭代时,将不同的属性名分配给变量。
object
被迭代枚举其属性的对象

描述

for...in 循环只遍历可枚举属性。像 Array和 Object使用内置构造函数所创建的对象都会继承自Object.prototypeString.prototype的不可枚举属性,例如 String 的 indexOf()  方法或 ObjecttoString()方法。循环将遍历对象本身的所有可枚举属性,以及对象从其构造函数原型中继承的属性(更接近原型链中对象的属性覆盖原型属性)。

删除,添加或者修改属性

for...in 循环以任意序迭代一个对象的属性(请参阅delete运算符,了解为什么不能依赖于迭代的表面有序性,至少在跨浏览器设置中)。如果一个属性在一次迭代中被修改,在稍后被访问,其在循环中的值是其在稍后时间的值。一个在被访问之前已经被删除的属性将不会在之后被访问。在迭代进行时被添加到对象的属性,可能在之后的迭代被访问,也可能被忽略。通常,在迭代过程中最好不要在对象上进行添加、修改或者删除属性的操作,除非是对当前正在被访问的属性。这里并不保证是否一个被添加的属性在迭代过程中会被访问到,不保证一个修改后的属性(除非是正在被访问的)会在修改前或者修改后被访问,不保证一个被删除的属性将会在它被删除之前被访问。

数组迭代和 for...in


提示:for...in不应该用于迭代一个 Array,其中索引顺序很重要。

数组索引只是具有整数名称的枚举属性,并且与通用对象属性相同。不能保证for ... in将以任何特定的顺序返回索引。for ... in循环语句将返回所有可枚举属性,包括非整数类型的名称和继承的那些。

因为迭代的顺序是依赖于执行环境的,所以数组遍历不一定按次序访问元素。因此当迭代访问顺序很重要的数组时,最好用整数索引去进行for循环(或者使用 Array.prototype.forEach() 或 for...of 循环)。

仅迭代自身的属性

如果你只要考虑对象本身的属性,而不是它的原型,那么使用 getOwnPropertyNames() 或执行 hasOwnProperty() 来确定某属性是否是对象本身的属性(也能使用propertyIsEnumerable)。或者,如果你知道不会有任何外部代码干扰,您可以使用检查方法扩展内置原型。

事例

var obj = {a:1, b:2, c:3};

for (var prop in obj) {
console.log("obj." + prop + " = " + obj[prop]);
} // Output:
// "obj.a = 1"
// "obj.b = 2"
// "obj.c = 3"
var triangle = {a: 1, b: 2, c: 3};

function ColoredTriangle() {
this.color = 'red';
} ColoredTriangle.prototype = triangle; var obj = new ColoredTriangle(); for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
console.log(`obj.${prop} = ${obj[prop]}`);
}
} // Output:
// "obj.color = red"

 for...of

语法

for (variable of iterable) {
//statements
}
variable在每次迭代中,将不同属性的值分配给变量。iterable被迭代枚举其属性的对象。

示例

迭代Array

let iterable = [10, 20, 30];

for (let value of iterable) {
value += 1;
console.log(value);
}
//
//
//

如果你不想修改语句块中的变量 , 也可以使用const代替let

let iterable = [10, 20, 30];

for (const value of iterable) {
console.log(value);
}
//
//
//

迭代String

let iterable = "boo";

for (let value of iterable) {
console.log(value);
}
// "b"
// "o"
// "o"

迭代 TypedArray

let iterable = new Uint8Array([0x00, 0xff]);

for (let value of iterable) {
console.log(value);
}
//
//

迭代Map

let iterable = new Map([["a", 1], ["b", 2], ["c", 3]]);

for (let entry of iterable) {
console.log(entry);
}
// ["a", 1]
// ["b", 2]
// ["c", 3] for (let [key, value] of iterable) {
console.log(value);
}
//
//
//

迭代 Set

let iterable = new Set([1, 1, 2, 2, 3, 3]);

for (let value of iterable) {
console.log(value);
}
//
//
//

迭代 arguments 对象

(function() {
for (let argument of arguments) {
console.log(argument);
}
})(1, 2, 3); //
//
//

迭代 DOM 集合

迭代 DOM 元素集合,比如一个NodeList对象:下面的例子演示给每一个 article 标签内的 p 标签添加一个 "read" 类。

//注意:这只能在实现了NodeList.prototype[Symbol.iterator]的平台上运行
let articleParagraphs = document.querySelectorAll("article > p"); for (let paragraph of articleParagraphs) {
paragraph.classList.add("read");
}

关闭迭代器

对于for...of的循环,可以由breakthrow 或return终止。在这些情况下,迭代器关闭。

function* foo(){
yield 1;
yield 2;
yield 3;
}; for (let o of foo()) {
console.log(o);
break; // closes iterator, triggers return
}

迭代生成器

你还可以迭代一个生成器:

function* fibonacci() { // 一个生成器函数
let [prev, curr] = [0, 1];
for (;;) { // while (true) {
[prev, curr] = [curr, prev + curr];
yield curr;
}
} for (let n of fibonacci()) {
console.log(n);
// 当n大于1000时跳出循环
if (n >= 1000)
break;
}

不要重用生成器

生成器不应该重用,即使for...of循环的提前终止,例如通过break关键字。在退出循环后,生成器关闭,并尝试再次迭代,不会产生任何进一步的结果。

var gen = (function *(){
yield 1;
yield 2;
yield 3;
})();
for (let o of gen) {
console.log(o);
break;//关闭生成器
} //生成器不应该重用,以下没有意义!
for (let o of gen) {
console.log(o);
}

迭代其他可迭代对象

你还可以迭代显式实现可迭代协议的对象:

var iterable = {
[Symbol.iterator]() {
return {
i: 0,
next() {
if (this.i < 3) {
return { value: this.i++, done: false };
}
return { value: undefined, done: true };
}
};
}
}; for (var value of iterable) {
console.log(value);
}
//
//
//

for...offor...in的区别

无论是for...in还是for...of语句都是迭代一些东西。它们之间的主要区别在于它们的迭代方式。

for...in 语句以原始插入顺序迭代对象的可枚举属性。

for...of 语句遍历可迭代对象定义要迭代的数据。

以下示例显示了与Array一起使用时,for...of循环和for...in循环之间的区别。

Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {}; let iterable = [3, 5, 7];
iterable.foo = 'hello'; for (let i in iterable) {
console.log(i); // logs 0, 1, 2, "foo", "arrCustom", "objCustom"
} for (let i in iterable) {
if (iterable.hasOwnProperty(i)) {
console.log(i); // logs 0, 1, 2, "foo"
}
} for (let i of iterable) {
console.log(i); // logs 3, 5, 7
}
Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {}; let iterable = [3, 5, 7];
iterable.foo = 'hello';

每个对象将继承objCustom属性,并且作为Array的每个对象将继承arrCustom属性,因为将这些属性添加到Object.prototypeArray.prototype。由于继承和原型链,对象iterable继承属性objCustomarrCustom

for (let i in iterable) {
console.log(i); // logs 0, 1, 2, "foo", "arrCustom", "objCustom"
}

此循环仅以原始插入顺序记录iterable 对象的可枚举属性。它不记录数组元素357 或hello,因为这些不是枚举属性。但是它记录了数组索引以及arrCustomobjCustom。如果你不知道为什么这些属性被迭代,array iteration and for...in中有更多解释。

for (let i in iterable) {
if (iterable.hasOwnProperty(i)) {
console.log(i); // logs 0, 1, 2, "foo"
}
}

这个循环类似于第一个,但是它使用hasOwnProperty() 来检查,如果找到的枚举属性是对象自己的(不是继承的)。如果是,该属性被记录。记录的属性是012foo,因为它们是自身的属性(不是继承的)。属性arrCustomobjCustom不会被记录,因为它们是继承的

for (let i of iterable) {
console.log(i); // logs 3, 5, 7
}

该循环迭代并记录iterable作为可迭代对象定义的迭代值,这些是数组元素 357,而不是任何对象的属性


摘取自MDN


js 之 for循环的更多相关文章

  1. js 控制Div循环显示 非插件版

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. js种的循环语句

    //js种的循环语句 //while与do while的区别是while是满足条件后才执行 //do while是不管满不满足条件都会执行一次 //for 循环与while,do while相比循环结 ...

  3. js中的循环语句

    js中的循环语句可分为三种:1.while:2.do……while:3.for. while的语法为 while (exp) {    //statements;} var a=1,b=0; whil ...

  4. js的事件循环绑定和jQuery的隐式迭代

    js的事件循环绑定和jQuery的隐式迭代 js事件循环绑定 jQuery隐式迭代 先举一个例子:给定一个ul,点击列表内的每一个li元素,使它的背景色变红,下边分别用js代码和jQuery实现. & ...

  5. 原生JS—实现图片循环切换的两种方法

    今天我们主要讲讲如何使用原生JS实现图片的循环切换的方法.多余的话我们就不多说了,我们一个一个开始讲吧. 1  原生JS实现图片循环切换 -- 方法一 在上栗子之前我们先简单介绍一下所用的一些知识点. ...

  6. 原生JS—实现图片循环切换及监测鼠标滚动切换图片

    今天我们主要讲讲如何使用原生JS实现图片的循环切换的方法以及如何检测鼠标滚动循环切换图片.多余的话我们就不多说了,我们一个一个开始讲吧. 1  原生JS实现图片循环切换 -- 方法一 在上栗子之前我们 ...

  7. js中的循环

    js中的循环是我们经常要用到的,现在进行一些归纳. 一.javascript种的循环. 1.循环对象 var o = { name: 'Jack', age: 20, city: 'Beijing' ...

  8. JS JavaScript事件循环机制

    区分进程和线程 进程是cpu资源分配的最小单位(系统会给它分配内存) 不同的进程之间是可以同学的,如管道.FIFO(命名管道).消息队列 一个进程里有单个或多个线程 浏览器是多进程的,因为系统给它的进 ...

  9. js:for循环ul/li,获取当前被点击元素的id,以及给其他li设置属性

    js:for循环ul/li,获取当前被点击元素的id,以及给其他li设置属性 <!doctype html> <html> <head> <meta char ...

  10. Node.js:事件循环

    ylbtech-Node.js:事件循环 1.返回顶部 1. Node.js 事件循环 Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高. Node.js 的每一个 ...

随机推荐

  1. 1028 List Sorting (25 分)

    Excel can sort records according to any column. Now you are supposed to imitate this function. Input ...

  2. Windows命令help的基本使用

  3. Google GMS介绍

    Google GMS介绍GMS全称为GoogleMobile Service.GMS目前提供有Search.Search by Voice.Gmail.Contact Sync.Calendar Sy ...

  4. Java第二十四天,线程安全

    线程安全 1.定义 多线程访问共享数据,会产生线程安全问题. 2.代码模拟 卖票Ticked类: package com.lanyue.day22; public class Person { pub ...

  5. Python设计模式(7)-建造者模式

    # coding=utf-8 class Report: def create_head(self): pass def create_body(self): pass class year_Repo ...

  6. Linux中使用netstat命令的基本操作,排查端口号的占用情况

    Linux中netstat命令详解 Netstat是控制台命令,是一个监控TCP/IP网络的非常有用的工具,它可以显示路由表.实际的网络连接以及每一个网络接口设备的状态信息.Netstat用于显示与I ...

  7. qad progress数据库启动出错解决

    1. 启动时报:SYSTEM ERROR: Wrong dbkey in block. Found 0, should be 6342528 in area 36.  (439) ** Save fi ...

  8. Jbox弹窗控件无法获取子页面元素值得问题

    top.$.jBox.open("iframe:${ctx}/report/reportSubjectDatabase/toChildWindow", "请选择重构快照表 ...

  9. echarts多个数据添加多个纵坐标

    在我们echarts开发中,肯定会遇到一个问题.那就是当有多个数据且数据大小差距太大时,就会出现有些数据小到看不到的情况.所以在遇到这种情况时,我通常的解决办法就是给他多加一个坐标轴. option  ...

  10. work of weekend 12/12/2015~12/14/2015

    part 组员                周末工作+今日工作 工作耗时/h 明日计划 工作耗时/h backup 冯晓云 try the backup plan:brower:rewrite bi ...