JS中for-in语句与for-of语句

JS从其他语言中借鉴了很多流控制语句,最典型的就是for,作为前测试循环语句,不得不提一下其中的for-in与for-of语句。
首先来看一下for-in,权威解释(W3school、菜鸟教程、JavaScript高级程序设计)为用于遍历数组或者对象的属性
来看一下实例:

var arr = [1, '2', 3, null, '4', undefined];
for(var i in arr){
    console.log(i);
}
// 0
// 1
// 2
// 3
// 4
// 5

可以看到对于该数组输出的是它的序号,那么再看一个对象的实例

var dog = {
    name : '大黄',
    age : 5,
    gender : '雄性'
}
for(var i in dog){
    console.log(i);
}
// name
// age
// gender

可以看到输出了该对象的属性,每一次执行循环时,都会将dog对象中存在的一个属性名赋值给变量i,这个过程会一直持续到对象中所有的属性都被枚举一遍为止,但是输出属性名的顺序是不可预测的,因浏览器而异。对于之前数组的例子,可以将其看作为这样:

var arr = {
    0: 1,
    1:'2',
    2: 3,
    3: null,
    4: '4',
    5: undefined
}

输出的序号也就是该数组的属性。
继续看这样一个例子,如果该对象是空,则会如何输出:

var arr = {

}
for(var i in arr){
    console.log(i);
}

无输出,这很正常,但是如果要迭代对象的变量值是null或者undefined呢?

var arr = null
for(var i in arr){
    console.log(i);
}
var arr = undefined
for(var i in arr){
    console.log(i);
}

均无输出,需要主要的是,这里的控制台输出,并不代表着该循环体被执行,JavaScript高级程序设计(第3版)Page57指出:如果表示要迭代的对象的变量值为null或undefined,for-in语句就会抛出错误。ECMAScript5更正了这一行为;对这种情况不再抛出错误,而只是不执行循环体。
扩展一下,既然for-in遍历的为对象的key,那么如何利用for-in输出对象的value呢?来看下面的代码:

var dog = {
    name : '大黄',
    age : 5,
    gender : '雄性'
}
for(var i in dog){
    console.log(dog[i]);
}
// 大黄
// 5
// 雄性

继续深挖,如果在遍历对象前,对象的属性改变了,无论是数量还是属性值,那么for-in会怎么样输出?

var dog = {
    name : '大黄',
    age : 5,
    gender : '雄性'
}
dog.color = 'black';
dog.age = 6;
for(var i in dog){
    console.log(i, `:`,dog[i]);
}
// name : 大黄
// age : 6
// gender : 雄性
// color : black

从结果可以得出结论,for-in遍历的是更新后的对象。
经过上面的检验,可以得出:for-in循环会遍历一个object所有的可枚举属性因此,对于对象的内置函数toString,valueOf等则无法遍历,那么推测一下,for-in是否可以遍历其原型上的属性呢?

var dog = {
    name : '大黄',
    age : 5,
    gender : '雄性',
}
dog.color = 'black';
dog.age = 6;
Object.prototype.objCustom = function () {
    return 'aaa';
}
for(var i in dog){
    console.log(i, `:`,dog[i]);
}
// name : 大黄
// age : 6
// gender : 雄性
// color : black
// objCustom : function () {
//     return 'aaa';
// }

答案是肯定的,但是这种将原型上的属性输出也会带来一些不必要的麻烦,将上面这个例子:

Array.prototype.myfunction = function () {
    return 'aaa';
}
var dog = [
    {name:'小黄', age : 3},
    {name:'小黑', age : 4},
    {name:'小白', age : 5}
]
for(var i in dog){
    console.log(dog[i].name)
}
console.log('这是一行空值测试~')

看一下输出结果:
在这里插入图片描述
可以看到多于输出了一个空值,这在一些大型的项目中,可能就会导致一些bug,解决方法有这些:

  1. 使用hasOwnProperty属性判断
 for(var i in dog){
    if(!dog.hasOwnProperty(i)){
        continue;
    }
    console.log(dog[i].name)
}

在这里插入图片描述
2. 使用length属性来进行条件循环
3. 使用for-of语句
接着上文的引入,来看一下for-of,for-of是ES6中引入的新特性,用来弥补ES-5引入for-in的缺陷,与for-of的本质区别在于,for-of遍历的是数组或对象的属性值(value),来看一个简单的数组例子:

var arr = [1, '2', null, 3, undefined, '4'];
for(var i of arr){
    console.log(i);
}
// 1
// 2
// null
// 3
// undefined
// 4

可以看到输出了数组中的元素各项元素,再来看一个对象实例:

var obj = {
    name : '小黄',
    age : 4,
    gender : 'black'
};
for(var j of obj){
    console.log(j);
}

结果报错了,明显for-of语句无法遍历普通对象,那么如何解决这问题呢?
使用Object.keys()方法,将对象中的key收纳为一个数组,然后输出,就像以下代码所示:

   var obj = {
    name : '小黄',
    age : 4,
    gender : 'black'
};
for(var j of Object.keys(obj)){
    console.log(j);
}
// name
// age
// gender

该方法的遍历是遵循怎样的原则呢?

var array = ['a', 123, {a:'1', b:'2'}];
array.name = '小黄';
for(var i of array){
    console.log(i);
}
// a
// 123
// { a: '1', b: '2' }

以上代码中,对array数组增加了属性值,但是结果并没有输出增加该属性,因此可以得出结论,for-of不同for-in,for-of只会遍历出初始数组或对象的key,即使在原型上进行增加也是如此。
参考博客:https://www.jb51.net/article/44028.htm
https://blog.csdn.net/wangpenglonton/article/details/79095011
https://segmentfault.com/q/1010000006658882

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值