グーグルのV8チームはこの瞬間を長い間待っていたと思います。 V8エンジン(最も人気のあるJavaScriptエンジン)の8番目のバージョンがリリースされました! この新しいバージョンには、いくつかの非常に優れたパフォーマンスの改善と、オプションの連鎖とnullish合体という2つの新しいクールなJavaScript言語機能が付属しています。

オプションの連鎖

これは待望の機能です。 ひどいAPIプロバイダーを使用しているとしましょう。 このAPIをCrocosAPIと呼びましょう。 CrocosAPIは、世界中のすべてのワニに関する情報を提供します(これは、「ゲーターがクロックスより優れている」ことを誰もが知っている不安定なAPIです)。

これは、ワニの生息地を取得するための私たちの機能です(一部のワニは淡水、汽水、および/または塩水に住んでいます)

const getWaterHabitat = async (crocName) => {
  // First we call our made up api
  const crocResponse = await fetch('http://api.crocosapi.io/croc/' + crocName);
  // We get the responses body
  const crocInfo = crocResponse.body;
  // We access the water property of the habitat property
  return crocInfo.habitat.water;
}

// Let's get the water habitat of a crocodile called Barry
const barrysWaterHabitat = getWaterHabitat('Barry');
// this returnsbarrysWaterHabitat == ['freshwater']

ここで、CrocosAPIの開発者が応答の構造を次のように変更することを決定したとしましょう。

{
  "personalInfo" : {
    "firstName" : "Barry"
  },
  "habitat": {
    "water": ["freshwater"],
  }
  // ... skipping
}

に:

{
  "personalInfo" : {
    "firstName" : "Barry"
    //  ...
  },
  // We changed 'habitat' to 'environment'
  "environment": {
    "water": ["freshwater"]
  }
  //...
}

getWaterHabitatと呼ぶと、次のようになります。

TypeError: Cannot read property 'water' of undefined

それはcrocInfo.habitatがもう存在しないからです。 crocInfoにアクセスするには、crocInfo.environment.waterにアクセスする必要があります。 これは、CrocosAPIの開発者がバージョン管理について知らないという理由だけで、アプリ全体がクラッシュすることを意味します。 では、そのエラーを回避する方法は? もちろんオプションのチェーン!

const getWaterHabitat = async (crocName) => {
  const crocResponse = await fetch('http://api.crocosapi.io/croc/' + crocName)
  const crocInfo = crocResponse.body
  // We access the water key with optional chaining
  return crocInfo?.habitat?.water
}

const myCrocsName = 'Barry'
const barrysWaterHabitat = getWaterHabitat('Barry')
// barrysWaterHabitat == undefined

配列でオプションのインデックスを使用することもできます。

const crocAddress1City = crocInfo?.personalInfo?.addresses?.[0].city
// if  crocInfo.personalInfo.addresses = []
// crocAddress1City === undefined

…そして機能付き!

// It is hard to make a short example
const getSkinStyle = (option) => {
  const scales = {
    color: 'green',
    texture: 'shiny'
  }
  if (option == 'naked')
    return
  else 
    return scales
}

const crocInfo = {
  name: 'Barry', 
  waterHabitat : 'Freshwaters',
  getSkinStyle : getSkinStyle
}

const barrysSkinColor = crocInfo?.getSkinStyle?.('naked')?.color
// barrysSkinColor === undefined
const larrysSkinColor = crocInfo?.getSkinStyle?.('naked')?.color
// larrysSkinColor === 'green'

…そして動的なプロパティアクセスを使用します。 うわー、それは本当にホリデーシーズンです⛄🎄🎁(執筆時点)!

// habitatType can be "water" or "land"
const getHabitatProperty = (habitatType) => {
  return crocInfo?.habitat?.[habitatType]
}
getHabitatType('water')
// returns  ['freshwater']
getHabitatType('land')
// returns ['forest']

undefinedの値だけで、タイプエラーはもうありません。

迅速なPSAとして、適切なエラー処理を行わない言い訳として、オプションのチェーンに依存しないでください。 未定義の値のプロパティにアクセスすることで得られるTypeErrorの良いところは、次のとおりです。

  • アプリケーションの予期しない動作に気づきやすくなります
  • それは私たちにもっと良いフォールバックメカニズムを書くことを強制します

未定義の値のプロパティにアクセスしようとするときは、何らかのフォールバックまたは警告メカニズムが必要です。

ヌルの合体

??…いいえ、混乱していません。??は、&&および||ファミリに加わった新しい短絡オペレータです。 React、Vue、Angularを書いた場合は、おそらくこのようなものをすでに書いているか、見たことがあるでしょう。

const name = props.name || 'CrocName Error';
const age = props.age || 'Invalid Age';
const isFemale = props.isFemale || true;
// pass name , age and isFemale to a view

このコードは、偽物でない場合、props.nameに保存されている値を割り当てます。 値が偽の場合、値nameCrocName Errorと等しくなります。

しかし、まだ名前が付けられていないワニの場合、APIは空の文字列を返すとしましょう。 JavaScriptでは、空の文字列は偽物と見なされるため、次のようになります。

// Let's say we have an anonymous new born boy crocodile
const props  = {
  name: '',
  age: 0,
  isFemale: false
}

const name = props.name || 'CrocName Error';
// name === 'CrocName Error'

const age = props.age || 'Invalid Age';
// age === 'Invalid Age'

const isFemale = props.isFemale || true;
// isFemale === true

これらは私たちが期待していた結果ではありません! props.nameの値がnullまたはundefinedのシナリオを、props.nameが空の文字列の場合に分けたいと思います。 age0に等しくし、isFemalefalseにしたいとします。 そこで??が助けになります。

const name = '' ?? 'CrocName Error'
// name === '' 

const age = 0 ?? 'Invalid Age';
// age === 0

const isFemale = false ?? true;
// isFemale === false

// Yay it worked!

||は、左側の演算子が偽であるかどうかをチェックします。 ??は、それがnullまたはundefinedであるかどうかのみをチェックします。 これがあなたのための小さなチートシートです:

// +0, -0, NaN, false, empty strings, null and undefined are all falsy
false ?? true;   // equals false
false || true;   // equals true

0 ?? 1;          // equals 0
0 || 1;          // equals 1

'' ?? 'default'; // equals ''
'' || 'default'; // equals 'default'

// null and undefined are falsy so in this case we  get the same results
null ?? [];      // equals []
null || [];      // equals []

undefined ?? []; // equals []
undefined || []; // equals []

演算子を混在させることもできます! かっこを使用することを忘れないでください。 これが何をするか考えてみてください:

const crocName = (props.name ?? 'CrocName Error') || 'Anonymous Croc';

いくつかの値の結果を見てみましょう。

  • props.name === 'Barry'crocName === 'Barry'
  • props.name === ''crocName ==== 'Anonymous Croc'
  • props.name === undefinedcrocName ==== 'CrocName Error'

ヌルの合体とオプションの連鎖が連携する

これらの2つの機能を一緒に使用するためのクールな方法を考えたかもしれません!

const getCrocName = async (crocId) => {
  // We try to access our unstable API's data
  const crocResponse = await fetch('http://api.crocosapi.io/croc/' + crocId)
  // If croc response or body is undefined 
  const crocInfo = crocResponse?.body ?? 'Croc API did not return a valid response'
  // if crocResponse equals {} then crocInfo == 'Croc API did not return a valid response'

  // checking if crocInfo, personal info or name is undefined/null or if name has a falsy value
  return (crocInfo?.personalInfo?.name ?? 'There was a problem loading the croc\'s name') || 'Anonymous Croc'
  // if crocInfo?.personalInfo?.name === '' we return 'Anonymous Croc'
  //  if crocInfo equals {} we return 'There was a problem loading the croc\'s name'
}

V8V8のパフォーマンス

今日、私たちはJavaScriptの速度に甘んじており、パフォーマンスの更新が繰り返されることでさらに甘やかされています。 繰り返しになりますが、V8のエンジニアは、エンジンのパフォーマンスとメモリを改善しました。 それがどのようになっているのかについてもっと知りたい場合は、リリース投稿をチェックしてください。 これらの更新について私が気に入っているのは、コードのパフォーマンスが向上することですが、新しいものを書く必要はありません。

小さなボーナス

Node.jdでV8v8を使用できるかどうかを確認するには、node -p process.versions.v8を実行して、バージョンが8を超えているかどうかを確認します。 今のところ、Webやトランスパイラーでcore-jsのようなポリフィルを使用する必要があります。 Babelを使用している場合は、@babel/plugin-proposal-optional-chaining@babel/plugin-proposal-nullish-coalescing-operatorを使用できます。

楽しく幸せな休日を! 🎄🎉