2015-08-11 32 views
5

Set'in bir alt sınıfını oluşturmaya çalışıyorum ve sadece basitçe genişletemediğimden, işlevselliğini sarar.Symbol.iterator nasıl uygulanır?

Symbol.iterator yöntemini uygulamaya çalışıyorum ancak Akış bunların hiçbirine sahip değil. Ben kolayca bastırmak çünkü

/* @flow */ 
class CSet<T> { 
    _set: Set<T>; 
    [Symbol.iterator](): Iterator<T> { 
     return this._set[Symbol.iterator]; 
    } 
} 

var a: CSet = new CSet(); 
for(var b of a){ 

} 

core.js:309:5,29: property @@iterator 
Property not found in 
test.js:2:7,10: CSet 

test.js:4:2,6:2: 
computed property keys not supported 

ikinci hata bir anlaşma olarak büyük değildir:

Bu

Ben koddur. Merak ediyorum da, hep birlikte yanlış bir şey yapıyorum.

cevap

5

bkz bu javascript kodu deneyin yolu Symbol.iterator temsil hacky ve temelde ön Şu anda kullanıcı alanında yineleyicileri tanımlama yeteneği (destek yalnızca kitaplık tanımlarında çalışır) :(

Özellikle Akış, yinelemenin üzerinde bir @@iterator özelliğine sahip olmasını bekler (ki bu kesinlikle geçerli bir özellik adı değil). kütüphane tanımlarında destek almak için geçici bir hack idi).

Yani doğru sembol destek inene kadar, burada geçici bir çözüm için en iyi bahis Flow'un anlaşılması için bu @@iterator özelliğini kullanan bu modül için bir kütüphane tanımını oluşturmak olacaktır:

// RealModule.js 
export class CSet { 
    [Symbol.iterator]() { 
     return this._set[Symbol.iterator]; 
    } 
} 

.

// RealModule.FlowLibDef.js 
declare module RealModule { 
    declare class CSet<T> { 
     _set: Set<T>; 
     @@iterator(): Iterator<T>; 
    } 
} 
0

Akış şu anda değil semboller için genel destek Çünkü

// module -- start 

let map = new WeakMap(); 

class Foo { 
    constructor(any) { 
    map.set(this, new Set(any)); 
    } 
    values() { 
    return map.get(this).values(); 
    } 
    [Symbol.iterator]() { 
    return this.values(); 
    } 
} 

// module -- end 


for(let item of new Foo([1,2,3])) { 
    console.log(item); 
} 

  1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
  2. sandbox
+0

Kötü, daha spesifik olmalıydım. Bu, Flow'un doğru şekilde kontrol edilmemesi ile ilgilidir. Akış, Değer() işlevine sahip olarak Ayarla'yı dikkate almaz. – Kyle

1

yazıyorum ve tüm sınıf için bir paralel libdef bakımını yapması gerekmeden, sen iterable olarak kullanıcı tanımlı sınıf işaretlemek sağlayan bir hile buldum.

anahtar [Symbol.iterator]() uygulayan özel bir üst sınıfı yazmak ve sadece bu üst sınıfı için libdef sağlamaktır: Şimdi

// IterableBase.js 
export default class IterableBase { 
    [Symbol.iterator]() { 
    return this._Symbol_iterator(); 
    } 
} 
// IterableBase.js.flow 
// @flow 
declare class IterableBase<T> { 
    @@iterator(): Iterator<T>; 
} 
export default IterableBase; 

size özel sınıf IterableBase genişletmek ve yerine uygulamak olabilir yöntem adı:

// RealModule.js 
// @flow 
import IterableBase from './IterableBase'; 

class CSet<T> extends IterableBase<T> { 
    _Symbol_iterator(): Iterator<T> { 
    ... 
    } 
} 

Bu kesinlikle bir kesmek, b Bu alternatiften daha kolay ve daha güvenli olmalıdır.

2
// @flow 
class MyCollection<T> { 
    /*:: @@iterator(): Iterator<T> { return ({}: any); } */ 

    // $FlowFixMe: computed property 
    [Symbol.iterator](): Iterator<T> { 
     // NOTE: this could just as easily return a different implementation 
     return new MyIterator(this); 
    } 
} 

class MyIterator<+T> { 
    /*:: @@iterator(): Iterator<T> { return (this: any); } */ 

    // $FlowFixMe: computed property 
    [Symbol.iterator](): Iterator<T> { 
     return this; 
    } 

    next(): IteratorResult<T, void> { 
     return { done: false, value: someT }; 
     // or return { done: true, value: undefined }; 
    } 
} 

for (const value of new MyCollection()) { 
    console.log(value); 
} 

bu nedenle aslında kod etkilemez zamanında dışarı yorumladı olması dışında bu kaynakta akış kodu sanki /*:: code */ bu akış, yorumlayan olduğunu çalışır sebep.geçerli JavaScript olmama rağmen Akış içsel, @@iterator yöntem bildiği

, böylece biz, mevcut bir Iterator<T> dönen, ve bunun için çalışan bir değer (any olarak, yani boş bir nesne döküm) dönen olarak tanımlar. Hesaplanan özellik yöntemi, tümüyle tanımlanmamış gibi, akış tarafından tamamen yok sayılır. Geçerli bir Iterator<T> yöntemini aslında döndürmeniz çok önemlidir, aksi halde işler çalışma zamanında bozulur.