【javascript】ロックとキーのシミュレート

こちらの記事は以下の書籍を参考に執筆しました

- [入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)


ロックとキーのシステムを構築する。
lock関数では鍵をかけて保管するデータが有る。
戻り地はロック解除のための一意のキー(key)。
unlock関数は正しいキーを使ってロックを解除する。
したがってAPIは`{key,unlock}=lock(secret)`となる。

```javascript
function lock(secret) {
  const key = Symbol('key')
  return {
    key,unlock(keyUserd) {
      if (keyUserd == key) {
        return secret;
      } else {
        return '*'.repeat(secret.length || secret.toString().length)
      }
    }
  }
}

const {key,unlock}=lovk(42)
console.log('key')//**
console.log(42)//**
console.log(key)//42
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)

lock関数の引数を渡すと、一意にキーが作成されkeyとunlock関数のオブジェクトを返す。
塩用されたキーが正しくない場合は文字列をマスクする処理をしている。

```javascript
'*'.repeat(secret.length || secret.toString().length)
```

>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)


この容量で複数のロックと複数のキーを作成することができる。

#ゲームを作成する


```javascript
function choose(message, options, secondAttempt) {
  //プロンプトに表示する複数選択オプションを作成
  //各インデックスに1を足すことでオプションが0でなく1から始まるようにする
  const opts = options.map(function(option, index) {
    return `Type ${index+1} for: ${option}`;
  })

  //ユーザがプロンプトで入力した番号を取得
  //先の足した1を引く
  const resp = Number(prompt(`${message}\n\n${opts.join('\n')}`)) - 1
  if (options[resp]) {
    //プロンプトから適切なレスポンスが返された場合はそれを返す。
    return resp;
  } else if (!secondAttempt) {
    //有効なタイじゃなかったらもう一回オプションを表示
    return choose(`Last try\n${message}`, options, true)
  } else {
    //2回目もだめならエラー
    throw Error('No selection')
  }
}

const message='最高のスーパーヒーローは誰か'
const options=['スーパーマン','アイアンマン','バットマン','キャプテンアメリカ'];
const hero=choose(message,options)
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)


ここではmapを使っているがこれは新しい配列を作成している。

###Array.prototype.map()

```javascript:構文
var new_array = arr.map(function callback(currentValue[, index[, array]]) {
    // 新しい配列の要素を返す
}[, thisArg])
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)


####引数
**callback**
新しい配列の要素を生成するためのコールバック関数は3つの引数を取る。

|callbackの引数|説明|
|---|---|
|currentValue|現在処理中の要素の値|
|index(optional)|現在処理中の要素の配列内におけるインデックス|
|array(optional)|mapが実行されている配列|

**thisArg(optional)**
callbacを実行するときにthisとして使う値

####返り値
新しい配列

initでまとめるとこうなる

```javascript
function lock(secret) {
  const key = Symbol('key')
  return {
    key,
    unlock(keyUserd) {
      if (keyUserd == key) {
        return secret;
      } else {
        return '*'.repeat(secret.length || secret.toString().length)
      }
    }
  }
}


function choose(message, options, secondAttempt) {
  //プロンプトに表示する複数選択オプションを作成
  //各インデックスに1を足すことでオプションが0でなく1から始まるようにする
  const opts = options.map(function(option, index) {
    return `Type ${index+1} for: ${option}`;
  })

  //ユーザがプロンプトで入力した番号を取得
  //先の足した1を引く
  const resp = Number(prompt(`${message}\n\n${opts.join('\n')}`)) - 1
  if (options[resp]) {
    //プロンプトから適切なレスポンスが返された場合はそれを返す。
    return resp;
  } else if (!secondAttempt) {
    //有効なタイじゃなかったらもう一回オプションを表示
    return choose(`Last try\n${message}`, options, true)
  } else {
    //2回目もだめならエラー
    throw Error('No selection')
  }
}
function init(){
  const {key:key1,unlock:door1}=lock('A new car')
  const {key:key2,unlock:door2}=lock('A trip to Hawaii')
  const {key:key3,unlock:door3}=lock('$100 Doloars')

  const keys=[key1,key2,key3]
  const doors=[door1,door2,door3]
  const key=keys[Math.floor(Math.random()*3)]

  const message=`you have been given a \u{1F511} plese choose a door.`

  const options=doors.map(function(door,index){
    return `Door #${index+1}: ${door()}`
  })

  const door=doors[choose(message,options)]
  alert(door(key))
}
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)