質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

7995閲覧

Node.jsでのグローバル変数について

mosin_nozomi

総合スコア29

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2018/09/30 15:29

オライリー本のオブジェクト指向JavaScriptの原則にてグローバル変数の解説で以下のようなコードがありました。

javascript

1function say() { 2 console.log(this.name); 3} 4 5var person1 = { 6 name: "Nico", 7 say: say 8}; 9 10var person2 = { 11 name: "Greg", 12 say: say 13}; 14 15var name = "Michael"; 16 17person1.say(); 18// => "Nico" 19 20person2.say(); 21// => "Greg" 22 23say(); 24// => "Michael" 25 26//実際はMichaelではなくundefinedが表示される 27 28//var name = "Michael" 29//ではなく 30//name = "Michael" 31//とすると 32//Michaelが表示されることが確認できた。

person1とperson2のsay()については、thisがそれぞれpersonのオブジェクトに割り当てられるためNicoとGregが出力されるのは分かるのですが

var nameでグローバル変数のnameに"Michael"が代入されているはずなのにsayを実行するとundefinedになってしまっています。

書籍内でもMichaelが期待される出力なのですが、これは何故なのでしょうか?

グローバル変数として定義 = グローバルオブジェクトにnameプロパティを追加している、という意味ではないのでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

自分も知らなかったので調べてみました。

https://nodejs.org/docs/latest-v9.x/api/globals.html#globals_global

をみますと、

In browsers, the top-level scope is the global scope. This means that within the browser var something will define a new global variable. In Node.js this is different. The top-level scope is not the global scope; var something inside a Node.js module will be local to that module.

(太字は回答者)

とあります。nodeではvar xxxと記述するとそれはモジュールのローカル変数とみなされるとのことです。おそらくオライリー本がフォーカスしているのはブラウザー上で動作するいわゆるJavaScriptでありNode.jsでは仕様が異なる点があると思うので注意したほうがよいと思います。

じゃぁどう書けばいいのかなと思って「nodejs global」で検索してみるとnodeでは
global.variable_name = value
と書くらしいです。

なおNodeJSでもvariable_name = valueと書けばglobal変数の宣言ができるようですが、strictモードではエラーとなる(global変数として扱われず、宣言ずみの変数と扱われ未定義といわれる)ためこの書き方はどちらかといえば非推奨なのかも知れません。

NodeJS/JavaScriptにあまり明るくないので間違いなどあったらご容赦ください。

投稿2018/09/30 19:23

編集2018/10/01 03:40
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mosin_nozomi

2018/10/01 03:15

通常のJavaScriptとnode.jsの挙動が違うのですね。 ブラウザ上で同じコードを動かして確認させていただきたいと思います! docsまで貼っていただきありがとうございました!
guest

0

KSwordOfHasteさんが答えきってるので、ちょっとした雑学でもぶら下げます。

そもそもグローバル変数を作る用途って、
大抵がこの2種類なので別の方法でもし代用出来れば使う必要はありません。

  • クラスや関数を共有
  • 値をシングルトンとして複数箇所で閲覧

Node.jsはCommomJS由来のrequireあたりの作りがよく出来てて、
requireで実行された外部のjsファイルの挙動はこんな感じになります。

  • require先のコードを読み込む
  • ファイル用のスコープを生成
  • 一通りコードを実行しきる
  • (コード内で)module.exports = valueとして代入する(最も推奨されるのがこれ)
  • module.exportsをrequireの実行結果として持ち帰る
  • 実行したmodule.exportsの中身はrequire関数のプロパティにキャッシュとして保存され、2度目以降は代入済みの値を即返す

この上手い感じの実装により、グローバル変数を利用すること無く、
関数はもちろん、シングルトンも実現できるのです。

bash

1$ ls 2index.js 3singleton.js 4show.js

各ファイルの実装はこんな感じ

JavaScript

1// index.js 2var user = require('./singleton.js'); 3user.name = 'jiro'; 4user.age = 17; 5console.log(user); 6require('./show.js'); 7 8// singleton.js 9module.exports = { 10 name: 'taro', 11 age: 18 12} 13 14// show.js 15var user = require('./singleton.js'); 16console.log(user);

bash

1$ index.js 2{ name: 'jiro', age: 17 } 3{ name: 'jiro', age: 17 }

index.js側のconsole.logの実行結果は{ name: 'jiro', age: 17 }になるのは一目で分かりますが、
その後に実行されたshow.jsも{ name: 'taro', age: 18 }ではなく、jiroのデータになっています。
実行結果のキャッシュというルールによりindex.jsが行った修正内容が残っていることが分かります。

※まぁDI覚えればこんな使い方のシングルトンも不要なんで、完全に余談ですけどね。


ブラウザに搭載されているJavaScriptはrequireはないので、
考えなしに使いまくるとグローバル変数がすぐに衝突します。

そのため、ベストプラクティスとしてグローバル変数汚染を必要最小限で抑えるためのテクニックが色々と存在します。
クロージャーなんかもそれですが、元になっている変数スコープの知識というのは覚えておいた方が何かと便利ですね。
という訳で、書籍ではわりと早い段階で変数スコープ周りの解説が載ってるんじゃないかなと思います。

投稿2018/10/01 04:00

編集2018/10/01 04:45
miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問