资讯专栏INFORMATION COLUMN

Javascript 循环和迭代

olle / 3194人阅读

摘要:数组循环对象循环迭代在中新增了几种迭代方法。方法为数组中的每个元素执行一次函数,直到它找到一个使返回表示可转换为布尔值的值的元素。数组为数组未被修改测试数组中某些元素是否通过指定函数的测试,若有一项终止循环返回。

循环

在Javascript中数组循环使用for循环,跟其他的语言非常类似。

//数组循环
var array = [1,2,3,4,5];
for(var i = 0; i < array.length; i++){
    console.log(array[i]);
}

//对象循环
var obj = {a:1,b:2,c:3};
for(var i in obj){
    console.log(i+":"+obj[i]);
}
迭代

在ES5中新增了几种迭代方法(forEach, every, filter, map, some)。根据文档显示,这些方法都含有两个参数:

callback

    为数组中每个元素执行的函数,该函数接收三个参数:

    currentValue(当前值)

        数组中正在处理的当前元素。

    index(索引)

        数组中正在处理的当前元素的索引。

    array

        方法正在操作的数组。

thisArg可选

    可选参数。当执行回调 函数时用作this的值(参考对象)。

forEach

循环遍历数组。forEach 方法按升序为数组中含有效值的每一项执行一次callback 函数,那些已删除(使用delete方法等情况)或者未初始化的项将被跳过(但不包括那些值为 undefined 的项)。

forEach 遍历的范围在第一次调用 callback 前就会确定。调用forEach 后添加到数组中的项不会被 callback 访问到。如果已经存在的值被改变,则传递给 callback 的值是 forEach 遍历到他们那一刻的值。已删除的项不会被遍历到。如果已访问的元素在迭代时被删除了(例如使用 shift()) ,之后的元素将被跳过 。

forEach() 为每个数组元素执行callback函数;不像 map() 或者 reduce() ,它总是返回 undefined 值,并且不可链式调用。典型用例是在一个链的最后执行副作用。

没有办法中止或者跳出 forEach 循环,除了抛出一个异常。如果你需要这样,使用forEach()方法是错误的,你可以用一个简单的循环作为替代。

简单使用

下面的代码会为每一个数组元素输出一行记录:

function logArrayElements(element, index, array) {
    console.log("a[" + index + "] = " + element);
}

// 注意索引2被跳过了,因为在数组的这个位置没有项
[2, 5, ,9].forEach(logArrayElements);

// a[0] = 2
// a[1] = 5
// a[3] = 9

[2, 5,"" ,9].forEach(logArrayElements);
// a[0] = 2
// a[1] = 5
// a[2] = 
// a[3] = 9

[2, 5, undefined ,9].forEach(logArrayElements);
// a[0] = 2
// a[1] = 5
// a[2] = undefined
// a[3] = 9


let xxx;
// undefined

[2, 5, xxx ,9].forEach(logArrayElements);
// a[0] = 2
// a[1] = 5
// a[2] = undefined
// a[3] = 9
使用thisArg

从每个数组中的元素值中更新一个对象的属性:

function Counter() {
    this.sum = 0;
    this.count = 0;
}

Counter.prototype.add = function(array) {
    array.forEach(function(entry) {
        this.sum += entry;
        ++this.count;
    }, this);
    //console.log(this);
};

var obj = new Counter();
obj.add([1, 3, 5, 7]);

obj.count; 
// 4 === (1+1+1+1)
obj.sum;
// 16 === (1+3+5+7)
如果数组在迭代时被修改了,则其他元素会被跳过

下面的例子输出"one", "two", "four"。当到达包含值"two"的项时,整个数组的第一个项被移除了,这导致所有剩下的项上移一个位置。因为元素 "four"现在在数组更前的位置,"three"会被跳过。 forEach()不会在迭代之前创建数组的副本。

var words = ["one", "two", "three", "four"];
words.forEach(function(word) {
  console.log(word);
  if (word === "two") {
    words.shift();
  }
});
// one
// two
// four
every

测试数组中所有元素是否都通过指定函数的测试,若有一项终止并返回false。

every 方法为数组中的每个元素执行一次 callback 函数,直到它找到一个使 callback 返回 false(表示可转换为布尔值 false 的值)的元素。如果发现了一个这样的元素,every 方法将会立即返回 false。否则,callback 为每一个元素返回 true,every 就会返回 true。callback 只会为那些已经被赋值的索引调用。不会为那些被删除或从来没被赋值的索引调用。

every 不会改变原数组。

every 遍历的元素范围在第一次调用 callback 之前就已确定了。在调用 every 之后添加到数组中的元素不会被 callback 访问到。如果数组中存在的元素被更改,则他们传入 callback 的值是 every 访问到他们那一刻的值。那些被删除的元素或从来未被赋值的元素将不会被访问到。

every 和数学中的"所有"类似,当所有的元素都符合条件才返回true。另外,空数组也是返回true。(空数组中所有元素都符合给定的条件,注:因为空数组没有元素)。

检测所有数组元素的大小

检测数组中的所有元素是否都大于 10。

function isBigEnough(element, index, array) {
  return (element >= 10);
}
var passed = [12, 5, 8, 130, 44].every(isBigEnough);
// passed is false
passed = [12, 54, 18, 130, 44].every(isBigEnough);
// passed is true
var a = [1, 2, 3,, 4].every (function(value){
console.log(value)
   return value       
})//1,2,3,4
console.log(a)//true
a = [1, 2, 3, undefined,4].every (function(value){
console.log(value)
   return value       
})//1,2,3,undefind
console.log(a)//false
filter

使用指定的函数测试所有的元素,创建并返回一个包含所有通过测试的元素的新数组。如果没有通过测试则返回空数组。

filter 为数组中的每个元素调用一次 callback 函数,并利用所有使得 callback 返回 true 或等价于 true 的值的元素创建一个新数组。callback 只会在已经赋值的索引上被调用,对于那些已经被删除或者从未被赋值的索引不会被调用。那些没有通过 callback 测试的元素会被跳过,不会被包含在新数组中。

filter 不会改变原数组,它返回过滤后的新数组。

filter 遍历的元素范围在第一次调用 callback 之前就已经确定了。在调用 filter 之后被添加到数组中的元素不会被 filter 遍历到。如果已经存在的元素被改变了,则他们传入 callback 的值是 filter 遍历到它们那一刻的值。被删除或从来未被赋值的元素不会被遍历到。

使用 filter 创建了一个新数组,该数组的元素由原数组中值大于 10 的元素组成。

var a = [1, 2, 3, 7,4].filter(function(value){
   return value > 4      
})
console.log(a)//[7]

function isBigEnough(element) {
  return element >= 10;
}
var filtered = [12, 5, 8, 130, 44].filter(isBigEnough);
// filtered is [12, 130, 44]
map

为数组每一项(不包括通过某些方法删除或者未定义的项,值定义为undefined的项除外)执行一个指定函数,返回一个新数组,每个元素都是回调函数的结果。

map 方法会给原数组中的每个元素都按顺序调用一次  callback 函数。callback 每次执行后的返回值(包括 undefined )组合起来形成一个新数组。 callback 函数只会在有值的索引上被调用;那些从来没被赋过值或者使用 delete 删除的索引则不会被调用。

map 不修改调用它的原数组本身(当然可以在 callback 执行时改变原数组)。

使用 map 方法处理数组时,数组元素的范围是在 callback 方法第一次调用之前就已经确定了。在 map 方法执行的过程中:原数组中新增加的元素将不会被 callback 访问到;若已经存在的元素被改变或删除了,则它们的传递到 callback 的值是 map 方法遍历到它们的那一时刻的值;而被删除的元素将不会被访问到。

下面的代码创建了一个新数组,值为原数组中对应数字的平方根:

var numbers = [1, 4, 9];
var roots = numbers.map(Math.sqrt);
// roots的值为[1, 2, 3], numbers的值仍为[1, 4, 9]
使用 map 重新格式化数组中的对象

以下代码将一个包含对象的数组用以创建一个包含新重新格式化对象的新数组。

var kvArray = [{key: 1, value: 10}, 
               {key: 2, value: 20}, 
               {key: 3, value: 30}];

var reformattedArray = kvArray.map(function(obj) { 
   var rObj = {};
   rObj[obj.key] = obj.value;
   return rObj;
});

// reformattedArray 数组为: [{1: 10}, {2: 20}, {3: 30}], 

// kvArray 数组未被修改: 
// [{key: 1, value: 10}, 
//  {key: 2, value: 20}, 
//  {key: 3, value: 30}]
some

测试数组中某些元素是否通过指定函数的测试,若有一项终止循环返回true。

some 为数组中的每一个元素执行一次 callback 函数,直到找到一个使得 callback 返回一个“真值”(即可转换为布尔值 true 的值)。如果找到了这样一个值,some 将会立即返回 true。否则,some 返回 false。callback 只会在那些”有值“的索引上被调用,不会在那些被删除或从来未被赋值的索引上调用。

some 被调用时不会改变数组。

some 遍历的元素的范围在第一次调用 callback. 时就已经确定了。在调用 some 后被添加到数组中的值不会被 callback 访问到。如果数组中存在且还未被访问到的元素被 callback改变了,则其传递给 callback 的值是 some 访问到它那一刻的值。

测试数组元素的值

下面的例子检测在数组中是否有元素大于 10。

function isBiggerThan10(element, index, array) {
  return element > 10;
}

[2, 5, 8, 1, 4].some(isBiggerThan10);  // false
[12, 5, 8, 1, 4].some(isBiggerThan10); // true
使用箭头函数测试数组元素的值
[2, 5, 8, 1, 4].some(x => x > 10);  // false
[12, 5, 8, 1, 4].some(x => x > 10); // true
判断数组元素中是否存在某个值
var fruits = ["apple", "banana", "mango", "guava"];

function checkAvailability(arr, val) {
  return arr.some(function(arrVal) {
    return val === arrVal;
  });
}

checkAvailability(fruits, "kela");   // false
checkAvailability(fruits, "banana"); // true
将任意值转换为布尔类型
var TRUTHY_VALUES = [true, "true", 1];

function getBoolean(value) {
  "use strict";
   
  if (typeof value === "string") { 
    value = value.toLowerCase().trim();
  }

  return TRUTHY_VALUES.some(function(t) {
    return t === value;
  });
}

getBoolean(false);   // false
getBoolean("false"); // false
getBoolean(1);       // true
getBoolean("true");  // true

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96769.html

相关文章

  • JavaScript的几种循环方式

    摘要:本教程解释了现代中各种各样的循环可能性目录介绍提供了许多迭代循环的方法。引入了循环,它结合了的简洁性和破解能力注意使用。此循环在每次迭代中创建一个新范围,因此我们可以安全地使用它而不是。 JavaScript提供了许多通过LOOPS迭代的方法。本教程解释了现代JAVASCRIPT中各种各样的循环可能性 showImg(https://segmentfault.com/img/bVbfH...

    Allen 评论0 收藏0
  • JavaScript的几种循环方式

    摘要:本教程解释了现代中各种各样的循环可能性目录介绍提供了许多迭代循环的方法。引入了循环,它结合了的简洁性和破解能力注意使用。此循环在每次迭代中创建一个新范围,因此我们可以安全地使用它而不是。 JavaScript提供了许多通过LOOPS迭代的方法。本教程解释了现代JAVASCRIPT中各种各样的循环可能性 showImg(https://segmentfault.com/img/bVbfH...

    piapia 评论0 收藏0
  • JavaScript的几种循环方式

    摘要:本教程解释了现代中各种各样的循环可能性目录介绍提供了许多迭代循环的方法。引入了循环,它结合了的简洁性和破解能力注意使用。此循环在每次迭代中创建一个新范围,因此我们可以安全地使用它而不是。 JavaScript提供了许多通过LOOPS迭代的方法。本教程解释了现代JAVASCRIPT中各种各样的循环可能性 showImg(https://segmentfault.com/img/bVbfH...

    ztyzz 评论0 收藏0
  • ES6语法之可迭代协议迭代器协议

    摘要:有两个协议可迭代协议和迭代器协议。为了变成可迭代对象,一个对象必须实现或者它原型链的某个对象必须有一个名字是的属性迭代器协议该迭代器协议定义了一种标准的方式来产生一个有限或无限序列的值。 ECMAScript 2015的几个补充,并不是新的内置或语法,而是协议。这些协议可以被任何遵循某些约定的对象来实现。有两个协议:可迭代协议和迭代器协议。 可迭代协议 可迭代协议允许 JavaScri...

    sarva 评论0 收藏0
  • JavaScript 中优雅的提取循环内的数据

    摘要:翻译疯狂的技术宅原文在本文中,我们将介绍两种提取循环内数据的方法内部迭代和外部迭代。它是循环和递归的组合递归调用在行。 翻译:疯狂的技术宅 原文:http://2ality.com/2018/04/ext... 在本文中,我们将介绍两种提取循环内数据的方法:内部迭代和外部迭代。 循环 举个例子,假设有一个函数 logFiles(): const fs = require(fs); c...

    Alliot 评论0 收藏0
  • JavaScript 设计模式(五):迭代器模式

    摘要:文章内容分两部分前半部分为迭代器模式概念后半部分为中迭代器上半部分开始迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。下半部分开始的迭代器迭代器等同于遍历器。执行该函数,会返回一个遍历器对象。 showImg(https://segmentfault.com/img/bVbuyaZ?w=800&h=600); 文章内容分两部分: 前半部分为 迭...

    zhou_you 评论0 收藏0

发表评论

0条评论

olle

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<