字句スコープとは何ですか?


682

字句スコープの簡単な紹介とは何ですか?


89
ポッドキャスト58では、ジョエルは他の場所で回答されたとしても、SOが回答の場になることを望んでいるため、これらのような質問を奨励しています。これは妥当な質問ですが、少し丁寧にすることもできます。
ラルフM.リッケンバッハ

5
@rahul私はそれが古い質問だと理解しています。しかし、2009年でさえ、SOは質問者がそれを解決するためいくつかの基本的な努力をすることを期待していました。現状では、何の努力も示していません。たぶん、それが多くの人が反対票を投じた理由ですか?
PP

13
この質問を書いているとき、質問者が英語に堪能でない(または無能だった)可能性があります
Martin

27
問題は礼儀正しく、彼は自分が何を望んでいるかを言うだけです。答えは自由です。ここでは無分別な丁寧さは必要ありません。
Markus Siebeneicher 14

25
SOのコンテンツを構築するため、このような質問は素晴らしいと思います。IMO、質問に努力がないかどうかを気にします...回答には素晴らしいコンテンツがあり、それがこのメッセージボードで重要なことです。
Jwan622 2014年

回答:


686

例を通してそれらを理解します。:)

まず、Cのような構文のレキシカルスコープ静的スコープとも呼ばれます):

void fun()
{
    int x = 5;

    void fun2()
    {
        printf("%d", x);
    }
}

すべての内部レベルはその外部レベルにアクセスできます。

Lispの最初の実装で使用される動的スコープと呼ばれる別の方法があります。これもCのような構文です。

void fun()
{
    printf("%d", x);
}

void dummy1()
{
    int x = 5;

    fun();
}

void dummy2()
{
    int x = 10;

    fun();
}

ここでfunxdummy1またはdummy2、またはで宣言されたを使用しxて呼び出す関数のいずれかにアクセスできます。funx

dummy1();

5を印刷します

dummy2();

10を印刷します

1つ目はコンパイル時に推定できるため静的と呼ばれ、2つ目は外部スコープが動的で関数のチェーン呼び出しに依存するため動的と呼ばれます。

静的スコープの方が見やすいと思います。ほとんどの言語は、Lispも含めて、最終的にこのようになりました(両方を実行できますか?)。動的スコープは、呼び出された関数にすべての変数の参照を渡すようなものです。

コンパイラーが関数の外部動的スコープを推定できない理由の例として、最後の例を考えてみましょう。このようなものを書くと:

if(/* some condition */)
    dummy1();
else
    dummy2();

呼び出しチェーンは、実行時の条件によって異なります。trueの場合、呼び出しチェーンは次のようになります。

dummy1 --> fun()

条件が偽の場合:

dummy2 --> fun()

funどちらの場合も、の外側のスコープは、呼び出し元呼び出し元の呼び出し元の合計です。

C言語ではネストされた関数や動的スコープは許可されていません。


19
私が見つけた非常に非常に理解しやすいチュートリアルも指摘したいと思います。Arakの例はいいですが、もっと多くの例を必要とする人には短すぎるかもしれません(実際には、他の言語と比較しています。)。見てください。このキーワードは語彙の範囲を理解するのに役立つため、これを理解することが重要です。howtonode.org/what-is-this
CppLearner、2011

9
これは良い答えです。しかし、質問はでタグ付けされていJavaScriptます。したがって、これは受け入れられた回答としてマークされるべきではないと思います。特にJSの語彙範囲は異なります
Boyang

6
非常に良い答え。ありがとうございました。@Boyang同意しない。私はLispコーダーではありませんが、JSにはない動的スコープの例なので、Lispの例は役に立ちました。
dudewad

4
最初は、この例は有効なCコードであると思いましたが、Cに動的スコープがあるかどうか混乱しました。おそらく最後の免責事項をコード例の前に移動できますか?
Yangshun Tay 2017

2
これはまだ非常に役立つ回答ですが、@ Boyangは正しいと思います。この回答は「レベル」を指します。これは、Cが持つブロックスコープの線に沿っています。デフォルトでは、JavaScriptにはブロックレベルのスコープがないため、forループ内が典型的な問題です。JavaScriptの字句スコープは、ES6 letまたはconstが使用されていない限り、関数レベルのみです。
icc97

274

可能な限り短い定義を試してみましょう:

字句スコープは、ネストされた関数での変数名の解決方法を定義します。内部関数には、親関数が返された場合でも、親関数のスコープが含まれます

それだけです!


21
最後の部分:「親関数が戻ったとしても」はクロージャーと呼ばれます。
Juanma Menendez

1
たった一文で字句スコープと閉鎖を理解した。ありがとう!!
ダンジョン

63
var scope = "I am global";
function whatismyscope(){
   var scope = "I am just a local";
   function func() {return scope;}
   return func;
}

whatismyscope()()

上記のコードは「私はただのローカルです」を返します。「私はグローバルです」は返されません。関数func()は、関数whatismyscopeのスコープ下にあるisが最初に定義された場所をカウントするためです。

それが呼び出されているもの(グローバルスコープ/別の関数内からでも)に煩わされることはありません。そのため、私がグローバルであるグローバルスコープの値は出力されません。

これは字句スコープと呼ばれ、「関数は、定義時に有効だったスコープチェーンを使用して実行されます」とJavaScript定義ガイドに従っています。

字句スコープは非常に強力な概念です。

お役に立てれば..:)


3
関数func(){return this.scope;}を記述した場合、もう1つ追加したいと思います。このキーワードを使用するだけで「I am global」が返され、スコープが変更されます
Rajesh Kumar Bhawsar


41

スコープは、関数、変数などが利用できる領域を定義します。たとえば、変数の可用性は、そのコンテキスト内で定義されます。たとえば、関数、ファイル、またはオブジェクトが定義されます。これらは、通常、これらのローカル変数と呼ばれます。

字句部分は、ソースコードの読み取りからスコープを派生できることを意味します。

字句スコープは静的スコープとも呼ばれます。

動的スコープは、定義された後、どこからでも呼び出しまたは参照できるグローバル変数を定義します。ほとんどのProgrammin言語のグローバル変数はレキシカルスコープのものですが、グローバル変数と呼ばれることもあります。つまり、変数をこのコンテキストで使用できるということは、コードを読み取ることから導き出すことができます。インスタンス化または定義を見つけるには、usesまたはincludes句に従う必要があるかもしれませんが、コード/コンパイラーはこの場所の変数について知っています。

対照的に、動的スコープでは、最初にローカル関数を検索し、次にローカル関数を呼び出した関数を検索してから、その関数を呼び出した関数を検索します。以下同様に、呼び出しスタックを上に向かっていきます。「動的」とは、特定の関数が呼び出されるたびに呼び出しスタックが異なる可能性がある変更を指します。そのため、関数は、呼び出し元に応じて異なる変数にヒットする可能性があります。(こちらをご覧ください

ダイナミックスコープの興味深い例については、こちらをご覧ください

詳細については、ここここを参照ください

Delphi / Object Pascalの例

Delphiには字句スコープがあります。

unit Main;
uses aUnit;  // makes available all variables in interface section of aUnit

interface

  var aGlobal: string; // global in the scope of all units that use Main;
  type 
    TmyClass = class
      strict private aPrivateVar: Integer; // only known by objects of this class type
                                    // lexical: within class definition, 
                                    // reserved word private   
      public aPublicVar: double;    // known to everyboday that has access to a 
                                    // object of this class type
    end;

implementation

  var aLocalGlobal: string; // known to all functions following 
                            // the definition in this unit    

end.

Delphiが動的スコープに最も近いのは、RegisterClass()/ GetClass()関数のペアです。使い方はこちらをご覧ください

RegisterClass([TmyClass])が特定のクラスを登録するために呼び出される時間は、コードを読み取ることによって予測できない(ユーザーによって呼び出されるボタンクリックメソッドで呼び出される)場合、GetClass( 'TmyClass')を呼び出すコードは結果かどうか。RegisterClass()の呼び出しは、GetClass()を使用してユニットの字句スコープ内にある必要はありません。

動的スコープのもう1つの可能性は、Delphi 2009の匿名メソッド(クロージャ)です。これは、呼び出し側関数の変数を知っているためです。そこからの呼び出しパスを再帰的にたどらないため、完全に動的ではありません。


2
実際には、クラスが定義されているユニット全体でプライベートにアクセスできます。これがD2006で「厳格なプライベート」が導入された理由です。
マルコファンデフォールト

2
平易な言語の+1(説明が
Pops

36

@Arakのような人々からの、言語にとらわれないフル機能の回答が大好きです。ただし、この質問にはJavaScriptのタグが付けられいたため、この言語に固有のいくつかのメモを欠かせません。

JavaScriptでは、スコープの選択は次のとおりです。

  • 現状のまま(スコープ調整なし)
  • 語彙 var _this = this; function callback(){ console.log(_this); }
  • バウンド callback.bind(this)

JavaScriptには実際には動的スコープがありません。キーワードを.bind調整しthis、それは近いですが、技術的に同じではありません。

これは両方のアプローチを示す例です。これは、コールバックのスコープを決定するたびに行うため、Promise、イベントハンドラーなどに適用されます。

字句

Lexical ScopingJavaScriptでのコールバックとは次のようなものです。

var downloadManager = {
  initialize: function() {
    var _this = this; // Set up `_this` for lexical access
    $('.downloadLink').on('click', function () {
      _this.startDownload();
    });
  },
  startDownload: function(){
    this.thinking = true;
    // Request the file from the server and bind more callbacks for when it returns success or failure
  }
  //...
};

バウンド

スコープする別の方法は、使用することFunction.prototype.bindです:

var downloadManager = {
  initialize: function() {
    $('.downloadLink').on('click', function () {
      this.startDownload();
    }.bind(this)); // Create a function object bound to `this`
  }
//...

これらの方法は、私の知る限り、行動的に同等です。


使用bindしてもスコープには影響しません。
ベンアストン

12

字句スコープ:関数の外部で宣言された変数はグローバル変数であり、JavaScriptプログラムのどこにでも表示されます。関数内で宣言された変数には関数スコープがあり、その関数内に出現するコードにのみ表示されます。


12

IBMは次のように定義しています。

宣言が適用されるプログラムまたはセグメント単位の部分。ルーチンで宣言された識別子は、そのルーチン内およびすべてのネストされたルーチン内で認識されます。ネストされたルーチンが同じ名前のアイテムを宣言している場合、外側のアイテムはネストされたルーチンでは使用できません。

例1:

function x() {
    /*
    Variable 'a' is only available to function 'x' and function 'y'.
    In other words the area defined by 'x' is the lexical scope of
    variable 'a'
    */
    var a = "I am a";

    function y() {
        console.log( a )
    }
    y();

}
// outputs 'I am a'
x();

例2:

function x() {

    var a = "I am a";

    function y() {
         /*
         If a nested routine declares an item with the same name,
         the outer item is not available in the nested routine.
         */
        var a = 'I am inner a';
        console.log( a )
    }
    y();

}
// outputs 'I am inner a'
x();

8

字句スコープとは、ネストされた関数のグループでは、内部関数が親スコープの変数やその他のリソースにアクセスできることを意味します。つまり、子関数はその親の実行コンテキストに字句的にバインドされます。字句スコープは、静的スコープとも呼ばれます

function grandfather() {
    var name = 'Hammad';
    // 'likes' is not accessible here
    function parent() {
        // 'name' is accessible here
        // 'likes' is not accessible here
        function child() {
            // Innermost level of the scope chain
            // 'name' is also accessible here
            var likes = 'Coding';
        }
    }
}

字句スコープについて気付くのは、順方向に機能することです。つまり、名前はその子の実行コンテキストからアクセスできます。しかし、それはその親に対して逆方向には機能しません。つまり、変数likesはその親からアクセスできません。

これは、異なる実行コンテキストで同じ名前の変数が実行スタックの上から下に優先されることも示しています。最も内側の関数(実行スタックの最上位のコンテキスト)にある、別の変数と同様の名前を持つ変数は、優先順位が高くなります。

これはここから取得されていることに注意してください


8

単純な言語では、字句スコープはスコープ外で定義された変数であるか、スコープ内で上位スコープが自動的に使用できるため、そこに渡す必要はありません。

例:

let str="JavaScript";

const myFun = () => {
    console.log(str);
}

myFun();

//出力:JavaScript


2
例を挙げて、私にとっては最も短くて最良の答えを示します。ES6の矢印機能がで問題を解決することが追加された可能性がありbindます。それらがあれば、bindもう必要ありません。この変更の詳細については、stackoverflow.com
a / 34361380/11127383を参照して

4

語彙的および動的スコープに関する会話には欠落している重要な部分があります。スコープ付き変数の存続期間の簡単な説明-または変数にいつアクセスできるかです。

動的スコーピングは、「グローバル」スコーピングにごくわずかしか対応していません。これは、私たちが伝統的に考えている方法です(この2つを比較した理由は、すでに言及ているためです。また、リンクされた記事の説明は特に好きではありません)); おそらく、リンクされた記事によれば、「... [it]はグローバルスコープ変数の代わりとして役立つ」とはいえ、おそらくグローバルとダイナミックを比較しない方がいいでしょう。

では、わかりやすい英語で、2つのスコープメカニズムの重要な違いは何ですか?

字句スコープは、上記の回答全体で非常によく定義されています。字句スコープ変数は、それが定義された関数のローカルレベルで使用できます。

ただし、これはOPの焦点では​​ないため、動的スコープはそれほど注目されていません。注目されたことは、おそらくもう少し必要であることを意味します(他の回答に対する批判ではなく、「ああ、その答えにより、もう少しあるといいのですが」)。それで、もう少しです:

動的スコープとは、関数呼び出しの存続期間中、または関数の実行中に、大きなプログラムから変数にアクセスできることを意味します。本当に、ウィキペディアは実際に2つの違いを説明することで素晴らしい仕事をします。わかりにくくしないように、動的スコープについて説明するテキストを次に示します。

... [I] n動的スコープ(または動的スコープ)、変数名のスコープが特定の関数の場合、そのスコープは関数が実行されている期間です。関数の実行中は変数名が存在します、その変数にバインドされていますが、関数が戻った後、変数名は存在しません。


3

字句スコープとは、関数がその周囲のスコープではなく、定義されたコンテキストで変数を検索することを意味します。

詳細が必要な場合は、Lispで字句スコープがどのように機能するかを確認してください。Common Lispの動的変数と語彙変数でカイルクローニンが選択した回答は、ここでの回答よりもはるかに明確です。

偶然にも私はLispクラスでのみこれについて学びましたが、それはたまたまJavaScriptにも当てはまります。

このコードをChromeのコンソールで実行しました。

// JavaScript               Equivalent Lisp
var x = 5;                //(setf x 5)
console.debug(x);         //(print x)
function print_x(){       //(defun print-x ()
    console.debug(x);     //    (print x)
}                         //)
(function(){              //(let
    var x = 10;           //    ((x 10))
    console.debug(x);     //    (print x)
    print_x();            //    (print-x)
})();                     //)

出力:

5
10
5

3

JavaScriptの字句スコープとは、関数の外部で定義された変数が、変数宣言の後に定義された別の関数の内部でアクセスできることを意味します。しかし、その反対は真実ではありません。関数内で定義された変数には、その関数の外からはアクセスできません。

この概念は、JavaScriptのクロージャーで頻繁に使用されます。

以下のコードがあるとしましょう。

var x = 2;
var add = function() {
    var y = 1;
    return x + y;
};

これで、add()を呼び出すと、3が出力されます。

したがって、add()関数は、xメソッド関数addの前に定義されているグローバル変数にアクセスしています。これは、JavaScriptの字句スコープのために呼び出されます。


コードスニペットが動的にスコープ指定された言語用であったことを考慮してください。add()関数が所定のコードスニペットの直後に呼び出された場合、3も出力されます。字句スコープとは、関数がローカルコンテキストの外部のグローバル変数にアクセスできることを意味するだけではありません。したがって、サンプルコードは実際に字句スコープの意味を示すのに役立ちません。コードで字句スコープを示すには、実際には反例または少なくともコードの他の可能な解釈の説明が必要です。
Cパーキンス

2

字句スコープとは、実行スタックの現在の位置から見える識別子(変数、関数など)の語彙集のことです。

- global execution context
    - foo
    - bar
    - function1 execution context
        - foo2
        - bar2
        - function2 execution context
            - foo3
            - bar3

fooまた、barグローバルであるため、常に使用可能な識別子のレキシコン内にあります。

ときにfunction1実行され、それはの辞書へのアクセス権を持っているfoo2bar2foo、とbar

いつ function2実行され、それはの辞書へのアクセス権を持っているfoo3bar3foo2bar2foo、とbar

グローバル関数や外部関数が内部関数識別子にアクセスできないのは、その関数の実行がまだ発生していないため、その識別子がメモリに割り当てられていないためです。さらに、その内部コンテキストが実行されると、実行スタックから削除されます。つまり、そのコンテキストのすべての識別子がガベージコレクションされ、使用できなくなります。

最後に、ネストされた実行コンテキストが常にその祖先の実行コンテキストにアクセスできるのはこのためです。したがって、識別子のより大きなレキシコンにアクセスできます。

見る:

上記の定義を単純化するのに役立つ@ robr3rdに特に感謝します。


1

ここでは、この問題について別の角度から説明します。一歩下がって、解釈のより大きなフレームワーク(プログラムの実行)におけるスコーピングの役割を調べます。言い換えれば、ある言語のインタープリター(またはコンパイラー)を構築していて、プログラムとそれに何らかの入力が与えられた場合に、出力を計算する責任があると想像してください。

解釈には次の3つを追跡することが含まれます。

  1. 状態-つまり、ヒープとスタック上の変数と参照メモリの場所。

  2. その状態での操作-つまり、プログラムのすべてのコード行

  3. 環境所与た動作が実行さ-つまり、投影状態動作に。

インタープリターは、プログラムのコードの最初の行から開始し、その環境を計算し、その環境で行を実行して、プログラムの状態への影響をキャプチャします。次に、プログラムの制御フローに従って次のコード行を実行し、プログラムが終了するまでプロセスを繰り返します。

操作の環境を計算する方法は、プログラミング言語で定義された一連の正式なルールによるものです。「バインディング」という用語は、プログラムの全体的な状態から環境内の値へのマッピングを表すために頻繁に使用されます。「全体的な状態」とは、グローバルな状態を意味するのではなく、実行の任意の時点で到達可能なすべての定義の合計を意味することに注意してください)。

これは、スコーピング問題が定義されるフレームワークです。次に、オプションの次の部分に進みます。

  • インタプリタの実装者として、環境をプログラムの状態にできるだけ近づけることで、タスクを簡略化できます。したがって、コード行の環境は、前の行が割り当て、関数呼び出し、関数からの戻りであったかどうかに関係なく、その操作の効果が適用された前のコード行の環境によって単純に定義されます。または、whileループなどの制御構造。

これは、動的スコープの要点であり、コードが実行される環境は、実行コンテキストによって定義されたプログラムの状態にバインドされます。

  • または、自分の言語を使用しているプログラマーのことを考え、変数が取り得る値を追跡するという彼または彼女のタスクを簡略化することもできます。過去の実行全体の結果についての推論には、経路が多すぎて複雑すぎます。字句スコープは、現在の環境を現在のブロック、関数またはスコープの他の単位、およびその親(つまり、現在のクロックを囲むブロック、または現在の関数を呼び出した関数を囲むブロック)で定義された状態の部分に制限することで、これを支援します。

言い換えると、字句スコープを使用すると、コードが認識する環境は、ブロックや関数など、言語で明示的に定義されたスコープに関連付けられた状態にバインドされます。


0

古代の質問ですが、これが私の見解です。

字句(静的)スコープとは、ソースコード内の変数のスコープを指します

JavaScriptのような言語では、関数を渡したり、さまざまなオブジェクトにアタッチしたり、再アタッチしたりできますが、そのスコープは、その時点で関数を呼び出しているユーザーに依存しますが、そうではありません。スコープをそのように変更すると動的スコープになり、JavaScriptはthisオブジェクト参照を使用する場合を除いてそれを行いません。

ポイントを説明するには:

var a='apple';

function doit() {
    var a='aardvark';
    return function() {
        alert(a);
    }
}

var test=doit();
test();

この例では、変数aはグローバルに定義されていますが、doit()関数内でシャドウされています。この関数は別の関数を返します。この関数は、ご覧のように、a自身のスコープ外の変数に依存しています。

これを実行すると、使用される値は aardvark、ではないapple、それはの範囲にあるもののれ、test()機能、元の関数のレキシカルスコープではありません。つまり、使用されるスコープは、ソースコードに表示されるスコープであり、関数が実際に使用されるスコープではありません。

この事実は、迷惑な結果をもたらす可能性があります。たとえば、関数を個別に整理し、イベントハンドラーなどで時間が来たらそれらを使用する方が簡単だと判断する場合があります。

var a='apple',b='banana';

function init() {
  var a='aardvark',b='bandicoot';
  document.querySelector('button#a').onclick=function(event) {
    alert(a);
  }
  document.querySelector('button#b').onclick=doB;
}

function doB(event) {
  alert(b);
}

init();
<button id="a">A</button>
<button id="b">B</button>

このコードサンプルは、それぞれ1つずつ実行します。字句スコープのため、ボタンがAは内部変数を使用しは使用Bしないます。ネスト関数は、思ったよりも多くなる可能性があります。

ちなみに、どちらの例でも、含まれている関数関数がコースを実行しても、内側のレキシカルスコープの変数が存続していることに気付くでしょう。これはクロージャと呼ば、外部関数が終了した場合でも、ネストされた関数が外部変数にアクセスすることを指します。JavaScriptは、これらの変数が不要になったかどうかを判断するのに十分スマートである必要があり、不要な場合はガベージコレクションを実行できます。


-1

私は通常例で学びます、そしてここに少し何かがあります:

const lives = 0;

function catCircus () {
    this.lives = 1;
    const lives = 2;

    const cat1 = {
        lives: 5,
        jumps: () => {
            console.log(this.lives);
        }
    };
    cat1.jumps(); // 1
    console.log(cat1); // { lives: 5, jumps: [Function: jumps] }

    const cat2 = {
        lives: 5,
        jumps: () => {
            console.log(lives);
        }
    };
    cat2.jumps(); // 2
    console.log(cat2); // { lives: 5, jumps: [Function: jumps] }

    const cat3 = {
        lives: 5,
        jumps: () => {
            const lives = 3;
            console.log(lives);
        }
    };
    cat3.jumps(); // 3
    console.log(cat3); // { lives: 5, jumps: [Function: jumps] }

    const cat4 = {
        lives: 5,
        jumps: function () {
            console.log(lives);
        }
    };
    cat4.jumps(); // 2
    console.log(cat4); // { lives: 5, jumps: [Function: jumps] }

    const cat5 = {
        lives: 5,
        jumps: function () {
            var lives = 4;
            console.log(lives);
        }
    };
    cat5.jumps(); // 4
    console.log(cat5); // { lives: 5, jumps: [Function: jumps] }

    const cat6 = {
        lives: 5,
        jumps: function () {
            console.log(this.lives);
        }
    };
    cat6.jumps(); // 5
    console.log(cat6); // { lives: 5, jumps: [Function: jumps] }

    const cat7 = {
        lives: 5,
        jumps: function thrownOutOfWindow () {
            console.log(this.lives);
        }
    };
    cat7.jumps(); // 5
    console.log(cat7); // { lives: 5, jumps: [Function: thrownOutOfWindow] }
}

catCircus();

-1

このトピックは組み込みbind関数と強く関連しており、ECMAScript 6 Arrow Functionsで導入されています。本当に面倒でした。なぜなら、使用したいすべての新しい「クラス」(実際には関数)メソッドについてbind、スコープにアクセスするためにこれを行わなければならなかったからです。

デフォルトでは、JavaScript thisは関数のスコープを設定しません(コンテキストをに設定しませんthis)。デフォルトでは、必要なコンテキストを明示的に指定する必要があります。

矢印の機能は自動的に、いわゆるますレキシカルスコープ(その包含ブロック内の変数の定義へのアクセス権を持っています)。アロー関数を使用するthisと、アロー関数が最初に定義された場所に自動的にバインドされ、このアロー関数のコンテキストはそれを含むブロックです。

以下の最も単純な例で実際にどのように機能するかを確認してください。

矢印関数の前(デフォルトでは字句スコープなし):

const programming = {
  language: "JavaScript",
  getLanguage: function() {
    return this.language;
  }
}

const globalScope = programming.getLanguage;
console.log(globalScope()); // Output: undefined

const localScope = programming.getLanguage.bind(programming);
console.log(localScope()); // Output: "JavaScript"

矢印関数を使用(デフォルトでは字句スコープ):

const programming = {
  language: "JavaScript",
  getLanguage: function() {
    return this.language;
  }
}

const arrowFunction = () => {
    console.log(programming.getLanguage());
}

arrowFunction(); // Output: "JavaScript"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.