参照 - みる会図書館


検索対象: 開眼!JavaScript : 言語仕様から学ぶJavaScriptの本質
66件見つかりました。

1. 開眼!JavaScript : 言語仕様から学ぶJavaScriptの本質

24 ー 1 章 JavaSc 「 ipt オブジェクト じオプジェクトにポイントしているということです。 ここで覚えておかないといけないことは、オプジェクトは参照を保持しているた め、あるオプジェクトを変更した場合、そのオプジェクトを参照しているすべての変 数も同時に変更されるということです。先の例では、 my0bject と copy0fMy0bject は 同じオプジェクトを参照しているので、一方を変更するともう片方にもその変更が反 映されます。 NOTE プリミティブ値はオブジェクトのように扱われる場合でも、オブジェクトのように参 照によってコピーされることはなく、値そのものが保存・コピーされます。 ・オブジェクトの内容を別の変数に複製する場合は、コピー元のオブジェクトからすべ ての値を抜き取って、新しいオブジェクトに注入する必要があります。 1 .14 オプジェクトは同値判定に参照を使用 オプジェクトを比較するとき、これらは同じオプジェクトを参照している場合 ( っ まり、 2 つのオプジェクトが同じ参照アドレスを持っている ) のみ同値となります。 同じ値を持っているものの、それぞれが参照する実体が異なる場合は同値とは判定さ れません。 次の例の objectFoo と obje ( tBar は全く同じプロバティと値を持っているオプジェ = 演算子 ( 同値演算子 ) で比較した場合、 JavaScript はこれらを違う クトですが、 ものであると判定します。 same ・ } ; = { same: / / JavaScript でオブジェクトの同値比較を行う場合、比較対象のオブジェクトが同じ型で同じ 値をもっているかどうかは同値の基準とはならない。 console. 10g(0bjectF00 = = 0bjectBar); / / 出力 : false / / オブジェクトが同値とみなされる場合 var 0bjectA = { f00 : 'bar' } ; var 0bjectB = 0bjectA; var 0bjectF00 var 0bjectBar console. 10g(0bjectA = = 0bjectB); / / 出力 : true / / これらのオブジェクトは同じオブジェクトを参照しているため同値

2. 開眼!JavaScript : 言語仕様から学ぶJavaScriptの本質

7.7 クロージャはスコープチェーンによって生成される ー 103 スコープ外 から変数に 直接アクセス はできない function() スコープ var 1 [ 0 ] スコープ var funcArray[] 本体 ( 0n501e.10 i ( i が存在しない ) return funcArray; 本体 関数実行時にスコープチェーンをたどり 同じ変数を参照する [ 2 ] スコープ 参照 関数呼び出し 10gE 1ementNumber [ ] con 501e.10 i [ 1 ] スコープ 本体 本体 C0n501e.10 i 図 7-1 子関数の i はすべて同じ変数を参照する 次の例は上記の例を一歩進めて、当初の意図どおりインデックスを出力するように 子関数を実行しても、 console. log(i) は常に 3 を出力します。 fun ( Array が返される時点でこの変数 i には 3 が代入されています。そのため、どの れの環境にコピーしているわけではなく、同じ変数 i を参照しています。そして配列 変数 i を参照しています ( 図 7-1 参照 ) 。つまり、子関数たちは変数 i の値をそれぞ 子関数が変数 i を参照する際、スコープチェーンをたどって親関数のスコープにある れる return function() { console. log(i); } ; / / バラメータに i を指定しているため、この関数スコープにローカル変数 i が定義さ var func = function(i) { var 1 ; var funcArray = [ ] ; var logElementNumber = function() { ne X します。 for (i = 0 ; i く 3 ; funcArray[i] 要素に格納 return funcArray; = func(i); 〃インデックスを出力する関数を funcArray のそれぞれの

3. 開眼!JavaScript : 言語仕様から学ぶJavaScriptの本質

1 . 1 6 typeof 演算子の戻り値ー 25 同じオプジェクトにポイントしている変数を比較した場合、それらは変数に同じ 「アドレス」を保持しているため同値とみなされます。逆に、個別に生成された変数 が複数存在する場合、それらの型が同じで、全く同じプロバティを持っているとして も同値とはみなされません。 1 ゴ 5 オプジェクトは動的なプロバティを持つ 1.13 節の例のように新しい変数に既存のオプジェクトを代入する場合、そのオプ ジェクトはコピーされません。この特性のため、オプジェクトは参照型と呼ばれるこ とがあります。メモリ上に存在するオプジェクトは、そのオプジェクトを参照する変 数をいくつでも持っことができ、それらの変数はオプジェクトの実体が変更されても 常にそのオプジェクトを参照します。 var 0bjA = { property: ・ value ・ } ; var pointerl = ObjA; var pointer2 = pointerl; / / 0bjA. property を変更すると、すべての参照がアップデートされる 0bjA. property = null; console. 10g(0bjA. property, pointerl. property, pointer2. property); / / 出力 : ・ null null null ・ / / 0bjA 、 pointerl 、 pointer2 はすべて同じオブジェクトを参照している 上記の例のように、動的なオプジェクトプロバティを生成することができます。オプ ジェクトを定義し、そのオプジェクトへの新たな参照を生成した後にオプジェクトを 変更すると、そのオプジェクトを参照するすべての変数にその変更が反映されます。 1.16 typeof 演算子の戻り値 typeof 演算子は値の型を返します。しかし、 typeof が返す値は一貫性に欠けるた め気をつける必要があります。次の例で typeof 演算子によって返される値を示しま す。

4. 開眼!JavaScript : 言語仕様から学ぶJavaScriptの本質

164 ー 付録 A レビュー 値で、オプジェクトのように扱われるまではオプジェクトの性質を持たな 一旦オプジェクトのように扱われると、 JavaScript は裏で一時的なラッ パーオプジェクトを生成し、プリミテイプ値をオプジェクトのように仕立て る。 0bject() 、 Array() 、 String() 、 Number() 、 B001ean() 、 Function() 、 Date() 、 RegExp() 、 Error() のコンストラクタ関数が new 演算子を伴って呼 ばれた場合、オプジェクトが生成される。生成されたオプジェクトは複合型 もしくは参照型の値とも呼ばれる。 プリミテイプ型の変数には値が格納される。プリミテイプ型の変数がコピー されると、文字通り変数が複製される。一方、オプジェクトを格納する変数 には、実際にはオプジェクトへの参照が格納されている。したがってこれが コピーされると、変数の値自体ではなく、参照がコピーされる。 プリミテイプ型の変数を同値比較 ( = = ) する場合は、それらの値が同じで あれば同値とみなされる。一方、オプジェクトを同値比較する場合は、同じ 参照値を持っている場合にのみ同値とみなされる。つまり、同じオプジェク トを参照している場合のみ同値とみなされる。 JavaScript のオプジェクトは動的プロバティを持つ。 JavaScript はミュータブル ( 可変 ) であり、ネイテイブオプジェクトやユー ザ定義オプジェクトのプロバティはいつでも変更することができる。 オプジェクトプロバティの取得・設定・変更はドット表記法もしくはプラ ケット表記法で行う。プラケット表記法はオプジェクトプロバティの名前を 変数や式を使ってアクセスする際に有利となり、場合によっては必須とな る。 オプジェクトプロバティを参照する際、最初に参照されたオプジェクト自身 のプロバティを検索する。そこに該当するプロバティが存在しない場合、 そのオプジェクトのコンストラクタ関数の prototype プロバティ内を検索 し、プロバティを発見するまでプロトタイプチェーンをたどって最終的に 0bje ( t ( ) コンストラクタの prototype プロバティを検索する。こでも見

5. 開眼!JavaScript : 言語仕様から学ぶJavaScriptの本質

6.4 入れ子関数内で this を見失う問題をスコープチェーンを使って回避する一 89 さて次は、下の例のように無名関数を f00. funcl ( ) に渡した場合に何がおこるかを 考えてみてください。無名関数が f00. funcl ( ) ( 関数内にネストされた関数 ) の内部 で呼ばれた場合、無名関数の内部で呼ばれる this の値はグローバルオプジェクトを 参照します。 社 : ″ 'sfiddle. net/ 、 se ・市 s var f00 = { funcl : function(bar) { bar(); / / この例では、引数として渡された無名関数が実行され、 f00 ではなく window を出力 console. log(this); / / しかしこの this は f00 オブジェクトへの参照 f00. funcl( function() { console. log(this); } ) ; / / 無名関数を引数として渡し実行 これでもう忘れることはありませんね。 this が呼ばれる関数が他の関数に内 包されている場合や、他の関数コンテクストから this が呼ばれた場合にはその this はグローバルオプジェクトを参照します ( もう一度言いますが、この仕様は ECMAScript5 で修正されます ) 。 6.4 入れ子関数内で this を見失う問題を スコープチェーンを使って回避する 前節の例のように入れ子関数内で this の値を見失わないためには、親の関数に this への参照を保存しておいて、スコープチェーンを使って参照すればよいのです。 次の例では入れ子関数からもアクセスできる that という変数を設定して、 this が保 持するオプジェクトへの参照をそこに確保しておくことによって、入れ子関数のため に親関数のコンテクストを保持しています。 は・ $fiddle 0 $e ・ 6 var my0bject myProperty: ・ I can see the light ・ , myMethod : function( ) { var that = this; / / this (my0bject) への参照を myMeth0d スコープに保持 var he1perFunction = function() { / / ネストされた子関数

6. 開眼!JavaScript : 言語仕様から学ぶJavaScriptの本質

88 ー 6 章 this 特に関数が宣言時とは別のコンテクストに存在する変数やプロバティに渡されて実 行される場合など、関数が呼び出されるコンテクストによって this の値が変化する ということをよく覚えておいてください。 this と arguments 以外のすべての変数は静的スコープ (Lexical Scope) に従います。ス コープについては 7 章で詳しく説明します。 NOTE 6.3 入れ子関数内では、 this は グローバルオプジェクトを参照する 関数が他の関数の入れ子である場合、入れ子関数内の this は何を参照しているの かを疑問に思うかもしれません。このようなケースでは、残念ながら ECMAScript3 の this は完全に方向を誤っており、関数が定義されているオプジェクトではなくグ ローバルオプジェクトを参照してしまいます。 次の例では、 func2() 関数と func3() 関数の中で、 this が my0bject を参照せすに グローバルオプジェクト (window) を参照している様子がわかります。 var my0bject funcl: function() { console. log(this); / / 出力 my0bject var func2 = function() { console. log(this) / / 出力 : window - これ以降の入れ子内では this はグローバ ルオブジェクトを参照 var func3 = function() { console. log(this) ; / / 出力 : window my0bject. funcl() ; ありがたいことに、 ECMAScript5 ではこの仕様が修正されます。しかし今のとこ ろは、関数を他の関数に値として渡す場合には、この苦しい仕様を理解しておいてく ださい ( 6.4 節で回避方法を紹介します ) 。

7. 開眼!JavaScript : 言語仕様から学ぶJavaScriptの本質

6.7 プロトタイプメソッド内の this は生成されるインスタンスを参照する 6.7 プロトタイプメソッド内の this は 生成されるインスタンスを参照する 93 コンストラクタの prototype に追加された関数を実行する際、そのプロトタイプ関 数内の this はメソッドが呼ばれたインスタンスを参照します。 たとえば、フルネームを渡すためのパラメータ x を持つ Person() コンスト ラクタを作成したとします。このコンストラクタで生成する Person() インスタ ンスのフルネームにアクセスするために、 Person. prototype のメソッドとして whatIsMyFu11Name() メソッドを加えておきます。これにより、すべての Pe て son ( ) イ ンスタンスが whatIsMyFu11Name() メソッドを継承します。このメソッドの実行中に this にアクセスすると、その this はメソッドを呼び出したインスタンスを参照しま す ( すなわち、そのインスタンスのプロバティにもアクセスすることができます ) 。 次の例では 2 つの person オプジェクト (cody と lisa) と、それらのインスタン スにアクセスするために this を使う whatIsMyFu11Name メソッドを生成します。 ne e 証 F ・ 2 を持つ。 Notes を参照 * / prototype に fu11Name プロバティを設定し、 Person と 0bject 両方の prototype に fullName プロバティ ンスタンスが fu11Name プロバティを持っていない場合はプロトタイプチェーンをたどる。 0bject. / * 次の例では、デフォルトの fu11Name の値を設定する。プロトタイプチェーンが有効なので、イ console. log(cody. whatIsMyFullName(), lisa. whatIsMyFullName()); / / プロトタイプ継承された whatIsMyFu11Name() メソッドを呼ぶ var lisa = new person('lisa lindley' ) ; var cody = new Person('cody lindley ・ ) ; たインスタンスを参照する return this. fullName; / / this は Person() コンストラクタではなく、 Person() から生成され person. prototype. whatIsMyFullName = function( ) { if(x) { this. fu11Name = x; } ; var person = function(x){

8. 開眼!JavaScript : 言語仕様から学ぶJavaScriptの本質

82 ー 5 章グローバルオブジェクト が与えられていない環境も存在します ) 。 2 つ目はグロ ことです。次の例で両方の方法を試します。 windowRef2 = this; windowRef1 = window; va て f00 = ーノヾルスコ ープで this を使う console. 10g(windowRef1, windowRef2) ; / / window オプジェクトへの参照を出力 ( onsole. 10g(windowRef1. f00, windowRef2. f00 ) ; / / 出力 : ・ bar ' 上記のコードでは、 2 つの変数に明示的にグローバルオプジェクトへの参照を格納 し、それらの変数を介してグローバル変数 f00 の値を取得しました。 5.5 グローバルオプジェクトは暗黙的に参照される グローバルオプジェクトは暗黙的に参照されるため、通常は参照を使うことはあ りません。たとえば Web プラウザ環境で window. alert と alert は基本的に同じで す。明示的に記述しなくても、 JavaScript が自動的にグローバルオプジェクトスコー プを補います。グローバルオプジェクトはスコープチェーンの最後に参照される場所 なので、グローバルオプジェクトは常に暗黙的に指し示されています。次の例では、 Web プラウザのグローバルスコープに格納されている alert 関数を使ってみます。 :/TsfiddIe,netPse ・ a/ZGDP = { 〃暗黙的に window オプジェクトに格納される ( つまり、 window. f00 と同じ ) var f00 fooMethod : function ( ) { alert('foo ・ + 'bar'); / / window オプジェクトを暗黙的に指している window. alert( ・ f00 ・ + 'bar' ) ; / / window オブジェクトを明示的に指定し、上の行と 同じ効果を得ている f00. fooMethod() ; 同じ ) / / window オブジェクトを暗黙的に指している (window. f00. fooMethod() と

9. 開眼!JavaScript : 言語仕様から学ぶJavaScriptの本質

1 . 1 3 にします。 オブジェクトはどのように保存・複製されるか 23 本節で登場するオブジェクト ( 「複合型」 ) は、他の文書では「複合オブジェクト」や「参 照型」と呼ばれることもあります。これらの名前はすべて、プリミティプ型を除いたすべ ての JavaSc 「 ipt の値 ( すなわち「オプジェクト」 ) の特徴を言い表しています。プリミ ティプ型は値渡しとなり、複数の要素で構成することができません。複合型は参照渡しと なり、自身に他の要素を内包することができます。 1 ゴ 3 オプジェクトはどのように保存・複製されるか オプジェクトは参照によって保存・操作される、ということの理解が非常に重要で す。オプジェクトを持った変数を宣言する際、値 ( 実体 ) はメモリ上のあるアドレス に保存されます。その値を参照する場合は、値の名前 ( 変数名やプロバティ名 ) を 使ってその変数が保持するメモリ上のアドレスにアクセスし、その場所に存在する値 を取得します。 この事実は、特にオプジェクトのコピーを行う場合の動作を理解するために重要で す。次の例では、 my0bject という変数にオプジェクトを格納します。その my0bject を ( opy0fMy0bject 変数にコピーします。しかし実はそれはオプジェクトのコピーで はなく、正確にはオプジェクトが存在するアドレスのコピーです。 NOTE var my0bject = { } ; var copy0fMy0bject = my0bject; / / 値が渡されるのではなく、参照が渡される my0bject. f00 = ' bar' ; / / my0bject の値を操作 / * ここで my0bject と ( opy0fMyObject の内容を出力すると、両方が f00 オブジェクトを保持し ている。これらの変数は同じオブジェクトを参照している。 * / ( onsole. 10g(my0bject, copy0fMy0bject) ; / / 出力・ 0bject { f00 = " b 訂 " } 0bject { f00 = " b 訂 " } 値を直接保持するプリミテイプ型とは違い、オプジェクトは実体への参照を保持し ています。そのため、オプジェクトを他の変数に代入する場合、実際の値はコピー されず、そのオプジェクトの参照 ( アドレス ) がコピーされます。先の例の場合、 my0bject と copy0fMy0bject の 2 つの変数はメモリ上の同じ場所に格納されている同

10. 開眼!JavaScript : 言語仕様から学ぶJavaScriptの本質

XViii ー 目次 グローバルオプジェクトにアクセスする .. 5.4 グローバルオプジェクトは暗黙的に参照される .. 5.5 ( 1 ワ 0 5 【 06 一 8 一 8 8 6 章 this . 6.1 this とは何か、および this は何を参照するか . this の値はどのように決められるのか ? . 6.2 6.3 入れ子関数内では、 this はグローバルオプジェクトを参照する 6.4 入れ子関数内で this を見失う問題をスコープチェーンを使って 回避する .. … 89 call() や叩 ply ( ) を使って this の値をコントロールする .. … 90 6.5 6.6 this キーワードをユーザ定義のコンストラクタ関数で使う .. … 91 6.7 プロトタイプメソッド内の this は生成されるインスタンスを 参照する . スコープとクロージャ .. 7 章 JavaScript のスコープ JavaScript はプロックスコープを持たない 7.2 7.3 関数内で変数を定義する際は常に var を使い、スコープの穴を 避ける .. スコープチェーン ( 静的スコープ ) .. スコープチェーンの検索は最初に発見した値を返す 99 スコープは関数実行時ではなく関数定義時に決められる .. … 100 7.6 クロージャはスコープチェーンによって生成される .. … 101 7.7 グローバルスコープで宣言されている関数もクロージャである 7.8 … 106 … 107 … 107 … 110 … 88 … 93 5 5 6 9 “ 9 、 9 … 97 … 98 7.4 7.5 ( マスキング ) 8 章 関数の prototype プロバティ . 8.1 プロトタイプチェーン .. なぜ proto Ⅳ pe プロバティが重要なのか . 8.2