NodeJS環境でthis
キーワードの奇妙な動作を見たばかりです。コードでそれらをリストしています。単一のJavaScript
ファイルで、NodeJS v6.x
でこのコードを実行しました。
'use strict'
ステートメントの有無にかかわらず、次の1行のコードでテストしているときに、これは空のオブジェクト{}
を指します。
console.log(this)
しかし、次のような自己実行関数内でステートメントを実行している場合、
(function(){
console.log(this);
}());
それは本当に大きなオブジェクトを印刷しています。 NodeJS
環境によって作成されたグローバル実行コンテキストオブジェクトのようです。
'use strict'
ステートメントを使用して上記の関数を実行しているときに、期待どおりにundefined
を出力しています
(function(){
'use strict';
console.log(this);
}());
ただし、ブラウザーで作業している間(Chrome
でのみテストしました)、最初の3つの例ではwindow
オブジェクトが生成され、最後の例ではundefined
オブジェクトが生成されました。
ブラウザの動作は非常に理解しやすいものです。しかし、NodeJS
の場合、関数内にラップするまで、実行コンテキストは作成されませんか?
したがって、NodeJS
のほとんどのコードは、空のglobalobject
?で実行されます。
ブラウザーではグローバルスコープはwindow
オブジェクトですが、nodeJSではモジュールのグローバルスコープはモジュール自体なので、nodeJSモジュールのグローバルスコープで変数を定義すると、このモジュールに対してローカルになります。
詳細については、NodeJSのドキュメントを参照してください。
global
_
<Object> The global namespace object.
_ブラウザでは、トップレベルのスコープはグローバルスコープです。つまり、ブラウザでは、グローバルスコープvarにいる場合、何かがグローバル変数を定義します。 Node.jsではこれは異なります。最上位のスコープはグローバルスコープではありません。 Node.jsモジュール内のvar somethingは、そのモジュールに対してローカルになります。
そして、あなたのコードであなたが書くとき:
console.log(this)
は、空のjsファイル(モジュール)で、空のモジュールを参照する空のオブジェクト_{}
_を出力します。console.log(this);
は、自己呼び出し関数内で、this
は、require()
、module
、exports
、console
などのすべてのNodeJS共通プロパティおよびメソッドを含むグローバルnodeJSスコープオブジェクトを指します。console.log(this)
with strict mode 自己呼び出し関数内では、自己呼び出し関数のようにundefined
を出力します 厳密モード にデフォルトのローカルスコープオブジェクトがありません。this
の値:NodeJSのthis
グローバルスコープは、グローバルオブジェクトではなく、現在のmodule.exportsオブジェクトです。これは、グローバルスコープがグローバルwindow
オブジェクトであるブラウザーとは異なります。 Nodeで実行される次のコードを検討してください。
console.log(this); // logs {}
module.exports.foo = 5;
console.log(this); // log { foo:5 }
このモジュールのmodule.exports
には値がないため、最初にemtyオブジェクトを記録します。次に、module.exports
オブジェクトにfoo
を配置し、this
オブジェクトを再度ログに記録すると、更新されたmodule.exports
オブジェクトを記録することがわかります。
global
オブジェクトにアクセスするにはどうすればよいですか:global
キーワードを使用して、ノードのglobal
オブジェクトにアクセスできます。
console.log(global);
global
オブジェクトは、環境に関するさまざまな有用なプロパティを公開します。また、これはsetImmediate
およびclearTimeout
としての関数が配置される場所です。
とても興味深い:
var JSON = require('circular-json');
console.log('1) ' + JSON.stringify(this, null, 2));
(function(){
console.log('2) ' + JSON.stringify(this, null, 2));
}());
(function(){
'use strict';
console.log('3) ' + JSON.stringify(this, null, 2));
}());
生成されます:
1) {}
2) {
"global": "~",
"process": {
"title": "node",
"version": "v6.9.1",
"moduleLoadList": [
"Binding contextify",
"Binding natives",
"NativeModule events",
"NativeModule util",
"Binding uv",
"NativeModule buffer",
"Binding buffer",
"Binding util",
"NativeModule internal/util",
"NativeModule timers",
"Binding timer_wrap",
"NativeModule internal/linkedlist",
"NativeModule assert",
"NativeModule internal/process",
"Binding config",
"NativeModule internal/process/warning",
"NativeModule internal/process/next_tick",
"NativeModule internal/process/promises",
"NativeModule internal/process/stdio",
"Binding constants",
"NativeModule path",
"NativeModule module",
"NativeModule internal/module",
"NativeModule vm",
"NativeModule fs",
"Binding fs",
"NativeModule stream",
"NativeModule _stream_readable",
"NativeModule internal/streams/BufferList",
"NativeModule _stream_writable",
"NativeModule _stream_duplex",
"NativeModule _stream_transform",
"NativeModule _stream_passthrough",
"Binding fs_event_wrap",
"NativeModule console",
"Binding tty_wrap",
"NativeModule tty",
"NativeModule net",
"NativeModule internal/net",
"Binding cares_wrap",
"Binding tcp_wrap",
"Binding pipe_wrap",
"Binding stream_wrap",
"Binding signal_wrap"
],
"versions": {
"http_parser": "2.7.0",
"node": "6.9.1",
"v8": "5.1.281.84",
"uv": "1.9.1",
"zlib": "1.2.8",
"ares": "1.10.1-DEV",
"icu": "57.1",
"modules": "48",
"openssl": "1.0.2j"
},
"Arch": "x64",
"platform": "linux",
"release": {
"name": "node",
"lts": "Boron",
"sourceUrl": "https://nodejs.org/download/release/v6.9.1/node-v6.9.1.tar.gz",
"headersUrl": "https://nodejs.org/download/release/v6.9.1/node-v6.9.1-headers.tar.gz"
},
"argv": [
"/usr/local/bin/node",
"/home/froth/freelancer-projects/thistest.js"
],
"execArgv": [],
"env": {
"NVM_DIR": "/home/froth/.nvm",
"LD_LIBRARY_PATH": "/opt/opencascade/lib",
"CSF_UnitsDefinition": "/opt/opencascade/src/UnitsAPI/Units.dat",
"CSF_GraphicShr": "/opt/opencascade/lib/libTKOpenGl.so",
"CSF_EXCEPTION_Prompt": "1",
"LANG": "de_DE.UTF-8",
"PROFILEHOME": "",
"DISPLAY": ":0",
"Shell_SESSION_ID": "09b6f0f3b1d94c5f8aba3f8022075677",
"NODE_PATH": "/usr/lib/node_modules",
"COLORTERM": "truecolor",
"NVM_CD_FLAGS": "",
"MOZ_PLUGIN_PATH": "/usr/lib/mozilla/plugins",
"CSF_IGESDefaults": "/opt/opencascade/src/XSTEPResource",
"CSF_XCAFDefaults": "/opt/opencascade/src/StdResource",
"XDG_VTNR": "1",
"PAM_KWALLET5_LOGIN": "/tmp/kwallet5_froth.socket",
"CSF_STEPDefaults": "/opt/opencascade/src/XSTEPResource",
"XDG_SESSION_ID": "c2",
"CSF_XSMessage": "/opt/opencascade/src/XSMessage",
"USER": "froth",
"DESKTOP_SESSION": "/usr/share/xsessions/awesome",
"GTK2_RC_FILES": "/home/froth/.gtkrc-2.0",
"PWD": "/home/froth/freelancer-projects",
"HOME": "/home/froth",
"XDG_SESSION_TYPE": "x11",
"CSF_PluginDefaults": "/opt/opencascade/src/StdResource",
"XDG_DATA_DIRS": "/usr/local/share/:/usr/share/:/var/lib/snapd/desktop",
"NVM_IOJS_ORG_MIRROR": "https://iojs.org/dist",
"KONSOLE_DBUS_SESSION": "/Sessions/1",
"XDG_SESSION_DESKTOP": "",
"CSF_StandardDefaults": "/opt/opencascade/src/StdResource",
"CSF_StandardLiteDefaults": "/opt/opencascade/src/StdResource",
"MMGT_CLEAR": "1",
"KONSOLE_DBUS_WINDOW": "/Windows/1",
"CSF_UnitsLexicon": "/opt/opencascade/src/UnitsAPI/Lexi_Expr.dat",
"GTK_MODULES": "canberra-gtk-module",
"MAIL": "/var/spool/mail/froth",
"NVM_RC_VERSION": "",
"CSF_XmlOcafResource": "/opt/opencascade/src/XmlOcafResource",
"TERM": "xterm-256color",
"Shell": "/bin/bash",
"KONSOLE_DBUS_SERVICE": ":1.23",
"XDG_SESSION_CLASS": "user",
"XDG_SEAT_PATH": "/org/freedesktop/DisplayManager/Seat0",
"XDG_CURRENT_DESKTOP": "",
"QT_LINUX_ACCESSIBILITY_ALWAYS_ON": "1",
"KONSOLE_PROFILE_NAME": "Shell",
"CASROOT": "/opt/opencascade",
"NVM_NODEJS_ORG_MIRROR": "https://nodejs.org/dist",
"COLORFGBG": "15;0",
"XDG_SEAT": "seat0",
"SHLVL": "2",
"LANGUAGE": "",
"WINDOWID": "29360134",
"LOGNAME": "froth",
"DBUS_SESSION_BUS_ADDRESS": "unix:path=/run/user/1000/bus",
"XDG_RUNTIME_DIR": "/run/user/1000",
"CSF_MDTVTexturesDirectory": "/opt/opencascade/src/Textures",
"XAUTHORITY": "/home/froth/.Xauthority",
"XDG_SESSION_PATH": "/org/freedesktop/DisplayManager/Session1",
"PATH": "/home/froth/.gem/Ruby/2.3.0/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/snap/bin:/usr/lib/jvm/default/bin:/opt/opencascade/bin:/usr/bin/site_Perl:/usr/bin/vendor_Perl:/usr/bin/core_Perl",
"CSF_LANGUAGE": "us",
"CSF_SHMessage": "/opt/opencascade/src/SHMessage",
"OLDPWD": "/home/froth",
"_": "/usr/local/bin/node"
},
"pid": 4658,
"features": {
"debug": false,
"uv": true,
"ipv6": true,
"tls_npn": true,
"tls_alpn": true,
"tls_sni": true,
"tls_ocsp": true,
"tls": true
},
"_needImmediateCallback": false,
"execPath": "/usr/local/bin/node",
"debugPort": 5858,
"_events": {
"SIGWINCH": [
null,
null
]
},
"_eventsCount": 4,
"domain": null,
"_exiting": false,
"config": {
"target_defaults": {
"cflags": [],
"default_configuration": "Release",
"defines": [],
"include_dirs": [],
"libraries": []
},
"variables": {
"asan": 0,
"debug_devtools": "node",
"force_dynamic_crt": 0,
"gas_version": "2.23",
"Host_Arch": "x64",
"icu_data_file": "icudt57l.dat",
"icu_data_in": "../../deps/icu-small/source/data/in/icudt57l.dat",
"icu_endianness": "l",
"icu_gyp_path": "tools/icu/icu-generic.gyp",
"icu_locales": "en,root",
"icu_path": "deps/icu-small",
"icu_small": true,
"icu_ver_major": "57",
"node_byteorder": "little",
"node_enable_d8": false,
"node_enable_v8_vtunejit": false,
"node_install_npm": true,
"node_module_version": 48,
"node_no_browser_globals": false,
"node_prefix": "/",
"node_release_urlbase": "https://nodejs.org/download/release/",
"node_shared": false,
"node_shared_cares": false,
"node_shared_http_parser": false,
"node_shared_libuv": false,
"node_shared_openssl": false,
"node_shared_zlib": false,
"node_tag": "",
"node_use_bundled_v8": true,
"node_use_dtrace": false,
"node_use_etw": false,
"node_use_lttng": false,
"node_use_openssl": true,
"node_use_perfctr": false,
"node_use_v8_platform": true,
"openssl_fips": "",
"openssl_no_asm": 0,
"shlib_suffix": "so.48",
"target_Arch": "x64",
"uv_parent_path": "/deps/uv/",
"uv_use_dtrace": false,
"v8_enable_gdbjit": 0,
"v8_enable_i18n_support": 1,
"v8_inspector": true,
"v8_no_strict_aliasing": 1,
"v8_optimized_debug": 0,
"v8_random_seed": 0,
"v8_use_snapshot": true,
"want_separate_Host_toolset": 0
}
},
"stdout": {
"connecting": false,
"_hadError": false,
"_handle": {
"bytesRead": 0,
"_externalStream": {},
"fd": 9,
"writeQueueSize": 0,
"owner": "~process~stdout"
},
"_parent": null,
"_Host": null,
"_readableState": {
"objectMode": false,
"highWaterMark": 16384,
"buffer": {
"head": null,
"tail": null,
"length": 0
},
"length": 0,
"pipes": null,
"pipesCount": 0,
"flowing": null,
"ended": false,
"endEmitted": false,
"reading": false,
"sync": true,
"needReadable": false,
"emittedReadable": false,
"readableListening": false,
"resumeScheduled": false,
"defaultEncoding": "utf8",
"ranOut": false,
"awaitDrain": 0,
"readingMore": false,
"decoder": null,
"encoding": null
},
"readable": false,
"domain": null,
"_events": {},
"_eventsCount": 3,
"_writableState": {
"objectMode": false,
"highWaterMark": 16384,
"needDrain": false,
"ending": false,
"ended": false,
"finished": false,
"decodeStrings": false,
"defaultEncoding": "utf8",
"length": 0,
"writing": false,
"corked": 0,
"sync": false,
"bufferProcessing": false,
"writecb": null,
"writelen": 0,
"bufferedRequest": null,
"lastBufferedRequest": null,
"pendingcb": 1,
"prefinished": false,
"errorEmitted": false,
"bufferedRequestCount": 0,
"corkedRequestsFree": {
"next": null,
"entry": null
}
},
"writable": true,
"allowHalfOpen": false,
"destroyed": false,
"_bytesDispatched": 6,
"_sockname": null,
"_writev": null,
"_pendingData": null,
"_pendingEncoding": "",
"server": null,
"_server": null,
"columns": 84,
"rows": 84,
"_type": "tty",
"fd": 1,
"_isStdio": true
},
"stderr": {
"connecting": false,
"_hadError": false,
"_handle": {
"bytesRead": 0,
"_externalStream": {},
"fd": 11,
"writeQueueSize": 0,
"owner": "~process~stderr"
},
"_parent": null,
"_Host": null,
"_readableState": {
"objectMode": false,
"highWaterMark": 16384,
"buffer": {
"head": null,
"tail": null,
"length": 0
},
"length": 0,
"pipes": null,
"pipesCount": 0,
"flowing": null,
"ended": false,
"endEmitted": false,
"reading": false,
"sync": true,
"needReadable": false,
"emittedReadable": false,
"readableListening": false,
"resumeScheduled": false,
"defaultEncoding": "utf8",
"ranOut": false,
"awaitDrain": 0,
"readingMore": false,
"decoder": null,
"encoding": null
},
"readable": false,
"domain": null,
"_events": {},
"_eventsCount": 3,
"_writableState": {
"objectMode": false,
"highWaterMark": 16384,
"needDrain": false,
"ending": false,
"ended": false,
"finished": false,
"decodeStrings": false,
"defaultEncoding": "utf8",
"length": 0,
"writing": false,
"corked": 0,
"sync": true,
"bufferProcessing": false,
"writecb": null,
"writelen": 0,
"bufferedRequest": null,
"lastBufferedRequest": null,
"pendingcb": 0,
"prefinished": false,
"errorEmitted": false,
"bufferedRequestCount": 0,
"corkedRequestsFree": {
"next": null,
"entry": null
}
},
"writable": true,
"allowHalfOpen": false,
"destroyed": false,
"_bytesDispatched": 0,
"_sockname": null,
"_writev": null,
"_pendingData": null,
"_pendingEncoding": "",
"server": null,
"_server": null,
"columns": 84,
"rows": 84,
"_type": "tty",
"fd": 2,
"_isStdio": true
},
"stdin": {
"connecting": false,
"_hadError": false,
"_handle": {
"bytesRead": 0,
"_externalStream": {},
"fd": 12,
"writeQueueSize": 0,
"owner": "~process~stdin",
"reading": false
},
"_parent": null,
"_Host": null,
"_readableState": {
"objectMode": false,
"highWaterMark": 0,
"buffer": {
"head": null,
"tail": null,
"length": 0
},
"length": 0,
"pipes": null,
"pipesCount": 0,
"flowing": null,
"ended": false,
"endEmitted": false,
"reading": false,
"sync": false,
"needReadable": true,
"emittedReadable": false,
"readableListening": false,
"resumeScheduled": false,
"defaultEncoding": "utf8",
"ranOut": false,
"awaitDrain": 0,
"readingMore": false,
"decoder": null,
"encoding": null
},
"readable": true,
"domain": null,
"_events": {},
"_eventsCount": 4,
"_writableState": {
"objectMode": false,
"highWaterMark": 0,
"needDrain": false,
"ending": false,
"ended": false,
"finished": false,
"decodeStrings": false,
"defaultEncoding": "utf8",
"length": 0,
"writing": false,
"corked": 0,
"sync": true,
"bufferProcessing": false,
"writecb": null,
"writelen": 0,
"bufferedRequest": null,
"lastBufferedRequest": null,
"pendingcb": 0,
"prefinished": false,
"errorEmitted": false,
"bufferedRequestCount": 0,
"corkedRequestsFree": {
"next": null,
"entry": null
}
},
"writable": false,
"allowHalfOpen": false,
"destroyed": false,
"_bytesDispatched": 0,
"_sockname": null,
"_writev": null,
"_pendingData": null,
"_pendingEncoding": "",
"server": null,
"_server": null,
"isRaw": false,
"isTTY": true,
"fd": 0
},
"argv0": "node",
"mainModule": {
"id": ".",
"exports": {},
"parent": null,
"filename": "/home/froth/freelancer-projects/thistest.js",
"loaded": false,
"children": [
{
"id": "/home/froth/freelancer-projects/node_modules/circular-json/build/circular-json.node.js",
"exports": {},
"parent": "~process~mainModule",
"filename": "/home/froth/freelancer-projects/node_modules/circular-json/build/circular-json.node.js",
"loaded": true,
"children": [],
"paths": [
"/home/froth/freelancer-projects/node_modules/circular-json/build/node_modules",
"/home/froth/freelancer-projects/node_modules/circular-json/node_modules",
"/home/froth/freelancer-projects/node_modules",
"/home/froth/node_modules",
"/home/node_modules",
"/node_modules"
]
}
],
"paths": [
"/home/froth/freelancer-projects/node_modules",
"/home/froth/node_modules",
"/home/node_modules",
"/node_modules"
]
}
},
"console": {}
}
3) undefined
3)
thisはndefinedです。これは、strictモードでオブジェクトに自動ボックス化されないためです。つまり、このコンテキストにはルートオブジェクトがありません。ストリクトモードを使用しない場合、コードは親スコープによってボックス化されます。出力からわかるように、nodejsには、ノードの内部に関する多くの情報があります。
1)
ノードモジュールの最上位コードでは、これはmodule.exportsと同等であり、この例ではmodule.exportsは空であるため、出力は空のオブジェクトです。
ノード環境のグローバルコンテキストで ドキュメント で開始するには
ブラウザでは、トップレベルのスコープはグローバルスコープです。つまり、ブラウザでは、グローバルスコープvarにいる場合、何かがグローバル変数を定義します。 Node.jsではこれは異なります。最上位のスコープはグローバルスコープではありません。 Node.jsモジュール内のvar somethingは、そのモジュールに対してローカルになります。
各JSファイルはモジュールとして扱われます。 Nodeは、関数のパラメーターとしてexports, require, module, __filename, __dirname
を使用して、自己IIFEのJSファイルのコードを自動的にラップします。
以下は、node-debug
を使用した実行コンテキストのスクリーンショットです
以下のコードを実行すると、true
が出力されます。つまり、this
はnode.jsのexports
を参照します。これで最もよく説明されています answer 。
console.log(this === exports);
つまり、実行時にコードはNode.jsで次のようなものにラップされ、wrapper function contextを使用してコードをグローバルコンテキストから分離します。
var context = (function (exports, require, module, __filename, __dirname) {
console.log(this) //This is my code
});
var module = {exports:{}};
context.apply(module.exports, [module.exports, require, module, "FILE_NAME", "DIR_NAME"]);
次のポイントへの回答はこれを参照してください documentation 完全に:
JavaScriptの関数のthisキーワードの動作は、他の言語とは少し異なります。また、厳密モードと非厳密モードにはいくつかの違いがあります。
このコードを実行すると
(function(){
console.log(this);
}());
global
オブジェクトを印刷し、use strict
モードでundefined
を印刷します
覚えておいてください:
ブラウザでは、関数はノードのようにIIFE /ラッパー関数コンテキストによってラップされず、window
オブジェクトで直接実行されます。したがって、呼び出しコンテキストはNode.jsとブラウザーによって異なります。
this も読んでください。