你不知道的JS系列 ( 39 ) - 对象遍历

for 循环可以遍历数组

var myArray = [1,2,3];
for(var i=0; i<myArray.length; i++) {
  console.log(myArray[i])
} // 1 2 3

ES5 增加了数组的辅助迭代器,包括 forEach(...)、every(...)、some(...)

forEach(...) 会遍历数组中的所有值并忽略回调函数的返回值

every(...) 会一直运行直到回调返回 false

some(...) 会一只运行直到回到函数返回 true

for..in 循环可以用来遍历对象的可枚举属性列表(包括原型链)。使用 for..in 遍历对象是无法直接获取属性值的,因为实际上遍历的是对象中的所有可枚举属性,需要手动获取属性值

遍历数组下标时采用的是数字顺序,但是遍历对象属性时的顺序是不确定的,因此,在不同环境中需要保证一致性时,一定不要相信任何观察到的顺序

那么如何遍历值而不是下标和属性呢,使用 ES6 增加的 for..of 循环语法

var myArray = [1,2,3];
for(var v of myArray){
  console.log(v)
}
// 1 2 3

for..of 循环首先会向被访问对象请求一个迭代器对象,然后通过调用迭代器对象的 next() 方法来遍历所有返回值

数组有内置的 @@iterator,因此 for..of 可以直接应用在数组上。我们使用内置的 @@iterator 来手动遍历数组

var myArray = [1,2,3];
var it = myArray[Symbol.iterator]();
it.next(); // {value: 1, done: false}
it.next(); // {value: 2, done: false}
it.next(); // {value: 3, done: false}
it.next(); // {done: true}

这里和值 ‘3’ 返回的是 done:false,咋一看好像很奇怪,你必须调用一次 next() 才能得到 done:true,从而确定完成遍历

普通的对象没有内置的 @@iterator,所以无法自动完成 for..of 遍历,当然,可以自己给任何想遍历的对象定义 @@iterator

var myObj = {
  a:2,
  b:3
}
Object.defineProperty(myObj, Symbol.iterator, {
  enumerable: false,
  writable: false,
  configurable: true,
  value: function() {
    var o = this;
    var idx = 0;
    var ks = Object.keys(o);
    return {
      next: function() {
        return {
          value: o[ks[idx++]],
          done: (idx > ks.length)
        }
      }
    }
  }
})

var it = myObj[Symbol.iterator]();
it.next(); // {value: 2, done: false}
it.next(); // {value: 3, done: false}
it.next(); // {done: true}

原文地址:https://www.cnblogs.com/wzndkj/p/12596368.html

时间: 2024-08-30 02:08:59

你不知道的JS系列 ( 39 ) - 对象遍历的相关文章

你不知道的JS系列 ( 33 ) - 对象复制

JS 初学者最常见的问题之一就是如何复制一个对象.看起来应该有一个内置的 copy() 方法,实际上比想象中的更复杂,我们无法选择一个默认的复制算法 function anotherFunction(){/** ... */}; var anotherObject = { c: true }; var anotherArray = []; var myObject = { a: 2, b: anotherObject, // 引用,不是复本! c: anotherArray, // 另一个引用

JS对JSON对象遍历输出的时候真的是按照顺序输出吗?

对象的遍历输出并不是按照对象属性定义顺序来的,那么是按照什么规则来的呢,仔细深入研究你会发现,这还跟浏览器有关系,Chrome跟IE是不一样的,所以给出以下结论: Chrome Opera 的 JavaScript 解析引擎遵循的是新版 ECMA-262 第五版规范.因此,使用 for-in 语句遍历对象属性时遍历书序并非属性构建顺序.而 IE6 IE7 IE8 Firefox Safari 的 JavaScript 解析引擎遵循的是较老的 ECMA-262 第三版规范,属性遍历顺序由属性构建的

你不知道的JS系列 ( 7 ) - 欺骗词法作用域

如果词法作用域完全由写代码期间函数所声明的位置来定义,怎样才能在运行时来“修改”词法作用域呢?有些人喜欢特殊的办法来解决遇到的问题.我们规定词法作用域是代码写在哪里决定的,一旦决定了无法更改,因为一些问题,我们不得不更改作用域,尽管这是不被推荐的,那是什么办法,JavaScript 中有两种机制来实现这个目的 eval function foo(str, a) { eval(str); console.log(a, b) } var b = 2; foo("var b = 3", 1)

你不知道的JS系列 ( 22 ) - this new 绑定

在传统的面向类的语言中,“构造函数“是类中的一些特殊方法,使用 new 初始化类时会调用类中的构造函数.通常的形式是这样的 something = new MyClass(..); 然而 JavaScript 中 new 的机制实际上和面向类的语言不同.它们只是被 new 操作符调用的普通函数而已.实际上并不存在所谓的“构造函数”,只有对于函数的“构造调用” function foo(a) { this.a = a; } var bar = new foo(2); console.log(bar

你不知道的JS系列上( 45 ) - 隐式混入

var Something = { cool: function () { this.greeting = 'Hello World'; this.count = this.count ? this.count + 1 : 1; } } Something.cool(); Something.greeting; // 'Hello World' Something.count; // 1 var Another = { cool: function() { // 隐式把 Something 混入

你不知道的JS系列(2)- 引擎怎么查找变量

对代码进行处理的三个角色 引擎:从头到尾负责整个 JavaScript 程序的编译和执行过程 编译器:负责语法分析及代码生成等 作用域:负责收集并维护所有变量的查询 var a = 2; 编译器首先会将这段程序分解成词法单元,然后将词法单元流解析成一个树结构.然后将树结构转换成可执行代码,也就是计算机懂的指令.为一个变量分配内存,将其命名为 a,然后将值 2 保存进这个变量.这符合编译原理 然而并不完全正确 事实上编译器会进行如下处理 1.在词法分析中,遇到 var a,编译器会询问当前作用域是

你不知道的JS系列 ( 5 ) - 词法作用域

作用域分为两种,一种是词法作用域,一种是动态作用域,我们先看第一种,词法作用域 词法作用域就是定义在词法阶段的作用域(编译器的第一个工作阶段叫做词法化,词法化的过程会对源代码中的字符进行检查).换句话说,词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的.因此词法分析器处理代码时会保持作用域不变 function foo(a) { var b = a * 2; function bar(c){ console.log( a, b, c ); } bar( b * 3 ); } foo(

你不知道的JS系列 ( 12 ) - 声明提升

我们直觉上会认为 JavaScript 代码在执行时是由上到下一行一行执行的.但实际这并不完全正确 a = 2; var a; console.log(a); 这里可能会认为是 undefined,因为 var a 声明在 a = 2 之后.实际输出了 2. console.log(a); var a = 2; 鉴于上面的代码可能会是 2,还有人认为可能会报异常 ReferenceError,不幸这两种猜测都不对,输出来的是 undefined 要搞明白这个,要明白编译的原理,在编译阶段中的一部

你不知道的JS系列 ( 13 ) - 什么是闭包

当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行 function foo(){ var a = 2; function bar() { console.log(a); } return bar } var baz = foo(); baz(); // 2 —— 朋友,这就是闭包的效果 在 foo() 执行后,通常会期待 foo() 的整个内部作用域都被销毁,因为我们知道引擎有垃圾回收用来释放不再使用的内存空间. 而闭包的“神奇”之处正是可以阻止这件事情的