<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>プログラミング言語 on AIによる技術記事 備忘録</title><link>https://ai.hack-le.com/tags/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E/</link><description>Recent content in プログラミング言語 on AIによる技術記事 備忘録</description><generator>Hugo -- gohugo.io</generator><language>ja</language><lastBuildDate>Sat, 22 Aug 2026 10:27:11 +0900</lastBuildDate><atom:link href="https://ai.hack-le.com/tags/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E/index.xml" rel="self" type="application/rss+xml"/><item><title>C言語のstrcmp関数の完全ガイド – 戻り値の理解と注意点</title><link>https://ai.hack-le.com/c%E8%A8%80%E8%AA%9E%E3%81%AEstrcmp%E9%96%A2%E6%95%B0%E3%81%AE%E5%AE%8C%E5%85%A8%E3%82%AC%E3%82%A4%E3%83%89-%E6%88%BB%E3%82%8A%E5%80%A4%E3%81%AE%E7%90%86%E8%A7%A3%E3%81%A8%E6%B3%A8%E6%84%8F%E7%82%B9/</link><pubDate>Fri, 05 Sep 2025 00:20:47 +0900</pubDate><guid>https://ai.hack-le.com/c%E8%A8%80%E8%AA%9E%E3%81%AEstrcmp%E9%96%A2%E6%95%B0%E3%81%AE%E5%AE%8C%E5%85%A8%E3%82%AC%E3%82%A4%E3%83%89-%E6%88%BB%E3%82%8A%E5%80%A4%E3%81%AE%E7%90%86%E8%A7%A3%E3%81%A8%E6%B3%A8%E6%84%8F%E7%82%B9/</guid><description>&lt;h2 id="strcmp関数の基本仕様"&gt;strcmp関数の基本仕様&#10;&lt;/h2&gt;&lt;p&gt;C言語の&lt;code&gt;strcmp&lt;/code&gt;関数は文字列比較を行う標準ライブラリ関数である。この関数は&lt;code&gt;string.h&lt;/code&gt;ヘッダーで定義されており、2つの文字列を辞書順で比較して整数値を返す。関数のプロトタイプは&lt;code&gt;int strcmp(const char *s1, const char *s2)&lt;/code&gt;となっている。&lt;/p&gt;&#10;&lt;p&gt;戻り値の仕様が特徴的で、多くのプログラマーが混乱する原因となっている。戻り値は以下の3つのパターンに分類される。まず、文字列が等しい場合は0を返す。次に、第一引数が第二引数より辞書順で前にある場合は負の値を返す。最後に、第一引数が第二引数より辞書順で後にある場合は正の値を返す。&lt;/p&gt;&#10;&lt;p&gt;この仕様は一見直感的でないように思えるが、数学的な比較演算子の考え方と一致している。つまり、&lt;code&gt;s1 - s2&lt;/code&gt;の結果を表現していると考えることができる。等しければ差は0、s1が小さければ負、s1が大きければ正という論理である。&lt;/p&gt;&#10;&lt;h2 id="具体的な使用例とコード実装"&gt;具体的な使用例とコード実装&#10;&lt;/h2&gt;&lt;p&gt;実際の使用例を通じて&lt;code&gt;strcmp&lt;/code&gt;の動作を確認してみよう。以下のコードは基本的な文字列比較を示している。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#include &amp;lt;stdio.h&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#include &amp;lt;string.h&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;int main() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; char str1[] = &amp;#34;apple&amp;#34;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; char str2[] = &amp;#34;banana&amp;#34;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; char str3[] = &amp;#34;apple&amp;#34;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; char str4[] = &amp;#34;application&amp;#34;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; int result1 = strcmp(str1, str2); // &amp;#34;apple&amp;#34; vs &amp;#34;banana&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; int result2 = strcmp(str1, str3); // &amp;#34;apple&amp;#34; vs &amp;#34;apple&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; int result3 = strcmp(str2, str1); // &amp;#34;banana&amp;#34; vs &amp;#34;apple&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; int result4 = strcmp(str1, str4); // &amp;#34;apple&amp;#34; vs &amp;#34;application&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; printf(&amp;#34;apple vs banana: %d\n&amp;#34;, result1); // 負の値&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; printf(&amp;#34;apple vs apple: %d\n&amp;#34;, result2); // 0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; printf(&amp;#34;banana vs apple: %d\n&amp;#34;, result3); // 正の値&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; printf(&amp;#34;apple vs application: %d\n&amp;#34;, result4); // 負の値&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; return 0;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコードを実行すると、&lt;code&gt;result1&lt;/code&gt;と&lt;code&gt;result4&lt;/code&gt;は負の値、&lt;code&gt;result2&lt;/code&gt;は0、&lt;code&gt;result3&lt;/code&gt;は正の値となる。重要な点は、具体的な数値に依存してはいけないということである。実装によって返される具体的な値は異なる可能性があるため、符号のみを判定に使用するべきである。&lt;/p&gt;&#10;&lt;p&gt;条件分岐での使用例も示しておこう。文字列が等しいかどうかを判定する場合、戻り値が0であることを明示的に確認する必要がある。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;if (strcmp(str1, str3) == 0) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; printf(&amp;#34;文字列は等しい\n&amp;#34;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;} else {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; printf(&amp;#34;文字列は異なる\n&amp;#34;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;if (strcmp(str1, str2) &amp;lt; 0) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; printf(&amp;#34;str1はstr2より辞書順で前にある\n&amp;#34;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="重要な注意点とトラブルシューティング"&gt;重要な注意点とトラブルシューティング&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;strcmp&lt;/code&gt;を使用する際に陥りがちな問題がいくつか存在する。最も深刻なのはNULLポインタを渡した場合の動作である。&lt;code&gt;strcmp&lt;/code&gt;はNULLチェックを行わないため、NULLポインタを渡すとセグメンテーションフォルトが発生する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;char *str1 = NULL;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;char *str2 = &amp;#34;hello&amp;#34;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;// strcmp(str1, str2); // これは実行時エラーを引き起こす&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;// 安全な実装例&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;if (str1 != NULL &amp;amp;&amp;amp; str2 != NULL) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; int result = strcmp(str1, str2);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; // 比較処理&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;} else {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; // NULLポインタの処理&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;大文字小文字の区別も重要な注意点である。&lt;code&gt;strcmp&lt;/code&gt;は大文字と小文字を異なる文字として扱うため、&lt;code&gt;strcmp(&amp;quot;Hello&amp;quot;, &amp;quot;hello&amp;quot;)&lt;/code&gt;は0を返さない。大文字小文字を無視した比較が必要な場合は、POSIX環境では&lt;code&gt;strcasecmp&lt;/code&gt;関数を使用できる。&lt;/p&gt;&#10;&lt;p&gt;文字列長が異なる場合の動作も理解しておく必要がある。短い文字列の方が長い文字列より「小さい」と判定される。例えば、&lt;code&gt;strcmp(&amp;quot;abc&amp;quot;, &amp;quot;abcdef&amp;quot;)&lt;/code&gt;は負の値を返す。これは短い文字列の終端文字（NULL文字）が、長い文字列の対応する文字より小さいと判定されるためである。&lt;/p&gt;&#10;&lt;p&gt;マルチバイト文字を含む文字列の比較では、&lt;code&gt;strcmp&lt;/code&gt;はバイト単位での比較を行うため、期待した結果にならない場合がある。日本語などを含む文字列を適切に比較するには、ロケールを考慮した&lt;code&gt;strcoll&lt;/code&gt;関数の使用を検討すべきである。&lt;/p&gt;&#10;&lt;h2 id="関連関数と使い分け"&gt;関連関数と使い分け&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;strcmp&lt;/code&gt;以外にも文字列比較に関連する関数が存在する。用途に応じて適切な関数を選択することが重要である。&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;strncmp&lt;/code&gt;関数は指定した文字数まで比較を行う。プロトタイプは&lt;code&gt;int strncmp(const char *s1, const char *s2, size_t n)&lt;/code&gt;である。部分的な文字列比較や、長大な文字列の前方部分のみを比較したい場合に有用である。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;char str1[] = &amp;#34;application&amp;#34;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;char str2[] = &amp;#34;apple&amp;#34;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;int result = strncmp(str1, str2, 5); // 最初の5文字を比較&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;// &amp;#34;appli&amp;#34; vs &amp;#34;apple&amp;#34; となり、結果は負の値&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;strcasecmp&lt;/code&gt;関数（POSIX環境）は大文字小文字を無視した比較を行う。Web開発やファイル名の比較など、大文字小文字の違いを無視したい場面で活用される。&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;strcoll&lt;/code&gt;関数は現在のロケール設定に基づいた文字列比較を行う。国際化されたアプリケーションで、各国の文字順序規則に従った比較が必要な場合に使用される。&lt;/p&gt;&#10;&lt;p&gt;これらの関数を適切に使い分けることで、より堅牢で国際化対応された文字列処理が実現できる。特に、ユーザー入力を扱うアプリケーションでは、想定外の文字列に対する適切な処理が重要となる。&lt;/p&gt;&#10;</description></item><item><title>レキシカルスコープとダイナミックスコープの比較</title><link>https://ai.hack-le.com/scope/</link><pubDate>Thu, 03 Oct 2024 05:00:45 +0900</pubDate><guid>https://ai.hack-le.com/scope/</guid><description>&lt;h2 id="レキシカルスコープとは"&gt;レキシカルスコープとは？&#10;&lt;/h2&gt;&lt;p&gt;レキシカルスコープ（Lexical Scope）は、変数がどのスコープに属するかを「コードの構造」や「定義された場所」に基づいて決定するものです。JavaScript、Python、Cなどの多くのプログラミング言語はこのスコープの仕組みを採用しています。関数がどこで「定義」されたかが重要であり、その関数が「呼び出される場所」によって変数の参照範囲が変わりません。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// このxは、fooが定義された場所のスコープから参照される&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// ここで呼び出してもxは10のまま&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// 10&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上記のコードでは、&lt;code&gt;foo&lt;/code&gt;は&lt;code&gt;bar&lt;/code&gt;の中で呼び出されても、&lt;code&gt;foo&lt;/code&gt;が定義された場所のスコープ（グローバルスコープ）を参照します。&lt;code&gt;bar&lt;/code&gt;の中に&lt;code&gt;x = 20&lt;/code&gt;があっても、それは無視されます。これは、レキシカルスコープが「定義時のスコープ」を重視するためです。&lt;/p&gt;&#10;&lt;h2 id="ダイナミックスコープとは"&gt;ダイナミックスコープとは？&#10;&lt;/h2&gt;&lt;p&gt;一方、ダイナミックスコープ（Dynamic Scope）は「実行時のスコープ」に基づいて変数を解決します。関数が呼び出された「場所」によって、そのスコープが決まります。したがって、ダイナミックスコープでは関数の呼び出し元が変わると、参照される変数も変わります。近年の主流の言語ではあまり使われていませんが、Lispや一部のシェルスクリプトでこの考え方が採用されています。&lt;/p&gt;&#10;&lt;p&gt;たとえば、JavaScriptがダイナミックスコープを採用していたとしたら、次のようになります。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// このxは、呼び出し元のスコープから参照される&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// ダイナミックスコープだとxは20になる&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// 20&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この場合、&lt;code&gt;foo&lt;/code&gt;関数が呼び出される時点のスコープ（&lt;code&gt;bar&lt;/code&gt;のスコープ）を参照するため、&lt;code&gt;x&lt;/code&gt;は&lt;code&gt;20&lt;/code&gt;となります。つまり、ダイナミックスコープでは、関数の「呼び出し元」のスコープが参照されるのです。&lt;/p&gt;&#10;&lt;h2 id="レキシカルスコープ-vs-ダイナミックスコープ"&gt;レキシカルスコープ vs ダイナミックスコープ&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;レキシカルスコープ&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;ダイナミックスコープ&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;スコープの決定&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;定義された場所に基づく&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;呼び出し元の場所に基づく&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;メリット&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;コードの予測可能性が高い&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;実行時の状況に柔軟に対応できる&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;デメリット&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;柔軟性が低くなる場合がある&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;コードの挙動が予測しにくくなる&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;レキシカルスコープの最大の利点は、コードを見ただけで変数の参照先がわかり、予測がしやすいことです。一方で、ダイナミックスコープは実行時の状況に応じて変数を解決できるため、柔軟性はありますが、逆にどの変数が参照されるかが分かりづらくなることが多いです。&lt;/p&gt;&#10;&lt;h2 id="なぜレキシカルスコープが一般的なのか"&gt;なぜレキシカルスコープが一般的なのか？&#10;&lt;/h2&gt;&lt;p&gt;レキシカルスコープが一般的な理由は、その予測可能性と安定性にあります。定義時のスコープが参照されるため、コードを読むだけで変数がどこから来るのか理解しやすく、バグを防ぎやすいからです。&lt;/p&gt;&#10;&lt;p&gt;一方で、ダイナミックスコープの柔軟性が求められる場面は、特殊なケースに限られるため、現代のプログラミング言語ではレキシカルスコープが主流となっています。&lt;/p&gt;&#10;</description></item><item><title>JavaScriptの演算子??の理解と使用例</title><link>https://ai.hack-le.com/javascript-ope/</link><pubDate>Mon, 07 Aug 2023 18:11:52 +0900</pubDate><guid>https://ai.hack-le.com/javascript-ope/</guid><description>&lt;p&gt;JavaScriptのググラビリティ最低ワード&lt;code&gt;??&lt;/code&gt;についての記事。この点の演算子周りはわからない時にGoogleが無力の極みで困りがち。&lt;/p&gt;&#10;&lt;p&gt;以下、&lt;code&gt;||&lt;/code&gt;とかにも触れつつChatGPT-4にまとめさせた。&lt;/p&gt;&#10;&lt;h2 id="イントロ"&gt;イントロ&#10;&lt;/h2&gt;&lt;p&gt;JavaScriptのNullish Coalescing Operator (&lt;code&gt;??&lt;/code&gt;) は、値がnullまたはundefinedであるかどうかをチェックする際に非常に便利な演算子です。この記事では、&lt;code&gt;??&lt;/code&gt; 演算子の使い方、&lt;code&gt;||&lt;/code&gt; 演算子との違い、および他の代替方法との比較について解説します。&lt;/p&gt;&#10;&lt;h2 id="-演算子の基本"&gt;&lt;code&gt;??&lt;/code&gt; 演算子の基本&#10;&lt;/h2&gt;&lt;p&gt;JavaScriptの &lt;code&gt;??&lt;/code&gt; 演算子はNullish Coalescing Operator（ヌリッシュ・コアレシング演算子）と呼ばれます。この演算子は、左側のオペランドがnullまたはundefinedの場合に、右側のオペランドを返します。左側のオペランドがnullやundefined以外であれば、左側の値がそのまま返されます。&lt;/p&gt;&#10;&lt;p&gt;以下は &lt;code&gt;??&lt;/code&gt; 演算子の使用例です。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;default value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// z は &amp;#34;default value&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;もし &lt;code&gt;x&lt;/code&gt; がnullかundefinedでなければ、&lt;code&gt;z&lt;/code&gt; の値は &lt;code&gt;x&lt;/code&gt; と同じになります。&lt;/p&gt;&#10;&lt;p&gt;この演算子は、変数にデフォルト値を設定する際などに便利で、特にオブジェクトのプロパティにデフォルト値を設定する場合によく使用されます。&lt;/p&gt;&#10;&lt;h2 id="-演算子との違い"&gt;&lt;code&gt;||&lt;/code&gt; 演算子との違い&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;??&lt;/code&gt; 演算子と似ている &lt;code&gt;||&lt;/code&gt; 演算子との違いは重要です。 &lt;code&gt;??&lt;/code&gt; （Nullish Coalescing Operator）と &lt;code&gt;||&lt;/code&gt; （論理OR演算子）との主な違いは、どのように「偽」と評価されるかにあります。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;??&lt;/code&gt; 演算子は、左側のオペランドがnullかundefinedの場合にのみ右側のオペランドを返します。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;||&lt;/code&gt; 演算子は、左側のオペランドがfalsy（偽と評価される値）である場合に右側のオペランドを返します。falsyな値には、null、undefined、0、空文字列（&amp;quot;&amp;quot;）、NaNなどが含まれます。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;この違いにより、0や空文字列などの値が意図された値として使用されるべき場合でも、&lt;code&gt;||&lt;/code&gt; 演算子を使うとデフォルト値に置き換えられてしまうことがあります。一方、&lt;code&gt;??&lt;/code&gt; 演算子はnullかundefinedの場合のみデフォルト値に置き換えるので、この問題が回避されます。&lt;/p&gt;&#10;&lt;p&gt;以下は例です。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// result1は &amp;#34;default&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value2&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// result2は 0&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この例では、&lt;code&gt;value1&lt;/code&gt; が0であるため、&lt;code&gt;||&lt;/code&gt; 演算子は &amp;ldquo;default&amp;rdquo; を返します。一方、&lt;code&gt;??&lt;/code&gt; 演算子は0がnullやundefinedではないため、0を返します。このように、&lt;code&gt;??&lt;/code&gt; 演算子はnullやundefinedの場合のみデフォルト値に置き換える動作をします。&lt;/p&gt;&#10;&lt;h2 id="他の代替方法"&gt;他の代替方法&#10;&lt;/h2&gt;&lt;p&gt;JavaScriptでnullまたはundefinedの値をチェックして、デフォルト値に置き換えるために使用できる他の方法もいくつかあります。以下はその一部です。&lt;/p&gt;&#10;&lt;h3 id="三項演算子"&gt;三項演算子&#10;&lt;/h3&gt;&lt;p&gt;三項演算子を使って値がnullまたはundefinedかどうかをチェックすることができます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;default&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="if文を使った方法"&gt;if文を使った方法&#10;&lt;/h3&gt;&lt;p&gt;もう少し冗長な方法として、if文を使って同じことを実現することもできます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;let value = null;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;if (value === null || value === undefined) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; value = &amp;#34;default&amp;#34;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="関数を使った方法"&gt;関数を使った方法&#10;&lt;/h3&gt;&lt;p&gt;このロジックを頻繁に使用する場合、関数にまとめることもできます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;function defaultValue(value, defaultVal) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; return value === null || value === undefined ? defaultVal : value;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;const result = defaultValue(null, &amp;#34;default&amp;#34;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="結論"&gt;結論&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;??&lt;/code&gt; 演算子は、値がnullまたはundefinedかどうかを素早く評価するための効率的な方法です。特に、0や空文字列など、他のfalsyな値を有効な値として扱いたい場合に威力を発揮します。三項演算子、if文、関数などの他の方法と比較して、コードの簡潔さと明確さが優れています。多くの場合、この演算子はコードの可読性と効率性を高める優れた選択肢となるでしょう。&lt;/p&gt;&#10;&lt;h2 id="寸評"&gt;寸評&#10;&lt;/h2&gt;&lt;p&gt;記事にしたものの、前述のとおりググらビリティは最悪なので、検索からはたどり着けなさそう。JavaScript系の記事を一覧にしてまとめたほうが良いかしら。せめてページ検索じゃないと機能しなさそう。&lt;/p&gt;&#10;</description></item><item><title>JavaScriptのオプショナルチェーンとは</title><link>https://ai.hack-le.com/javascript-optional-chaining/</link><pubDate>Sat, 05 Aug 2023 22:19:23 +0900</pubDate><guid>https://ai.hack-le.com/javascript-optional-chaining/</guid><description>&lt;p&gt;Mozillaの解説サイトを置きつつ。&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Optional_chaining" target="_blank" rel="noopener"&#10; &gt;オプショナルチェーン (?.) - JavaScript | MDN&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;ChatGPT-4に色々説明させてまとめさせた。&lt;/p&gt;&#10;&lt;h2 id="イントロ"&gt;イントロ&#10;&lt;/h2&gt;&lt;p&gt;JavaScriptのコードを書いていて、深くネストされたプロパティや関数に安全にアクセスしたいと思ったことはありませんか？ ECMAScript 2020（ES11）が導入したオプショナルチェーンは、このような問題を解決します。&lt;/p&gt;&#10;&lt;h2 id="オプショナルチェーンとは"&gt;オプショナルチェーンとは&#10;&lt;/h2&gt;&lt;p&gt;オプショナルチェーンは、JavaScriptの構文の一つで、存在を確認せずにオブジェクトのプロパティにアクセスしようとしたときにエラーが発生する問題を解決する新しいJavaScriptの機能です。これにより、プロパティが存在する場合に値を取得し、存在しない場合に&lt;code&gt;undefined&lt;/code&gt;を返します。オプショナルチェーン演算子は &amp;lsquo;?.&amp;rsquo;, と表されます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;const city = user.address?.city; // &amp;#39;New York&amp;#39;またはundefined&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;オプショナルチェーンは、コードの冗長性を減らし、読みやすさとメンテナンス性を向上させます。さらに、nullやundefinedに対する安全なアクセスを提供することで、ランタイムエラーを防ぐ役割も果たします。&lt;/p&gt;&#10;&lt;h2 id="オプショナルチェーンの使用方法"&gt;オプショナルチェーンの使用方法&#10;&lt;/h2&gt;&lt;p&gt;通常、JavaScriptではプロパティやメソッドにアクセスする際に、そのプロパティやメソッドが存在するかどうかを先に確認しなければなりません。存在しないプロパティやメソッドにアクセスしようとすると、&lt;code&gt;TypeError&lt;/code&gt;が発生します。しかし、オプショナルチェーンを使うことで、このようなエラーを防ぐことができます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Alice&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;New York&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// &amp;#39;New York&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// TypeError: Cannot read property &amp;#39;zip&amp;#39; of undefined&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このような場合に、オプショナルチェーンを使うと次のように書けます：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;console.log(user.address?.city); // &amp;#39;New York&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;console.log(user.address?.zip); // undefined&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;オプショナルチェーン演算子 &amp;lsquo;?.&amp;rsquo;, を使用すると、左辺の値が&lt;code&gt;null&lt;/code&gt;または&lt;code&gt;undefined&lt;/code&gt;の場合、その時点で評価が終了し、&lt;code&gt;undefined&lt;/code&gt;を返します。したがって、存在しないプロパティにアクセスしてもエラーを投げずに&lt;code&gt;undefined&lt;/code&gt;を返すため、コードの安全性が向上します。&lt;/p&gt;&#10;&lt;p&gt;また、オプショナルチェーンはメソッド呼び出しや配列のアクセスにも使用できます。存在しないメソッドを呼び出そうとしたり、存在しない配列の要素にアクセスしようとするときにも、オプショナルチェーンを使うことでエラーを防ぐことができます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Hello!&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;.();&lt;/span&gt; &lt;span class="c1"&gt;// &amp;#39;Hello!&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sayBye&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;.();&lt;/span&gt; &lt;span class="c1"&gt;// undefined&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Alice&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Bob&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// &amp;#39;Alice&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// undefined&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このように、オプショナルチェーンはJavaScriptで安全にオブジェクトのプロパティにアクセスするための便利な機能であり、コードのエラーハンドリングと可読性を大いに改善します。&lt;/p&gt;&#10;&lt;h2 id="オプショナルチェーンの注意点"&gt;オプショナルチェーンの注意点&#10;&lt;/h2&gt;&lt;p&gt;オプショナルチェーンの使用には、以下のような注意すべき点があります。&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;適切な利用：&lt;/strong&gt; プロパティの存在を必要とするケースや、nullやundefinedが許容されない場合には、オプショナルチェーンは適切ではないかもしれません。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;パフォーマンス：&lt;/strong&gt; オプショナルチェーンは過度に使用するとパフォーマンスに影響を及ぼす可能性があります。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;互換性：&lt;/strong&gt; オプショナルチェーンはECMAScript 2020（ES11）で導入された新しい機能なので、古いブラウザではサポートされていない可能性があります。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;オプショナルチェーンの注意が不適切であるかもしれないケースとして、具体的には下記のようなものが考えられます。&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;外部APIからのレスポンスのパース:&lt;/strong&gt; APIからのレスポンスとして特定のオブジェクトが常に存在することが明示的に保証されている場合、そのオブジェクトのプロパティにアクセスする際にはオプショナルチェーンを使うべきではありません。なぜなら、そのオブジェクトが期待通りに存在しなかった場合、それはAPIのエラーまたはデータの不整合を示しており、それをコードの中で明示的に検出するべきだからです。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;必須の設定値:&lt;/strong&gt; 例えば、アプリケーション設定を含むオブジェクトがあるとします。その中のいくつかの値がアプリケーションの正常な動作にとって絶対必要である場合、それらの値にアクセスする際にオプショナルチェーンを使用すると、値が存在しない場合にエラーが発生せずに&lt;code&gt;undefined&lt;/code&gt;が返るため、問題が見逃される可能性があります。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;計算に必要な値:&lt;/strong&gt; 例えば、算術演算子を使用して計算を行う場合、undefinedやnullの値を算術演算子で使うとNaN（Not a Number）が結果として出力されます。これが意図した動作でない場合、値の存在チェックを明示的に行うべきです。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;これらのケースでは、オプショナルチェーンを使用すると、本来検出されるべきエラーや問題が見逃され、バグが発生する可能性があります。このようなケースでは、明示的に値の存在をチェックし、適切なエラーハンドリングを行うことが重要です。&lt;/p&gt;&#10;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;p&gt;オプショナルチェーンは、コードを簡潔にし、プロパティの存在チェックを容易にします。ただし、使用している環境がECMAScript 2020以降をサポートしていることを確認してから使用する必要があります。&lt;/p&gt;&#10;&lt;h2 id="寸評"&gt;寸評&#10;&lt;/h2&gt;&lt;p&gt;最初からオプショナルチェーンについて解説を書かせるつもりで質問した。Mozillaの記事と比べてどうだろうか。説明はこちらのほうが易しいように思える。また、「なぜ必要なのか」「使用しないほうがよいケースはあるのか」など、実際に使用するうえで気になる部分についても突っ込んで聞くことで、より実用的な記事になったんじゃなかろうかと思う。&lt;/p&gt;&#10;&lt;p&gt;なお記事自体はすんなり一発でこれだけの長文を出してくれない。適宜書き直させたりツギハギしたりしている。以下は今回のチャット。&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://chat.openai.com/share/eb8b48d6-4b6a-4c84-87cb-9d6f7eac9ce1" target="_blank" rel="noopener"&#10; &gt;https://chat.openai.com/share/eb8b48d6-4b6a-4c84-87cb-9d6f7eac9ce1&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>JavaScriptでオブジェクトのキーと値をループ処理する方法</title><link>https://ai.hack-le.com/javascript-loop/</link><pubDate>Wed, 19 Jul 2023 19:28:20 +0900</pubDate><guid>https://ai.hack-le.com/javascript-loop/</guid><description>&lt;p&gt;初歩的なんだけど割といつもググっているあたりに地力のなさが出ていてつらい。ChatGPT-4に聞いてまとめる。&lt;/p&gt;&#10;&lt;p&gt;まぁ結局は&lt;code&gt;Object.entries()&lt;/code&gt;使おうという記事になる。あと&lt;code&gt;for ... in&lt;/code&gt;時の&lt;code&gt;hasOwnProperty()&lt;/code&gt;の必要性についてとかも書かせてみた。&lt;/p&gt;&#10;&lt;h2 id="イントロ"&gt;イントロ&#10;&lt;/h2&gt;&lt;p&gt;JavaScriptでオブジェクトのキーと値をループ処理するための方法はいくつかありますが、その中でも特に便利で使いやすい方法を3つ紹介します。それぞれの方法について、具体的なコード例とともに詳しく見ていきましょう。&lt;/p&gt;&#10;&lt;h2 id="forinループを使用する"&gt;for&amp;hellip;inループを使用する&#10;&lt;/h2&gt;&lt;p&gt;JavaScriptで最も基本的なオブジェクトのループ処理方法です。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// obj 自身がそのプロパティを持っていることをチェック&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`Key: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;, Value: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;しかし、これはあまり制御力がなく、また配列などの特定のオブジェクトでは順序が保証されないため、使いどころは限定的です。&lt;/p&gt;&#10;&lt;p&gt;hasOwnProperty()が何故必要かについては後述します。&lt;/p&gt;&#10;&lt;h2 id="objectkeysとarrayprototypeforeachを使用する"&gt;Object.keys()とArray.prototype.forEach()を使用する&#10;&lt;/h2&gt;&lt;p&gt;この組み合わせは、オブジェクトのキーを配列として取得し、その配列をループ処理します。こちらの方法では順序が保証されます。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`Key: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;, Value: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="objectentriesとarrayprototypeforeachを使用する"&gt;Object.entries()とArray.prototype.forEach()を使用する&#10;&lt;/h2&gt;&lt;p&gt;こちらはオブジェクトのキーと値を配列として取得し、その配列をループ処理します。Pythonの &lt;code&gt;dict.items()&lt;/code&gt; のように、キーと値のペアをイテレートしたいときに便利です。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`Key: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;, Value: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この方法が最も直感的で、キーと値の両方にアクセスできるため、より複雑な処理に対応可能です。&lt;/p&gt;&#10;&lt;h2 id="補足hasownpropertyについて"&gt;【補足】hasOwnProperty()について&#10;&lt;/h2&gt;&lt;p&gt;最初に紹介した&lt;code&gt;for ... in&lt;/code&gt;ループで、なぜ&lt;code&gt;hasOwnProperty()&lt;/code&gt;が使われているのか、また何故他の2つの手法では使われていないのかについて説明します。&lt;/p&gt;&#10;&lt;p&gt;JavaScriptでは、オブジェクトはプロパティを他のオブジェクトから「継承」することができます。これは、オブジェクトが他のオブジェクトの「プロトタイプ」となり、そのプロパティとメソッドを共有するという特性によるものです。このプロトタイプチェーンという仕組みはJavaScriptの強力な特性の一つですが、オブジェクトをループ処理する際には注意が必要です。&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;for...in&lt;/code&gt;ループを使用すると、オブジェクト自身のプロパティだけでなく、プロトタイプチェーン全体を通じて継承されたプロパティもループされます。&lt;/p&gt;&#10;&lt;p&gt;以下に具体的な例を示します。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extra&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Unexpected!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上記のコードを実行すると、出力は以下のようになります。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;extra&lt;/span&gt; &lt;span class="nx"&gt;Unexpected&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上記の例では、&lt;code&gt;Object.prototype&lt;/code&gt;に新たなプロパティ &lt;code&gt;extra&lt;/code&gt; を追加しています。&lt;code&gt;Object.prototype&lt;/code&gt;はすべてのオブジェクトが継承する基本的なプロトタイプなので、この新たなプロパティはすべてのオブジェクトで利用可能になります。そのため &lt;code&gt;for...in&lt;/code&gt; ループは &lt;code&gt;extra&lt;/code&gt; プロパティも巡回します。&lt;/p&gt;&#10;&lt;p&gt;（注意：&lt;code&gt;Object.prototype&lt;/code&gt;にプロパティを追加することは、一般的には推奨されません。これは全てのオブジェクトに影響を与え、予期しない副作用を引き起こす可能性があります。この例は、&lt;code&gt;for...in&lt;/code&gt; ループと &lt;code&gt;hasOwnProperty()&lt;/code&gt; メソッドの動作を説明するためのものであり、実際のコードではこのような方法は避けるべきです。）&lt;/p&gt;&#10;&lt;p&gt;しかし、通常はオブジェクト自身が持つプロパティだけを対象にしたいと思うでしょう。そのため、ループ内で &lt;code&gt;hasOwnProperty()&lt;/code&gt;メソッドを使用します。このメソッドは、オブジェクト自身が指定されたプロパティを持つ場合にtrueを返し、継承されたプロパティの場合はfalseを返します。&lt;/p&gt;&#10;&lt;p&gt;したがって、 &lt;code&gt;for...in&lt;/code&gt;ループを使用する際には、 &lt;code&gt;hasOwnProperty()&lt;/code&gt;メソッドを使用してループ処理の対象をオブジェクト自身のプロパティに制限することが一般的です。これにより、意図しないプロパティがループ処理の対象となることを防ぎます。&lt;/p&gt;&#10;&lt;p&gt;一方で&lt;code&gt;Object.keys()&lt;/code&gt;や&lt;code&gt;Object.entries()&lt;/code&gt;は、オブジェクト自身が持つ列挙可能なプロパティのキー（あるいはキーと値のペア）だけを取得します。これらのメソッドはプロトタイプチェーンを通じて継承されたプロパティを無視するため、&lt;code&gt;hasOwnProperty()&lt;/code&gt;メソッドを使用してフィルタリングする必要がありません。&lt;/p&gt;&#10;&lt;p&gt;したがって、オブジェクト自身のプロパティだけを対象にしたループ処理を行う場合には、&lt;code&gt;Object.keys()&lt;/code&gt;や&lt;code&gt;Object.entries()&lt;/code&gt;を使用することが推奨されます。これらのメソッドは、キーと値のペアの順序も保証するため、より予測可能で制御可能なループ処理が可能になります。&lt;/p&gt;&#10;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;p&gt;以上、JavaScriptでオブジェクトのキーと値をループ処理するための3つの主な方法を紹介しました。それぞれの特性を理解し、シチュエーションに応じて最適なものを選んでください。コードは動的なものであり、より良い解決策が見つかる可能性もあります。どの方法を選ぶにせよ、常に自分のコードを見直し、最適化の機会を探すことを忘れないでください。&lt;/p&gt;&#10;&lt;h2 id="寸評"&gt;寸評&#10;&lt;/h2&gt;&lt;p&gt;初心者向けの記事ならすぐに書けるね。ついでに深掘りしたいところについて書かせることで、ワンランク上の技術記事になる。なかなか良い感じ。&lt;/p&gt;&#10;&lt;p&gt;さて、恒例の質問例。&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;JavaScriptでオブジェクトのループを回したい&lt;/li&gt;&#10;&lt;li&gt;どれを使えばいいの？&lt;/li&gt;&#10;&lt;li&gt;なるほど。では、Pythonでいうところ dict.items() みたいな挙動をさせたければ、Object.entries()がよさそうだな。&lt;/li&gt;&#10;&lt;li&gt;OK、JavaScriptのキーとペアでループ処理したい時の方法として、ブログ記事風にまとめてくれ。具体的に簡単に試せるコードの例を適宜つけてくれ。また、記事は適度に見出しを入れて構造的にしてくれ。&lt;/li&gt;&#10;&lt;li&gt;for &amp;hellip; in でなぜhasOwnProperty() を使う必要があるかについて、詳細な説明をしたほうがいい。&lt;/li&gt;&#10;&lt;li&gt;for &amp;hellip; in だと意図しないプロパティがあるかもしれないことがわかる、具体的な例はあるか&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;けっこうポイントついて質問していることがわかるだろう。質問一発でぽんと出てくる記事はそのままでは使えない。しかし、突っ込めばそれらしくなってくる。&lt;/p&gt;&#10;</description></item></channel></rss>