JavaScript `of` 关键字(for...of 循环)

Posted

技术标签:

【中文标题】JavaScript `of` 关键字(for...of 循环)【英文标题】:JavaScript `of` Keyword (for...of loops) 【发布时间】:2014-12-18 23:30:52 【问题描述】:

我刚刚发现 in Firefox SDK javascript (on MDN) 使用了一个我以前从未见过的关键字:

var tabs = require('sdk/tabs');
for (let tab of tabs)
  console.log(tab.title);

of关键字是Mozilla自己编出来的还是标准化的?

【问题讨论】:

ES6 的一部分。谷歌搜索“for of loop ES6”应该会出现一些东西。 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 【参考方案1】:

这是 EcmaScript 6 的一项功能,并非所有现代浏览器都稳定或支持。您需要等待它稳定下来,或者您可以使用像 Traceur 这样的转译器,它将您的 ES6 代码转换为 ES5。

【讨论】:

“不稳定”是什么意思?另外,转码器是另外一回事,也许您正在寻找 transpiler 这个词。 他可以使用var tab in tabs 来支持 pre-es6 吗? 所有浏览器都支持使用var tab in tabs 或换句话说for...in 结构。您可以安全使用。 “不稳定”是指在某些浏览器或某些浏览器的某些版本中添加了该功能,但现在相信它的支持可能不是一个好主意。【参考方案2】:

for...of 循环遍历属性 values,是 added to the JavaScript specification in ECMAScript 2015 的一项功能。

鉴于此问题的上下文是 Firefox 插件,问题不在于它何时或是否在其他浏览器中可用。问题是当这个ECMAScript 2015 feature was added to Firefox 以及使用它导致的向后兼容性的任何限制时。

它已在 Firefox 13 中添加到 Firefox。因此,使用它会导致将您的附加组件限制为 Firefox 13+。鉴于截至 2014 年 10 月的当前版本是 Firefox 33.0,并且在 Firefox 13 和现在之间已经有多个 ESR 版本,使用for...of 循环可能不会显着减少能够使用您的添加的人数-在。您正在使用的某些其他功能可能会将您的插件限制为更新的版本。

使用for...of

与Array.prototype.forEach() 不同,for...of 循环不仅限于数组,还将迭代其他类型的iterable objects,其中包括大量不同类型的对象。

有时让人们感到困惑的一件事是for...of 迭代属性values,而不是属性键。根据您的操作,这可能非常方便,也可以使 for...of 循环不合适。

示例:for..of 迭代 NodeList

const listItems = document.querySelectorAll('li');

for (let item of listItems) 
    console.log('item text:', item.textContent); // "first", "second", "third", "fourth"
<ol>
    <li>first</li>
    <li>second</li>
    <li>third</li>
    <li>fourth</li>
</ol>

普通对象通常不是iterable(不能使用for...of

尝试在普通对象上使用for...of 会引发错误。

const obj =  first: 3, second: 5, third: 7, fourth: "hello" ;

// with Object.keys()

for (let value of obj)  //This is an error. obj is not iterable
    console.log('value:', value);

其他迭代 Object 属性值的方法

Array.prototype.forEach()

如果您正在寻找其他方法来执行类似任务,MDN shows examples 使用 Array.prototype.forEach() 迭代 Arrays 和 Objects 的属性值:

forEach 直接覆盖从 Object.values() 获得的 Object 值:

const obj =  first: 3, second: 5, third: 7, fourth: "hello" ;

// with Object.keys()

Object.values(obj).forEach(function (value) 
    console.log('value:', value); // logs "3", "5", "7", "hello"
);

forEach 通过从 Object.keys() 获得的 Object 的键:

const obj =  first: 3, second: 5, third: 7, fourth: "hello" ;

// with Object.keys()

Object.keys(obj).forEach(function (key) 
    //obj[key] is the property value
    console.log('key:', key);        // logs "first", "second", "third", "fourth"
    console.log('value:', obj[key]); // logs "3", "5", "7", "hello"
);

forEach 覆盖数组的值:

const arr = [ 3, 5, 7 ];

arr.forEach(function (value, index) 
    console.log('value:', value);     // logs "3", "5", "7"
    console.log('index:', index);     // logs "0", "1", "2"
);

for..in

使用for..in 循环的主要缺点是它会迭代对象的enumerable properties,这将包括对象原型上的属性。这可能会导致意外错误。因此,使用Object.prototype.hasOwnProperty() 或其他方法测试循环的键值是否是对象自己的值总是一个好主意,除非您知道要遍历不是的可枚举属性对象自己的属性(您很少想要)。

虽然这不是绝对必要的,但最好使用Object.prototype.hasOwnProperty() 的已知良好副本,因为任何对象都可以有意或无意地定义自己的hasOwnProperty

const obj =  first: 3, second: 5, third: 7, fourth: "hello" ;

// with for..in

for (let key in obj) 
    if (Object.prototype.hasOwnProperty.call(obj, key)) 
        //obj[key] is the property value
        console.log('key:', key); // logs "first", "second", "third", "fourth"
        console.log('value:', obj[key]); // logs "3", "5", "7", "hello"
    

浏览器兼容性:

如果您打算将您的插件移植到其他浏览器,或在网页中使用for...of,那么您应该知道何时将该功能添加到各种浏览器。从Browser Compatibility table on MDN 可以看出,主要问题是 Internet Explorer 不支持它。

这是截至 2018 年 3 月 11 日的compatibility table from MDN:

    Chrome 29–37:for...of 循环功能在首选项后面可用。在 chrome://flags 中,激活“启用实验性 JavaScript”条目。 在 Firefox 51 之前,使用带有 const 关键字的 for...of 循环构造会引发 SyntaxError(“在 const 声明中缺少 =”)。

【讨论】:

非常有用的答案,我不知道它登陆了FF13

以上是关于JavaScript `of` 关键字(for...of 循环)的主要内容,如果未能解决你的问题,请参考以下文章

javascript总for of和for in的区别

译文理解 JavaScript 中的 for…of 循环

javascript总for of和for in的区别?

Javascript 和 Typescript:使用 for..of 对对象进行迭代

JavaScript中for in,for, for of,forEach之间的区别

我可以在 Javascript for...in 和 for...of 循环中使用 continue 和 break 吗?