×

学习Javascript循环和迭代

作者:andy0012018.10.08来源:Web前端之家浏览:7581评论:0
关键词:循环迭代

学习Javascript 循环和迭代。

循环

在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

您的支持是我们创作的动力!
温馨提示:本文作者系 ,经Web前端之家编辑修改或补充,转载请注明出处和本文链接:
https://jiangweishan.com/article/html3456348604938.html

网友评论文明上网理性发言 已有0人参与

发表评论: