JavaScript は ES2015 以降、デフォルトのパラメーター値をサポートしています。あなたはこれを知っています。私はこれを知っています。私が知らなかったのは、兄弟 パラメータ をデフォルト値自体として使用できるということです。 (あるいは、「隣接する位置パラメーター」かもしれません。これらを何と呼ぶべきかわかりません。)
function myFunc(arg1, arg2 = arg1) { console.log(arg1, arg2); } myFunc("arg1!"); // "arg1!" "arg1!"
これはクラス コンストラクターでも機能します。これは、一部の PicPerf.io コードをよりテストしやすくするのに非常に役立つことがわかりました。この目的のために単純な依存性注入が使用されるのが一般的です。少し詳しく見てみましょう。
画像の最適化のテーマに沿って、OptimizedImage クラスがあるとします。画像の URL をコンストラクターに指定すると、画像の新しく最適化されたバッファーまたはキャッシュされたバージョンのいずれかを取得できます。
class OptimizedImage { constructor( imageUrl: string, cacheService = new CacheService(), optimizeService = new OptimizeService() ) { this.imageUrl = imageUrl; this.cacheService = cacheService; this.optimizeService = optimizeService; } async get() { const cached = this.cacheService.get(this.imageUrl); // Return the previously optimized image. if (cached) return cached; const optimizedImage = await this.optimizeService .optimize(this.imageUrl); // Cache the optimized image for next time. return this.cacheService.put(this.imageUrl, optimizedImage); } } const instance = new OptimizedImage('https://macarthur.me/me.jpg'); const imgBuffer = await instance.get();
運用環境で使用される唯一のコンストラクター パラメーターは imageUrl ですが、CacheService と OptimizeService を挿入すると、モックを使用した単体テストが簡単になります。
import { it, expect, vi } from 'vitest'; import { OptimizedImage } from './main'; it('returns freshly optimized image', async function () { const fakeImageBuffer = new ArrayBuffer('image!'); const mockCacheService = { get: (url) => null, put: vi.fn().mockResolvedValue(fakeImageBuffer), }; const mockOptimizeService = { optimize: (url) => fakeImageBuffer, }; const optimizedImage = new OptimizedImage( 'https://test.jpg', mockCacheService, mockOptimizeService ); const result = await optimizedImage.get(); expect(result).toEqual(fakeImageBuffer); expect(mockCacheService.put).toHaveBeenCalledWith( 'https://test.jpg', 'optimized image' ); });
この例では、これらのサービス クラスは両方とも、特定のメソッドが呼び出された場合にのみ imageUrl を使用します。しかし、代わりにそれを独自のコンストラクターに渡す必要がある場合を想像してください。インスタンス化を OptimizedImage のコンストラクターに取り込みたくなるかもしれません (私はそうでした):
class OptimizedImage { constructor( imageUrl: string ) { this.imageUrl = imageUrl; this.cacheService = new CacheService(imageUrl); this.optimizeService = new OptimizeService(imageUrl); }
それはうまくいきますが、OptimizedImage がサービスのインスタンス化を完全に担当するようになり、テストもさらに面倒になります。サービス インスタンスのモックを渡すのはそれほど簡単ではありません。
モック クラス定義を渡すことでこれを回避できますが、その場合、独自のコンストラクターを使用してそれらのクラスのモック バージョンを作成する必要があり、テストがさらに面倒になります。幸いなことに、引数リストの残りの部分で imageUrl パラメータを使用するという別のオプションがあります。
少し前まで、これが可能であることさえ知りませんでした。それは次のようになります:
export class OptimizedImage { constructor( imageUrl: string, // Use the same `imageUrl` in both dependencies. cacheService = new CacheService(imageUrl), optimizeService = new OptimizeService(imageUrl) ) { this.cacheService = cacheService; this.optimizeService = optimizeService; } async get() { const cached = this.cacheService.get(); // Return the previously optimized image. if (cached) return cached; const optimizedImage = await this.optimizeService.optimize(); // Cache the optimized image for next time. return this.cacheService.put(optimizedImage); } }
この設定を使用すると、以前と同じように簡単にこれらのインスタンスをモックすることができ、クラスの残りの部分は imageUrl 自体のインスタンスを保持する必要さえありません。もちろん、インスタンス化は依然として単純です:
const instance = new OptimizedImage('https://macarthur.me/me.jpg'); const img = await instance.get();
同じテストアプローチもそのまま残ります:
import { it, expect, vi } from 'vitest'; import { OptimizedImage } from './main'; it('returns freshly optimized image', async function () { const mockCacheService = { get: () => null, put: vi.fn().mockResolvedValue('optimized image'), }; const mockOptimizeService = { optimize: () => 'optimized image', }; const optimizedImage = new OptimizedImage( 'https://test.jpg', mockCacheService, mockOptimizeService ); const result = await optimizedImage.get(); expect(result).toEqual('optimized image'); expect(mockCacheService.put).toHaveBeenCalledWith('optimized image'); });
ここには画期的なことは何もありません。私の生活を人間工学的にもう少し快適にしてくれる小さな機能だけです。今後もこのような逸品に出会えることを期待しています。
以上が兄弟パラメータを関数のデフォルト値として使用できるとは知りませんでした。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。