2022.12.17 前端周刊

151 阅读4分钟

1. SvelteKit 1.0发布

经过两年的开发,SvelteKit1.0终于发布,可以用于生产环境的开发了。

SvelteKit是一个基于Svelte的框架,为用户提供SSR等功能,SvelteKit之于Svelte,就像nuxt之于vue,next.js之于React。

如果不了解Svelte,这里有一篇很好的文章推荐大家看一看:新兴前端框架 Svelte 从入门到原理

2. ECMAScript proposal——Iterator Healpers 和 Set Methods

ECMAScript有了新提案,关于Iterator Healpers和Set Methods。

2.1 Iterator Healpers

Iterator Healpers有一个很主要的变动,目前可迭代对象(iterable)是主要的迭代角色(iteration role), 而新提案中,iterator是主要的迭代角色。这个提案引入了两个新的class——Iterator和AsyncIterator,他们会分别返回iterator和asynchronous iterators,而以下是一些关于Iterator和iterator的方法介绍(没有全部说,摘了部分,想了解更多可以看原文,且只介绍了同步的iterator,异步的类似,也不说了,具体看原文吧)

方法介绍

Iterator.from(x)

该方法会返回Iterator类型的对象。懒得翻译了,放原文:

If x is a synchronous API iterable, it returns x[Symbol.iterator]().

If x is a synchronous API iterator, it returns x unchanged.

If x is a synchronous legacy iterator (that doesn’t support the new API), it wraps it so that it supports the new API and returns the result.

If x is a synchronous legacy iterable, it wraps the result of x[Symbol.iterator]() and returns it.

iterator.take(limit)

该方法会将你指定的iterator中的子元素以iterator的形式返回。举个🌰

// 以这个iterator为例,后面举的例子都用它
function* createSyncIterator() {
  yield 'a'; yield 'b'; yield 'c'; yield 'd';
}
createSyncIterator().take(1).toArray() // 返回结果为['a]

iterator.drop(limit)

该方法会返回含有除了你指定iterator子元素以外的其他子元素的iterator,🌰:

createSyncIterator().drop(1).toArray() // 返回结果为['b', 'c', 'd']

iterator.toAsync()

该方法可以基于一个同步iterator,生成一个异步iterator, 🌰:

  createSyncIterator() instanceof AsyncIterator // 返回false
  createSyncIterator().toAsync() instanceof AsyncIterator // 返回true

旧版可迭代对象要如何使用新的API呢?

以下面这个手写的可迭代对象为例:

class MyIterable {
  #values;
  #index = 0;
  constructor(...values) {
    this.#values = values;
  }
  [Symbol.iterator]() {
    return {
      // Arrow function so that we can use the outer `this`
      next: () => {
        if (this.#index >= this.#values.length) {
          return {done: true};
        }
        const value = this.#values[this.#index];
        this.#index++;
        return {done: false, value};
      },
    };
  }
}
Array.from(new MyIterable('a', 'b', 'c')) // 返回['a', 'b', 'c']

有两种方案:

  • 通过Iterator.from()方法,将旧版可迭代对象转为API iterator,🌰:
      class MyIterable {
        // ···
        [Symbol.iterator]() {
          return Iterator.from({
            next: () => {
              // ···
            },
          });
        }
      }
    
  • 使该可迭代对象 instance of Iterator
     class MyIterable {
       // ···
       [Symbol.iterator]() {
         return {
           __proto__: Iterator.prototype,
           next: () => {
             // ···
           },
         };
       }
     }
    

如何统一新旧iteration styles的冲突

冲突在哪里

旧iteration styles:

  • 迭代对象是主要的迭代角色
  • 代码操纵的都是可迭代对象,对于程序员来说他们是无法直接操作iterator的
  • 该style也被用于Java和Python

新iteration styles:

  • 迭代器是主要的迭代角色,除了旧版代码,API不再应用于可迭代对象上。
  • 该style也被用于Rust

目前考虑有两种处理冲突的方式

  1. 统一使用可迭代对象,通过Iterator.from()把可迭代对象做个包装,就类似jquery那种。
  2. 统一使用iterator,前提是编程语言能够接受iterator(比如Functions和methods需要接受iterator,而非可迭代对象,特别是ts),通过Iterator.from()来将数据结构转换为合适的iterator

2.2 Set methods

新增方法

set.union(other)

该方法会返回this和other两个集合的并集, 🌰:

new Set(['a', 'b', 'c']).union(new Set(['c', 'd'])) // 结果为['a', 'b', 'c', 'd']

set.intersection(other)

该方法会返回this和other两个集合的交集, 🌰:

new Set(['a', 'b', 'c']).intersection(new Set(['c', 'd'])) // 结果为['c']

set.difference(other)

该方法会返回this集合中与other不同的子集, 🌰:

new Set(['a', 'b', 'c']).difference(new Set(['c', 'd'])) // 结果为['c', 'b']

set.symmetricDifference(other)

该方法会返回this和other中除了相同元素外其他元素构成的集合

  new Set(['a', 'b', 'c']).symmetricDifference(new Set(['c', 'd'])) // 结果为['a', 'b', 'd']

set.isSubsetOf(other)

当this是other的子集时,该方法返回true

  new Set(['a', 'b']).isSubsetOf(new Set(['a', 'b', 'c'])) // true

set.isSupersetOf(other) 

当other是this子集时,该方法返回true

set.isDisjointFrom(other)

当this和other不相交时, 返回true

  new Set(['a', 'b', 'c']).isDisjointFrom(new Set(['x'])) // true
  new Set(['a', 'b', 'c']).isDisjointFrom(new Set(['c', 'd'])) // false

this和other的规则

Set方法中对this和other有以下要求:

  • this必须为Set
  • other必须继承SetReadOperations接口,接口如下:
interface SetReadOperations<T> {
  /** Can be `Infinity` (see next section). */
  size: number;
  
  has(key: T): boolean;

  /** Returns an iterator for the elements in `this`. */
  keys(): Iterator<T>; // only method `.next()` is required
}

支持无限大小的set-like数据

other的.size可以是Infinity, 除了union和symmetricDifference两个方法,都支持size为infinite的数据