近年のJSで分からないこと

個人用メモをそのまま公開します。

## 前提
jQuery時代のJavaScriptは分かるけど、それ以降の知識が曖昧なため、
VueとかNuxtとか書こうとすると、すぐにつまずく。

## export default...は何？
JSでモジュール分割するための記法というのは分かる。


## const { data } = ...は何？
複数の変数に代入するための記法と思うけど、１個のときもこの書き方を見る。

中括弧を使うのは、どういう意味？
オブジェクトを書くときの中括弧と同じか、文法的にはまったく別の意味か。

## コード例
いま見てるチュートリアルのコードを例に疑問をまとめる。
JS、TS、Vueの疑問が混在してるけど構わない。
https://www.newt.so/docs/tutorials/get-contents-in-nuxt
```vue
<script lang="ts" setup>
// {}を削除しても動いたけど警告が出る: Default export is not declared in imported module
// Q1 {}は複数のときだけ必須というわけじゃなく、importの解釈に影響する？
// A1 {}の有無はデフォルトインポートかどうか。importの挙動に影響する。JSの仕様。
import type { Article } from '~/types/article'

// async/awaitが入れ子で複数出てきて混乱する
// awaitだから非同期処理を待ち、dataに代入してから次の行に進む、というのは分かる
// useAsyncDataはNuxtの機能
// Q2 {}を消してconst data = にすると取得結果が表示されなくなる。JS解釈が変わってVueに影響する？
// A2 {}を付けると戻り値のなかの特定のプロパティを取得する。ここではref型のdataプロパティが欲しいので、{}が必要。
const { data } = await useAsyncData('articles', async () => {
  // Q3 識別子を渡してないのにNewt用機能が返されるのが分からない。分かりやすい変数名にしてるだけ？
  // A3 {}でNuxtAppのnewtClientプロパティを取得している。変数名に＄が付くのはよく分からない。Nuxtの仕様？
  const { $newtClient } = useNuxtApp()
  // asyncのなかでawaitしてる。
  // これはuseAsyncDataのハンドラのreturnで、戻り値がdataに入るのは分かる
  return await $newtClient.getContents<Article>({
    appUid: 'blog',
    modelUid: 'article',
    query: {
      // Q4 要素を削除してもエラーにならない。型定義の不一致も、SDKがうまいこと処理してくれる？
      // A4 よく分からない。ここまでチェックできないという感じかもしれない。
      select: ['_id', 'title', 'slug', 'body']
    }
  })
})
// Q5 .valueがあるということは、const {data}はrefになる？
// A5 だいたい合ってる。refになるというより、ref型であるdataプロパティを取得している。
const articles = data.value?.items
</script>
```

## Q1 import
`import type`はTypeScriptの仕様。型のみをインポートするためのTS記法。
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html
```ts
import type Foo, { Bar, Baz } from "some-module";
//     ~~~~~~~~~~~~~~~~~~~~~~
// error! A type-only import can specify a default import or named bindings, but not both.
```
{}なしはデフォルトインポート、{}つきは名前付きバインドと解釈されるみたい。

#### {}の解釈は、JSのimportの仕様がある
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/import
{}つきは、エクスポートされたものから特定のオブジェクト等をインポートする。
{}なしは、デフォルトとしてエクスポートされたものをインポートする。

#### exportの仕様を見る
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/export
一番最初に説明がある。

> 1. 名前付きエクスポート (モジュールごとに 0 以上のエクスポート)
> 2. デフォルトエクスポート (モジュールごとに 1 つのエクスポート)

それぞれの意味は簡単に理解できるけど、使い分けがよく分からない。
慣例とか書きやすさで適当にやればいい気がする。

> 値をひとつエクスポートしたい、あるいはモジュールでフォールバック先の値を持ちたい場合は、デフォルトエクスポートを使用するとよいでしょう。

## Q2 const { data } = ...
分割代入というJS仕様。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
```js
({ a, b } = { a: 10, b: 20 });
console.log(a); // 10
console.log(b); // 20
```

`const {data}`は、戻り値のなかで、dataという名前の値を取得する記述。
{}なしにすると、戻り値そのものを受け取ることになるので、結果が変わって当然。

#### useAsyncData
https://nuxt.com/docs/api/composables/use-async-data/
useAsyncDataの戻り値はAsyncData型で、data以外もいくつかのプロパティがある。
dataは`data: Ref<DataT | null>`と定義されてて、予想通りrefだった。

## Q3 useNuxtApp
Nuxtの仕様
https://nuxt.com/docs/api/composables/use-nuxt-app

プラグインを定義して呼び出す方法
https://nuxt.com/docs/guide/directory-structure/plugins#automatically-providing-helpers

呼び出す時に＄をつける理由が分からない。

## Q4 型定義の不一致
NewtのAPIドキュメント
https://developers.newt.so/apis/cdn#tag/contents_methods/operation/getContents
JS用のSDK
https://github.com/Newt-Inc/newt-client-js

#### TypeScriptの型
https://typescriptbook.jp/reference/object-oriented/interface
> TypeScriptで定義されたインターフェースは、コンパイルチェックに活用された後、JavaScriptコードを生成する過程で消されるため、インターフェースがJavaScript実行時に影響することはありません。

`export interface Article`のなかを削除変更しても、エラーにならない。問題なく動く。
SDKの内部の作りによって、コンパイルチェックが及ばないのかもしれない。

## 感想
JSの分割代入が分かれば、ほとんどの疑問が解消した。


分割代入は、イメージ的にはこんなコードと同じ感じ。
```js
// 分割代入
const { data } = get()

// 普通に書くと、こんな感じ
const data  = get().data
// 指定のデータだけ取得するという意味では、こんな感じもする
const data  = get('data')
```
左辺に識別子を書くという記法が、たぶん初めて経験することで、説明を見るまで全然分からなかった。

https://ja.javascript.info/destructuring-assignment#ref-1858
「入れ子構造の非構造化」以下の書き方が非常に強力。
ただ短いだけの記法じゃなく、広範囲に便利に使えそう。

## 翌日の感想
#### 分割代入に感じた違和感
```js
const { data } = get()
```
このコードの場合、getメソッドの中に書かれてる識別子を、左辺で使ってることに違和感があった。呼び出し元から、呼び出し先を覗き込んでいるような感じで、それまでのプログラミング観と相容れなかった。

でも、よく考えると、全然そういう話ではない。
getメソッドから受け取った戻り値を、呼び出し元で処理してるだけなので、getメソッドの中を覗き込んでいるわけではない。
```js
// こう書けば、戻り値を処理してるだけなのは明白
const ret = get()
const { data } = ret
```

慣れないNuxtを前にして、必要以上に「分からない」と思い込んでたかもしれない。
そのせいで、一目で分からない記述に不思議な解釈をしようとしてた。

#### phpでも分割代入できるみたい
古いlistのイメージしかなかった。
この記事を見ると、JSの分割代入と同じようなことができるみたい。JS独自の仕様ではなかった。
https://qiita.com/okumurakengo/items/9c781a17c15ea2916566