TSConfig文件详解18

2024-07-03  本文已影响0人  从零开始学ArchLinux

编译器配置项-compilerOptions

输出相关配置项02

降级迭代-downlevelIteration

降级是 TypeScript 的术语,表示转换为旧版 JavaScript。downlevelIteration选项是为了支持现代JavaScript的迭代概念能够更准确地在旧版 JavaScript 中运行。

ECMAScript 6 添加了几个新的迭代语法:for / of 循环(for (el of arr))、数组展开([a, ...b])、参数展开(fn(...args))和 Symbol.iterator。如果存在 Symbol.iterator已经被实现,则 downlevelIteration 允许在 ES5 环境中更准确地使用这些迭代原语。

示例1:在for/of语法中的作用

有以下TypeScript 代码:

const str = "Hello!";
for (const s of str) {
  console.log(s);
}

未启用downlevelIteration时,一个在Object上的for/of循环将降级为传统的for循环:

"use strict";
var str = "Hello!";
for (var _i = 0, str_1 = str; _i < str_1.length; _i++) {
    var s = str_1[_i];
    console.log(s);
}

这通常是人们所期望的,但它并不 100% 符合 ECMAScript 迭代协议。某些字符串,例如表情符号 (😜),其 .length 为 2(甚至更大!),但在 for-of 循环中应作为 1 个单位进行迭代。有关更详细的解释,请参阅 Jonathan New 的这篇博文

启用downlevelIteration后,TypeScript 将使用辅助函数检查Symbol.iterator实现(原生或 polyfill)。如果缺少此实现,您将回退到基于索引的迭代。

"use strict";
var __values = (this && this.__values) || function(o) {
    var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
    if (m) return m.call(o);
    if (o && typeof o.length === "number") return {
        next: function () {
            if (o && i >= o.length) o = void 0;
            return { value: o && o[i++], done: !o };
        }
    };
    throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
var e_1, _a;
var str = "Hello!";
try {
    for (var str_1 = __values(str), str_1_1 = str_1.next(); !str_1_1.done; str_1_1 = str_1.next()) {
        var s = str_1_1.value;
        console.log(s);
    }
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
    try {
        if (str_1_1 && !str_1_1.done && (_a = str_1.return)) _a.call(str_1);
    }
    finally { if (e_1) throw e_1.error; }
}

可以通过tslib中的importHelpers减少内联 JavaScript 的数量:

"use strict";
var __values = (this && this.__values) || function(o) {
    var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
    if (m) return m.call(o);
    if (o && typeof o.length === "number") return {
        next: function () {
            if (o && i >= o.length) o = void 0;
            return { value: o && o[i++], done: !o };
        }
    };
    throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
var e_1, _a;
var str = "Hello!";
try {
    for (var str_1 = __values(str), str_1_1 = str_1.next(); !str_1_1.done; str_1_1 = str_1.next()) {
        var s = str_1_1.value;
        console.log(s);
    }
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
    try {
        if (str_1_1 && !str_1_1.done && (_a = str_1.return)) _a.call(str_1);
    }
    finally { if (e_1) throw e_1.error; }
}

注意: 如果运行时不存在Symbol.iterator,那么启用downlevelIteration并不能提高合规性。

示例2:展开数组上的作用

下边是展开数组的一个示例:

// Make a new array whose elements are 1 followed by the elements of arr2
const arr = [1, ...arr2];

根据描述,降级到 ES5 听起来很容易:

// The same, right?
const arr = [1].concat(arr2);

但是,在某些罕见情况下,情况会有所不同。

例如,如果源数组缺少一个或多个的空元素,则扩展语法会将每个空元素替换为undefined,而.concat则会保留它们。

// Make an array where the element at index 1 is missing
let arrayWithHole = ["a", , "c"];
let spread = [...arrayWithHole];
let concatenated = [].concat(arrayWithHole);
console.log(arrayWithHole);
// [ 'a', <1 empty item>, 'c' ]
console.log(spread);
// [ 'a', undefined, 'c' ]
console.log(concatenated);
// [ 'a', <1 empty item>, 'c' ]

for / of语法一样,启用downlevelIteration将使用Symbol.iterator (如果存在) 来更准确地模拟 ES 6 行为

上一篇下一篇

猜你喜欢

热点阅读