JavaScript中直接供应的轮回,主要有以下几种
while 轮回
和其他言语一样,JavaScript中的while
轮回有两种情势:
while (condition) {
// 轮回内容
}
do {
// 轮回内容
} while (condition)
个中两种情势的差别在于,对condition
推断的位置差别,前者先推断,再实行轮回体;而后者先实行轮回体一次,再举行前提推断。所以效果的差别就是后者能将轮回内容最少实行一次。
for 轮回
for
轮回的语法:
for (init; condition; step) {
// 轮回体代码块
}
init 语句 中的内容,会在轮回代码最先前实行一次,一般用来声明一些变量。
condition 语句 会在每次轮回最先时,举行推断。假如第一次就不满足,则不会进入轮回。
step 语句 会在每次轮回完毕时实行,一般是递增或递减condition中的某个变量。
var arr = [0, 10, 20, 30];
for (var j = 0; j < arr.length; j++) {
console.log(arr[j]);
}
// 假如在轮回体中不会转变数组的长度,用一个变量存储数组长度是个更高效的挑选
for (var i = 0, l = arr.length; i < l; i++) {
console.log(arr[i]);
}
var k = 0,
length = arr.length;
for (; k < length; k++) {
console.log(arr[k]);
}
for
轮回中的init语句,一般用来声明初始变量,其能够有多个,用,
分开即可。而且因为此语句是在轮回最先前实行,且只用实行一次,所以假如在外部已声明过要用的变量了,for
轮回中的这个语句能够直接省略,如上例中的第三个for
轮回所示。
for
轮回的前提语句是在每次轮回体最先前举行推断,假如为true
,则实行轮回体内容,不然完毕轮回。当此语句省略时,示意不举行前提推断,轮回将一向实行,只要在轮回中运用break
来跳出轮回。
for
轮回的step语句,最常见的就是运用++
也许--
运算符的表达式,不过也能够运用其他恣意值的,而且也能够省略,换到轮回体中举行转变赋值。
for-in 轮回
for-in
轮回是JavaScript中特地供应用来遍历对象属性的。
var zs = {
name: 'zhang san',
gender: 'male',
age: 26
};
for (var key in zs) {
console.log('%s : %s', key, zs[key]);
}
// name : zhang san
// gender : male
// age : 26
不过须要注重一点题目,请看以下示例:
function Person(name, gender) {
this.name = name;
this.gender = gender;
}
Person.prototype.sayHello = function() {
console.log('Hello,I am', this.name, '. I\'m a', this.gender);
};
var zs = new Person('zhang san', 'male');
for (var key in zs) {
console.log('%s : %s',key, zs[key]);
}
// name : zhang san
// gender : male
// sayHello : function () {
// console.log('Hello,I am', this.name, '. I\'m a', this.gender);
// }
此次轮回遍历中,它还输出了zs
原型链上的属性sayHello
。这反应出一个题目,for - in
轮回会遍历全部原型链,虽然能够运用hasOwnProperty
要领举行过滤仅猎取自身属性,但其接见的还是全部原型链,遍历局限较广,所以其效力比较低,一般来讲,其效力仅为一般for
轮回的1/7。
在JavaScript中,因为数组也是对象,所以此要领也能够用来遍历数组。
var arr = [1, 2, 3, 4];
for (var i in arr) {
console.log(typeof i);
if (arr.hasOwnProperty(i))
console.log('arr[%s] : %d', i, arr[i]);
else
console.log('arr.%s : ', i, arr.[i]);
}
// string
// arr[0] : 1
// string
// arr[1] : 2
// string
// arr[2] : 3
// string
// arr[3] : 4
// string
// arr.where : function ...
// string
// arr.groupBy : function ...
// string
// arr.has : function ...
这个输出的效果也许不是你设想的模样,然则他就是如许。我们以为的索引,现实是对象的键名,所以其是String
范例。关于数组来讲,和对象一样,在其原型上扩大的要领where
、groupBy
、has
也都被输出了。 也许会有疑问,数组不是有length
属性吗,为何没有输出呢?缘由在于数组的length
属性是不可罗列属性,for - in
轮回不会接见这些属性。关于此的更多学问可参考MDN – 属性的可罗列性和所有权
Array 在 Javascript 中是一个对象,
Array
的索引是属性名。事实上, Javascript 中的 “array
” 有些误导性, Javascript 中的Array
并不像大部分其他言语的数组。起首, Javascript 中的Array
在内存上并不一连,其次,Array
的索引并非指偏移量。现实上,Array
的索引也不是Number
范例,而是String
范例的。我们能够正确运用如arr[0]
的写法的缘由是言语能够自动将Number
范例的 0 转换成String
范例的 “0” 。所以,在 Javascript 中从来就没有Array
的索引,而只要相似 “0” 、 “1” 等等的属性。
for - in
轮回底本就是用来遍历对象的,用其来遍历数组并不适宜,不过也有破例的状况,比方希罕数组:
var arr = new Array(1000);
arr[0] = 1;
arr[99] = 3;
arr[999] = 5;
// for轮回
for (var i = 0, l = arr.length; i < l; i++) {
console.log('arr[%s]', i, arr[i]);
}
console.log('i :' , i);
// ...
// arr[0] 1
// ...
// arr[99] 3
// ...
// arr[999] 5
// i : 1000
// for - in 轮回
var count = 0;
for(var j in arr){
count ++ ;
if(arr.hasOwnProperty(j)){
console.log('arr[%s]', j, arr[j]);
}
}
console.log('count : ', count);
// arr[0] 1
// arr[99] 3
// arr[999] 5
// i : 1000
直接运用一般的for
轮回,轮回次数为数组长度1000次,而运用for - in
轮回,仅仅轮回了3次。
上面看起来轮回的效力是高了不少,然则在前面已说过了,for - in
的专职是对象的遍历(相似的另有Object.keys()
),因而上面的计划并非是一个圆满的计划,更好的做法是用是数组自身的遍历要领forEach
(forEach
为ES5中新增,须要IE9+)。
var arr = new Array(1000);
arr[0] = 1;
arr[99] = 3;
arr[999] = 5;
var count = 0;
arr.forEach(function(value, index) {
count++;
console.log(typeof index);
console.log(index, value);
});
console.log('count', count);
// number
// 0 1
// number
// 99 3
// number
// 999 5
// count 3
如许就高效地举行了轮回遍历,而且数组的索引index
也被正确地辨认为了number
范例。
也许你会想到jQuery中供应的东西要领$.each()
和$.map()
也许实例jQuery对象的each
和map
要领,然则效果会让你扫兴的,照旧会是轮回1000次,以下是示例:
var count1 = 0;
$.each(arr, function(index, value) {
count1++;
console.log(index, value);
});
console.log('count1',count1);
// count1 1000
var count2 = 0;
$.map(arr,function(value,index){
count2++;
console.log(index, value);
});
console.log('count2',count2);
// count2 1000
从上面临比来看Array.prototype.forEach
要领好像不错,但其轮回效力依然不如一般的for
轮回,不过上风在于在希罕数组的处置惩罚。
不过forEach
要领,严厉来算并不算是轮回,缘由在于,它并不能相应轮回应有的break
和continue
语句。正确地讲,它是一个遍历函数,对每一个元素实行指定的回调函数。
for-of轮回
ES6中又新增了for - of
轮回,它与for - in
轮回相似,但又有所差别。
for - of
支撑对数组和类数组对象举行轮回,不支撑一般对象的轮回。for - of
支撑对字符串举行轮回遍历。for - of
支撑对Map
和Set
(ES6 中新增的范例)对象遍历。for - of
不支撑一般对象的轮回遍历。
// 数组
var arr = [0, 1, 2, 3, 4, 5];
for (let index of arr) {
if (index === 1) continue;
if (index === 4) break;
console.log(typeof index);
console.log(index, arr[index]);
}
// number
// 0 0
// number
// 2 2
// number
// 3 3
当索引为1时直接举行下一次轮回,而当索引为4时,直接退出轮回,因而输出如上效果,也一样正确辨认索引为number
范例。
// 类数组
// 类数组
var divs = document.querySelectorAll('div');
for (let i of divs) {
console.log(i.classList);
}
// ["container", "md-doc", value: "container md-doc"]
// ["doc-cata", value: "doc-cata"]
// ["nicescroll-rails", "nicescroll-rails-vr", value: "nicescroll-rails nicescroll-rails-vr"]
// ["nicescroll-cursors", value: "nicescroll-cursors"]
// ["nicescroll-rails", "nicescroll-rails-hr", value: "nicescroll-rails nicescroll-rails-hr"]
// ["nicescroll-cursors", value: "nicescroll-cursors"]
for (let k in divs) {
console.log(k, divs[k].classList);
}
// "0" ["container", "md-doc", value: "container md-doc"]
// "1" ["doc-cata", value: "doc-cata"]
// "2" ["nicescroll-rails", "nicescroll-rails-vr", value: "nicescroll-rails nicescroll-rails-vr"]
// "3" ["nicescroll-cursors", value: "nicescroll-cursors"]
// "4" ["nicescroll-rails", "nicescroll-rails-hr", value: "nicescroll-rails nicescroll-rails-hr"]
// "5" ["nicescroll-cursors", value: "nicescroll-cursors"]
// length undefined
// item undefined
// keys undefined
// values undefined
// entries undefined
// forEach undefined
在for - of
轮回用于类数组对象的处置惩罚时,须要注重,of
症结字前面的变量即为类数组对象中的键值,如上例所示,在for - of
轮回中i
即代表着DOM nodelist 中的每一个对象,而在for - in
轮回中k
代表的仅仅是对象的键名。
参考链接
原文宣布在我的博客JavaScript 轮回,迎接接见!