JavaScript` of`关键字(for ... of loops)

Nic*_*ler 8 javascript firefox-addon firefox-addon-sdk

我刚刚发现,在Firefox SDK JavaScript(在MDN上),使用了我从未见过的关键字:

var tabs = require('sdk/tabs');
for (let tab of tabs)
  console.log(tab.title);
Run Code Online (Sandbox Code Playgroud)

of关键字由由Mozilla抑或是标准化?

Mak*_*yen 15

for...of循环,它在属性迭代,是一种功能添加到JavaScript规范ECMAScript中2015.

鉴于此问题的上下文是Firefox附加组件,问题不在于或是否在其他浏览器中可用.问题是当这个ECMAScript 2015功能被添加到Firefox时,以及使用它的后向兼容性的任何限制.

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

运用 for...of

Array.prototype.forEach()不同,for...of循环不仅限于Arrays,而是迭代其他类型的可迭代对象,其中包括大量不同类型的对象.

有时让人困惑的一件事是for...of迭代属性,而不是属性键.根据你正在做的事情,这可能非常方便,使得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"
}
Run Code Online (Sandbox Code Playgroud)
<ol>
    <li>first</li>
    <li>second</li>
    <li>third</li>
    <li>fourth</li>
</ol>
Run Code Online (Sandbox Code Playgroud)

普通对象通常不可迭代(不能使用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);
}
Run Code Online (Sandbox Code Playgroud)

迭代Object属性值的其他方法

Array.prototype.forEach()

如果您正在寻找执行类似任务的其他方法,MDN会显示使用Array.prototype.forEach()迭代ArraysObjects的属性值的示例:

forEach直接在Object的值上获得的形式Object.values():

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"
});
Run Code Online (Sandbox Code Playgroud)

forEach通过对象的密钥获得形式Object.keys():

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"
});
Run Code Online (Sandbox Code Playgroud)

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"
});
Run Code Online (Sandbox Code Playgroud)

for..in

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

虽然这不是绝对必要的,但是使用已知良好的副本是个好主意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"
    }
}
Run Code Online (Sandbox Code Playgroud)

浏览器兼容性

如果您打算将加载项移植到其他浏览器或for...of在网页中使用,那么您应该知道该功能何时添加到各种浏览器中.可以在MDN上浏览器兼容性表中看到,主要问题是Internet Explorer不支持它.

这是MDN截至2018-03-11 的兼容性表:

浏览器兼容性

  1. Chrome 29-37:for...of循环功能可在首选项后面使用.在chrome:// flags中,激活"启用实验JavaScript"条目.
  2. 在Firefox 51之前,使用for...of带有const关键字的循环结构抛出了一个SyntaxError("missing = in const declaration").