JavaScriptã¢ãžã¥ãŒã«ã§å€ãªããžã§ã¯ããæŽ»çšããå ç¢ã§ä¿å®ã»ãã¹ãããããã³ãŒããå®çŸããŸããäžå€ããŒã¿æ§é ã®å®è£ ãšããŒã¿æŽåæ§ãé«ããæ¹æ³ãåŠã³ãŸãããã
JavaScriptã¢ãžã¥ãŒã«å€ãªããžã§ã¯ãïŒäžå€ãªããŒã¿ã¢ããªã³ã°
çŸä»£ã®JavaScriptéçºã«ãããŠãããŒã¿ã®æŽåæ§ãšä¿å®æ§ã確ä¿ããããšã¯æãéèŠã§ãããããéæããããã®åŒ·åãªææ³ã®1ã€ããã¢ãžã¥ãŒã«åãããJavaScriptã¢ããªã±ãŒã·ã§ã³å ã§å€ãªããžã§ã¯ããæŽ»çšããããšã§ããå€ãªããžã§ã¯ãã¯ãç¹ã«äžå€æ§ïŒã€ãã¥ãŒã¿ããªãã£ïŒãšçµã¿åãããããšã§ãããã¯ãªãŒã³ã§äºæž¬å¯èœããããŠãã¹ãããããã³ãŒãã«ã€ãªããå ç¢ãªããŒã¿ã¢ããªã³ã°ã®ã¢ãããŒããæäŸããŸãã
å€ãªããžã§ã¯ããšã¯ïŒ
å€ãªããžã§ã¯ãã¯ãæŠå¿µçãªå€ã衚çŸããå°ããåçŽãªãªããžã§ã¯ãã§ããã¢ã€ãã³ãã£ãã£ã«ãã£ãŠå®çŸ©ããããšã³ãã£ãã£ãšã¯ç°ãªããå€ãªããžã§ã¯ãã¯ãã®å±æ§ã«ãã£ãŠå®çŸ©ãããŸãã2ã€ã®å€ãªããžã§ã¯ãã¯ããªããžã§ã¯ãã®ã¢ã€ãã³ãã£ãã£ã«é¢ä¿ãªãããã®å±æ§ãçãããã°çãããšèŠãªãããŸããå€ãªããžã§ã¯ãã®äžè¬çãªäŸã«ã¯ä»¥äžã®ãããªãã®ããããŸãïŒ
- é貚 (Currency): ééç䟡å€ã衚ããŸãïŒäŸïŒUSD 10, EUR 5ïŒã
- æé (Date Range): éå§æ¥ãšçµäºæ¥ã衚ããŸãã
- ã¡ãŒã«ã¢ãã¬ã¹ (Email Address): æå¹ãªã¡ãŒã«ã¢ãã¬ã¹ã衚ããŸãã
- éµäŸ¿çªå· (Postal Code): ç¹å®ã®å°åã®æå¹ãªéµäŸ¿çªå·ã衚ããŸããïŒäŸïŒç±³åœã®90210ãè±åœã®SW1A 0AAããã€ãã®10115ãæ¥æ¬ã®ã100-0001ïŒ
- é»è©±çªå· (Phone Number): æå¹ãªé»è©±çªå·ã衚ããŸãã
- åº§æš (Coordinates): å°ççãªäœçœ®ïŒç·¯åºŠãšçµåºŠïŒã衚ããŸãã
å€ãªããžã§ã¯ãã®äž»ãªç¹åŸŽã¯ä»¥äžã®éãã§ãïŒ
- äžå€æ§ (Immutability): äžåºŠäœæããããšãå€ãªããžã§ã¯ãã®ç¶æ ã¯å€æŽã§ããŸãããããã«ãããæå³ããªãå¯äœçšã®ãªã¹ã¯ãæé€ãããŸãã
- å€ã«åºã¥ãç䟡æ§: 2ã€ã®å€ãªããžã§ã¯ãã¯ãã¡ã¢ãªäžã§åããªããžã§ã¯ãã§ãããã©ããã§ã¯ãªãããã®å€ãçããå Žåã«çãããšãããŸãã
- ã«ãã»ã«å (Encapsulation): å€ã®å éšè¡šçŸã¯é èœãããã¡ãœãããéããŠã¢ã¯ã»ã¹ãæäŸãããŸããããã«ãããæ€èšŒãå¯èœã«ãªããå€ã®å®å šæ§ãä¿èšŒãããŸãã
ãªãå€ãªããžã§ã¯ãã䜿ãã®ãïŒ
JavaScriptã¢ããªã±ãŒã·ã§ã³ã§å€ãªããžã§ã¯ããæ¡çšããããšã«ã¯ãããã€ãã®éèŠãªå©ç¹ããããŸãïŒ
- ããŒã¿æŽåæ§ã®åäž: å€ãªããžã§ã¯ãã¯äœææã«å¶çŽãæ€èšŒã«ãŒã«ã匷å¶ã§ãããããæå¹ãªããŒã¿ã®ã¿ã䜿çšãããããšãä¿èšŒããŸããäŸãã°ã`EmailAddress`å€ãªããžã§ã¯ãã¯ãå ¥åæååãå®éã«æå¹ãªã¡ãŒã«åœ¢åŒã§ããããšãæ€èšŒã§ããŸããããã«ããããšã©ãŒãã·ã¹ãã å šäœã«äŒæããå¯èœæ§ãæžãããŸãã
- å¯äœçšã®åæž: äžå€æ§ã«ãããå€ãªããžã§ã¯ãã®ç¶æ ãæå³ãã倿Žãããå¯èœæ§ããªããªããããäºæž¬å¯èœã§ä¿¡é Œæ§ã®é«ãã³ãŒãã«ãªããŸãã
- ãã¹ãã®ç°¡çŽ å: å€ãªããžã§ã¯ãã¯äžå€ã§ããããã®ç䟡æ§ã¯å€ã«åºã¥ããŠããããããŠããããã¹ããã¯ããã«ç°¡åã«ãªããŸããæ¢ç¥ã®å€ãæã€å€ãªããžã§ã¯ããäœæããæåŸ ãããçµæãšæ¯èŒããã ãã§ãã
- ã³ãŒãã®æç¢ºæ§ã®åäž: å€ãªããžã§ã¯ãã¯ãã¡ã€ã³ã®æŠå¿µãæç€ºçã«è¡šçŸããããšã§ãã³ãŒãããã衚çŸè±ãã§çè§£ããããããŸããçã®æååãæ°å€ãæž¡ã代ããã«ã`Currency`ã`PostalCode`ã®ãããªå€ãªããžã§ã¯ãã䜿çšããããšã§ãã³ãŒãã®æå³ãããæç¢ºã«ãªããŸãã
- ã¢ãžã¥ãŒã«æ§ã®åŒ·å: å€ãªããžã§ã¯ãã¯ç¹å®ã®å€ã«é¢é£ããããžãã¯ãã«ãã»ã«åããé¢å¿ã®åé¢ãä¿é²ããã³ãŒããããã¢ãžã¥ãŒã«åããŸãã
- ã³ã©ãã¬ãŒã·ã§ã³ã®æ¹å: æšæºçãªå€ãªããžã§ã¯ãã䜿çšããããšã§ãããŒã éã§ã®å ±éçè§£ãä¿é²ãããŸããäŸãã°ã誰ãããé貚ããªããžã§ã¯ããäœã衚ãããçè§£ããŠããŸãã
JavaScriptã¢ãžã¥ãŒã«ã§ã®å€ãªããžã§ã¯ãã®å®è£
ESã¢ãžã¥ãŒã«ã䜿çšããŠãäžå€æ§ãšé©åãªã«ãã»ã«åã«çŠç¹ãåœãŠãªãããJavaScriptã§å€ãªããžã§ã¯ããå®è£ ããæ¹æ³ãæ¢ã£ãŠã¿ãŸãããã
äŸïŒEmailAddresså€ãªããžã§ã¯ã
ç°¡åãª`EmailAddress`å€ãªããžã§ã¯ããèããŠã¿ãŸããããã¡ãŒã«åœ¢åŒãæ€èšŒããããã«æ£èŠè¡šçŸã䜿çšããŸãã
```javascript // email-address.js const EMAIL_REGEX = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/; class EmailAddress { constructor(value) { if (!EmailAddress.isValid(value)) { throw new Error('Invalid email address format.'); } // Private property (using closure) let _value = value; this.getValue = () => _value; // Getter // Prevent modification from outside the class Object.freeze(this); } getValue() { return this.value; } toString() { return this.getValue(); } static isValid(value) { return EMAIL_REGEX.test(value); } equals(other) { if (!(other instanceof EmailAddress)) { return false; } return this.getValue() === other.getValue(); } } export default EmailAddress; ```解説ïŒ
- ã¢ãžã¥ãŒã«ãšã¯ã¹ããŒã: `EmailAddress`ã¯ã©ã¹ã¯ã¢ãžã¥ãŒã«ãšããŠãšã¯ã¹ããŒããããã¢ããªã±ãŒã·ã§ã³ã®ããŸããŸãªéšåã§åå©çšå¯èœã«ãªããŸãã
- æ€èšŒ: ã³ã³ã¹ãã©ã¯ã¿ã¯æ£èŠè¡šçŸïŒ`EMAIL_REGEX`ïŒã䜿çšããŠå ¥åãããã¡ãŒã«ã¢ãã¬ã¹ãæ€èšŒããŸããã¡ãŒã«ãç¡å¹ãªå Žåããšã©ãŒãã¹ããŒããŸããããã«ãããæå¹ãª`EmailAddress`ãªããžã§ã¯ãã®ã¿ãäœæãããããšãä¿èšŒãããŸãã
- äžå€æ§: `Object.freeze(this)`ã¯ã`EmailAddress`ãªããžã§ã¯ããäœæãããåŸã®å€æŽãé²ããŸããåçµããããªããžã§ã¯ãã倿Žããããšãããšãšã©ãŒãçºçããŸãããŸããã¯ããŒãžã£ã䜿çšããŠ`_value`ããããã£ãé èœããã¯ã©ã¹ã®å€éšããçŽæ¥ã¢ã¯ã»ã¹ã§ããªãããã«ããŠããŸãã
- `getValue()` ã¡ãœãã: `getValue()`ã¡ãœããã¯ãåºã«ãªãã¡ãŒã«ã¢ãã¬ã¹ã®å€ãžã®å¶åŸ¡ãããã¢ã¯ã»ã¹ãæäŸããŸãã
- `toString()` ã¡ãœãã: `toString()`ã¡ãœããã«ãããå€ãªããžã§ã¯ããç°¡åã«æååã«å€æã§ããŸãã
- `isValid()` éçã¡ãœãã: éçãª`isValid()`ã¡ãœããã䜿çšãããšãã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãäœæããã«ãæååãæå¹ãªã¡ãŒã«ã¢ãã¬ã¹ã§ãããã©ããã確èªã§ããŸãã
- `equals()` ã¡ãœãã: `equals()`ã¡ãœããã¯ã2ã€ã®`EmailAddress`ãªããžã§ã¯ãããã®å€ã«åºã¥ããŠæ¯èŒããç䟡æ§ããªããžã§ã¯ãã®ã¢ã€ãã³ãã£ãã£ã§ã¯ãªãå 容ã«ãã£ãŠæ±ºå®ãããããšãä¿èšŒããŸãã
䜿çšäŸ
```javascript // main.js import EmailAddress from './email-address.js'; try { const email1 = new EmailAddress('test@example.com'); const email2 = new EmailAddress('test@example.com'); const email3 = new EmailAddress('invalid-email'); // This will throw an error console.log(email1.getValue()); // Output: test@example.com console.log(email1.toString()); // Output: test@example.com console.log(email1.equals(email2)); // Output: true // Attempting to modify email1 will throw an error (strict mode required) // email1.value = 'new-email@example.com'; // Error: Cannot assign to read only property 'value' of object '#å®èšŒãããå©ç¹
ãã®äŸã¯ãå€ãªããžã§ã¯ãã®åºæ¬ååã瀺ããŠããŸãïŒ
- æ€èšŒ: `EmailAddress`ã³ã³ã¹ãã©ã¯ã¿ã¯ã¡ãŒã«åœ¢åŒã®æ€èšŒã匷å¶ããŸãã
- äžå€æ§: `Object.freeze()`ã®åŒã³åºãã倿Žãé²ããŸãã
- å€ã«åºã¥ãç䟡æ§: `equals()`ã¡ãœããã¯ã¡ãŒã«ã¢ãã¬ã¹ããã®å€ã«åºã¥ããŠæ¯èŒããŸãã
é«åºŠãªèæ ®äºé
TypeScript
åã®äŸã§ã¯ãã¬ãŒã³ãªJavaScriptã䜿çšããŸããããTypeScriptã¯å€ãªããžã§ã¯ãã®éçºãšå ç¢æ§ãå€§å¹ ã«åäžãããããšãã§ããŸããTypeScriptã䜿çšãããšãå€ãªããžã§ã¯ãã®åãå®çŸ©ã§ããã³ã³ãã€ã«æã®åãã§ãã¯ãšã³ãŒãã®ä¿å®æ§ã®åäžãæäŸãããŸãã以äžã¯ãTypeScriptã䜿çšããŠ`EmailAddress`å€ãªããžã§ã¯ããå®è£ ããæ¹æ³ã§ãïŒ
```typescript // email-address.ts const EMAIL_REGEX = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/; class EmailAddress { private readonly value: string; constructor(value: string) { if (!EmailAddress.isValid(value)) { throw new Error('Invalid email address format.'); } this.value = value; Object.freeze(this); } getValue(): string { return this.value; } toString(): string { return this.value; } static isValid(value: string): boolean { return EMAIL_REGEX.test(value); } equals(other: EmailAddress): boolean { return this.value === other.getValue(); } } export default EmailAddress; ```TypeScriptã«ããäž»ãªæ¹åç¹ïŒ
- åå®å šæ§: `value`ããããã£ã¯æç€ºçã«`string`ãšããŠåä»ããããã³ã³ã¹ãã©ã¯ã¿ã¯æååã®ã¿ãæž¡ãããããšã匷å¶ããŸãã
- èªã¿åãå°çšããããã£: `readonly`ããŒã¯ãŒãã¯ã`value`ããããã£ãã³ã³ã¹ãã©ã¯ã¿å ã§ã®ã¿ä»£å ¥å¯èœã§ããããšãä¿èšŒããäžå€æ§ãããã«åŒ·åããŸãã
- ã³ãŒãè£å®ãšãšã©ãŒæ€åºã®åäž: TypeScriptã¯ããè¯ãã³ãŒãè£å®ãæäŸããéçºäžã«åé¢é£ã®ãšã©ãŒããã£ããããã®ã«åœ¹ç«ã¡ãŸãã
颿°åããã°ã©ãã³ã°ã®ææ³
颿°åããã°ã©ãã³ã°ã®ååã䜿çšããŠå€ãªããžã§ã¯ããå®è£ ããããšãã§ããŸãããã®ã¢ãããŒãã§ã¯ã颿°ã䜿çšããŠäžå€ã®ããŒã¿æ§é ãäœæããã³æäœããããšããããããŸãã
```javascript // currency.js import { isNil, isNumber, isString } from 'lodash-es'; function Currency(amount, code) { if (!isNumber(amount)) { throw new Error('Amount must be a number'); } if (!isString(code) || code.length !== 3) { throw new Error('Code must be a 3-letter string'); } const _amount = amount; const _code = code.toUpperCase(); return Object.freeze({ getAmount: () => _amount, getCode: () => _code, toString: () => `${_code} ${_amount}`, equals: (other) => { if (isNil(other) || typeof other.getAmount !== 'function' || typeof other.getCode !== 'function') { return false; } return other.getAmount() === _amount && other.getCode() === _code; } }); } export default Currency; // Example // const price = Currency(19.99, 'USD'); ```解説ïŒ
- ãã¡ã¯ããªé¢æ°: `Currency`颿°ã¯ãã¡ã¯ããªãšããŠæ©èœããäžå€ã®ãªããžã§ã¯ããäœæããŠè¿ããŸãã
- ã¯ããŒãžã£: `_amount`ãš`_code`倿°ã¯é¢æ°ã®ã¹ã³ãŒãå ã«éã蟌ããããå€éšããã¢ã¯ã»ã¹ã§ããªããªããŸãã
- äžå€æ§: `Object.freeze()`ã¯ãè¿ããããªããžã§ã¯ãã倿Žã§ããªãããšãä¿èšŒããŸãã
ã·ãªã¢ã©ã€ãºãšãã·ãªã¢ã©ã€ãº
å€ãªããžã§ã¯ããæ±ãéãç¹ã«åæ£ã·ã¹ãã ãããŒã¿ä¿åæã«ã¯ãããããã·ãªã¢ã©ã€ãºïŒJSONã®ãããªæåå圢åŒã«å€æïŒãããã·ãªã¢ã©ã€ãºïŒæåå圢åŒããå€ãªããžã§ã¯ãã«æ»ãïŒããå¿ èŠãé »ç¹ã«ãããŸããJSONã·ãªã¢ã©ã€ãºã䜿çšããå Žåãéåžžã¯å€ãªããžã§ã¯ãã衚çŸããçã®ïŒ`string`衚çŸã`number`衚çŸãªã©ã®ïŒå€ãååŸããŸãã
ãã·ãªã¢ã©ã€ãºããéã«ã¯ãåžžã«ã³ã³ã¹ãã©ã¯ã¿ã䜿çšããŠå€ãªããžã§ã¯ãã®ã€ã³ã¹ã¿ã³ã¹ãåäœæããæ€èšŒãšäžå€æ§ã匷å¶ããããã«ããŠãã ããã
```javascript // Serialization const email = new EmailAddress('test@example.com'); const emailJSON = JSON.stringify(email.getValue()); // Serialize the underlying value console.log(emailJSON); // Output: "test@example.com" // Deserialization const deserializedEmail = new EmailAddress(JSON.parse(emailJSON)); // Re-create the Value Object console.log(deserializedEmail.getValue()); // Output: test@example.com ```å®äžçã§ã®äŸ
å€ãªããžã§ã¯ãã¯æ§ã ãªã·ããªãªã§é©çšã§ããŸãïŒ
- Eã³ããŒã¹: `Currency`å€ãªããžã§ã¯ãã䜿çšããŠååã®äŸ¡æ Œã衚çŸããäžè²«ããé貚åŠçãä¿èšŒããã`SKU`å€ãªããžã§ã¯ãã§ååã®SKUãæ€èšŒããã
- éèã¢ããªã±ãŒã·ã§ã³: `Money`ã`AccountNumber`å€ãªããžã§ã¯ãã§éé¡ãå£åº§çªå·ãæ±ããæ€èšŒã«ãŒã«ã匷å¶ãããšã©ãŒãé²ãã
- å°çã¢ããªã±ãŒã·ã§ã³: `Coordinates`å€ãªããžã§ã¯ãã§åº§æšã衚çŸãã緯床ãšçµåºŠã®å€ãæå¹ãªç¯å²å ã«ããããšãä¿èšŒããã`CountryCode`å€ãªããžã§ã¯ãã§åœã衚çŸããïŒäŸïŒãUSãããGBãããDEãããJPãããBRãïŒã
- ãŠãŒã¶ãŒç®¡ç: å°çšã®å€ãªããžã§ã¯ãã䜿çšããŠã¡ãŒã«ã¢ãã¬ã¹ãé»è©±çªå·ãéµäŸ¿çªå·ãæ€èšŒããã
- ç©æµ: `Address`å€ãªããžã§ã¯ãã§é éå äœæãæ±ããå¿ é ãã£ãŒã«ãããã¹ãŠååšããæå¹ã§ããããšãä¿èšŒããã
ã³ãŒããè¶ ããå©ç¹
- ã³ã©ãã¬ãŒã·ã§ã³ã®åäž: å€ãªããžã§ã¯ãã¯ãããŒã ãšãããžã§ã¯ãå ã§å ±æã®èªåœãå®çŸ©ããŸãã誰ãã`PostalCode`ã`PhoneNumber`ãäœã衚ãããçè§£ããŠããã°ãã³ã©ãã¬ãŒã·ã§ã³ã¯å€§å¹ ã«åäžããŸãã
- ãªã³ããŒãã£ã³ã°ã®å®¹æå: æ°ããããŒã ã¡ã³ããŒã¯ãåå€ãªããžã§ã¯ãã®ç®çãšå¶çŽãçè§£ããããšã§ããã¡ã€ã³ã¢ãã«ãè¿ éã«ææ¡ã§ããŸãã
- èªç¥çè² è·ã®è»œæž: è€éãªããžãã¯ãšæ€èšŒãå€ãªããžã§ã¯ãå ã«ã«ãã»ã«åããããšã§ãéçºè ã¯ããé«ã¬ãã«ã®ããžãã¹ããžãã¯ã«éäžã§ããããã«ãªããŸãã
å€ãªããžã§ã¯ãã®ãã¹ããã©ã¯ãã£ã¹
- å°ãããçŠç¹ãçµã: å€ãªããžã§ã¯ãã¯ãåäžã®æç¢ºã«å®çŸ©ãããæŠå¿µã衚ãã¹ãã§ãã
- äžå€æ§ã匷å¶ãã: äœæåŸã«å€ãªããžã§ã¯ãã®ç¶æ ã倿Žãããã®ãé²ããŸãã
- å€ã«åºã¥ãç䟡æ§ãå®è£ ãã: 2ã€ã®å€ãªããžã§ã¯ãã®å€ãçããå Žåã«ãããããçãããšèŠãªãããããã«ããŸãã
- `toString()`ã¡ãœãããæäŸãã: ããã«ããããã®ã³ã°ããããã°ã®ããã«å€ãªããžã§ã¯ããæååãšããŠè¡šçŸãããããªããŸãã
- å æ¬çãªãŠããããã¹ããäœæãã: å€ãªããžã§ã¯ãã®æ€èšŒãç䟡æ§ãäžå€æ§ã培åºçã«ãã¹ãããŸãã
- æå³ã®ããååã䜿çšãã: å€ãªããžã§ã¯ããè¡šãæŠå¿µãæç¢ºã«åæ ããååãéžã³ãŸãïŒäŸïŒ`EmailAddress`ã`Currency`ã`PostalCode`ïŒã
çµè«
å€ãªããžã§ã¯ãã¯ãJavaScriptã¢ããªã±ãŒã·ã§ã³ã§ããŒã¿ãã¢ãã«åãã匷åãªæ¹æ³ãæäŸããŸããäžå€æ§ãæ€èšŒãå€ã«åºã¥ãç䟡æ§ãåãå ¥ããããšã§ãããå ç¢ã§ä¿å®ããããããã¹ãããããã³ãŒããäœæã§ããŸããå°èŠæš¡ãªWebã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããŠããå Žåã§ããå€§èŠæš¡ãªãšã³ã¿ãŒãã©ã€ãºã·ã¹ãã ãæ§ç¯ããŠããå Žåã§ããã¢ãŒããã¯ãã£ã«å€ãªããžã§ã¯ããçµã¿èŸŒãããšã§ããœãããŠã§ã¢ã®å質ãšä¿¡é Œæ§ãå€§å¹ ã«åäžãããããšãã§ããŸããã¢ãžã¥ãŒã«ã䜿çšããŠãããã®ãªããžã§ã¯ããæŽçããšã¯ã¹ããŒãããããšã§ãããã¢ãžã¥ãŒã«åãããããæ§é åãããã³ãŒãããŒã¹ã«è²¢ç®ãããåå©çšæ§ã®é«ãã³ã³ããŒãã³ããäœæã§ããŸããå€ãªããžã§ã¯ããæ¡çšããããšã¯ãã°ããŒãã«ãªå©çšè ã察象ãšãããããã¯ãªãŒã³ã§ä¿¡é Œæ§ãé«ããçè§£ããããJavaScriptã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã®éèŠãªäžæ©ã§ãã