NodeJS 中的 'global' 对象是什么
What is the 'global' object in NodeJS
我刚刚在 NodeJS 环境中看到 this
关键字的奇怪行为。我用代码列出它们。我已经 运行 使用单个 JavaScript
文件编写了此代码 NodeJS v6.x
。
用一行代码测试如下,不管有没有'use strict'
语句,this指向一个空对象{}
.
console.log(this)
但是,当我运行在一个自执行函数中使用语句时,
(function(){
console.log(this);
}());
它正在打印一个非常大的对象。在我看来,NodeJS
环境创建的全局执行上下文对象。
并且在使用 'use strict'
语句执行上述函数时,预计它正在打印 undefined
(function(){
'use strict';
console.log(this);
}());
但是,在使用浏览器时(我只测试过 Chrome
),前三个示例生成 window
对象,最后一个示例按预期生成 undefined
。
浏览器的行为是可以理解的。但是,在 NodeJS
的情况下,它不会创建执行上下文,直到我包装在一个函数中吗?
因此,NodeJS
运行 中的大部分代码带有一个空 global object
?
非常有趣:
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 中是 undefined 因为它不会在严格模式下自动装箱到对象。这意味着在此上下文中没有根对象。如果您不使用严格模式,那么您的代码将被父级 scope.As 装箱,您可以在输出中看到,在 nodejs 中有很多关于节点内部内容的信息。
在 1)
中输出是一个空对象,因为在节点模块的顶级代码中,这相当于 module.exports 并且 module.exports 在这个例子中是空的.
虽然在浏览器中全局作用域是 window
对象,但在 nodeJS 中模块的全局作用域是模块本身,所以当你在 nodeJS 模块的全局作用域中定义变量时,它会是这个模块的本地。
您可以在 NodeJS documentation 中阅读更多相关信息:
global
<Object> The global namespace object.
In browsers, the top-level scope is the global scope. That means that
in browsers if you're in the global scope var something will define a
global variable. In Node.js this is different. The top-level scope is
not the global scope; var something inside an Node.js module will be
local to that module.
并在您的代码中编写:
console.log(this)
在一个空的 js 文件(模块)中它会打印一个空对象 {}
引用你的空模块。
console.log(this);
在自调用函数中,this
将指向全局 nodeJS 作用域对象,该对象包含所有 NodeJS 通用属性和方法,例如 require()
、module
, exports
, console
...
console.log(this)
与 strict mode inside a self invoking function it will print undefined
as a self invoked function doesn't have a default local scope object in Strict mode.
从 documentation 节点环境中的全局上下文开始
In browsers, the top-level scope is the global scope. That means that in browsers if you're in the global scope var something will define a 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.
每个 JS 文件都被视为一个模块。 Node 自动将 JS 文件的代码包装在一个 self IIFE 中,并以 exports, require, module, __filename, __dirname
作为函数的参数。
下面是使用node-debug
执行上下文的截图
如果你 运行 下面的代码,打印 true
这意味着 this
引用 node.js 中的 exports
。最佳解释在此 .
console.log(this === exports);
这意味着在执行时,代码被包裹起来,类似于下面 Node.js 假设使用 wrapper function context or IIFE 技术将代码与全局上下文分开。
var context = (function (exports, require, module, __filename, __dirname) {
console.log(this) //This is my code
});
/** hypothetical module wrapper code **/
var module = {exports:{}};
context.apply(module.exports, [module.exports, require, module, "FILE_NAME", "DIR_NAME"]);
下一点的答案完全参考这个documentation:
A function's this
keyword behaves a little differently in JavaScript compared to other languages. It also has some differences between strict mode and non-strict mode.
所以当你执行这段代码时
(function(){
console.log(this);
}());
打印 global
对象并在 use strict
模式下打印 undefined
记住:
在浏览器中,该函数不像 Node.JS 那样被 IIFE wrapper function 上下文包装,而是直接在 window
对象上执行。因此,调用上下文因 Node.JS 和浏览器而异。
另请阅读 this 文章。
节点模块中 this
的值:
NodeJS中的this
global scope是当前的module.exports对象,不是全局对象。这与全局范围是全局 window
对象的浏览器不同。考虑以下在 Node 中执行的代码:
console.log(this); // logs {}
module.exports.foo = 5;
console.log(this); // log { foo:5 }
首先我们记录一个空对象,因为这个模块的 module.exports
中没有值。然后我们将 foo
放在 module.exports
对象上,当我们再次记录 this
时,我们可以看到它现在记录更新的 module.exports
对象。
我们如何访问 global
对象:
我们可以使用 global
关键字访问节点中的 global
对象:
console.log(global);
global
对象公开了有关环境的各种有用属性。这也是 setImmediate
和 clearTimeout
函数所在的位置。
我写了一个全面的答案,涵盖了 this
在不同情况下的价值。在需要的地方添加解释作为代码注释。
let this_in_objects = {
propA: "let's figure THIS out!",
/*
* Object property set to a standard function.
* */
propB: function () {
return this.propA;
// Returns the value of this_in_objects.propA as expected.
},
/*
* Object property set to an arrow function (Introduced in ES6).
* */
propC: () => {
return this.propA;
// Should return 'undefined'
// In this case, 'this' refers to the surrounding scope, which could be one of the following :
// - 'module.exports' if the code is inside a nodejs module.
// - 'window' if the code is executed in a browser, or 'undefined' if running in a terminal due to the lack of 'window' global variable.
},
/*
* Object property set to a standard function that returns an arrow function.
* */
propD: function () {
let newArrowFunction = () => {
return this.propA;
// Returns the value of this_in_objects.propA.
// The first functions declaration binds 'this' to the current object
// then the second function scope is now the 'this' of the first function.
}
return newArrowFunction;
},
/*
* Object property set another object with 2 properties, one of which returns a standard function.
* */
propE: {
propE_1: "value of propE.propE_1",
propE_2: function () {
return this.propE_1;
// In this case, 'this' refers to the surrounding scope, which is the parent object 'propE'
}
},
/*
* Object property set another object with 2 properties, one of which returns an arrow function.
* */
propF: {
propF_1: "value of propF.propF_1",
propF_2: () => {
return this.propF_1;
// Should return 'undefined'
// There no change in the binding of 'this', so
// In this case, 'this' refers to the surrounding scope, which could be one of the following :
// - 'module.exports' if the code is inside a nodejs module.
// - 'window' if the code is executed in a browser, or 'undefined' if running in a terminal due to the lack of 'window' global variable.
}
},
};
console.log(this_in_objects.propB());
// Returns "let's figure THIS out!"
console.log(this_in_objects.propC());
// Returns 'undefined'
console.log(this_in_objects.propD()());
// Returns "let's figure THIS out!"
// Notice the double round brackets to call the nested anonymous functions.
console.log(this_in_objects.propE.propE_2());
// Returns "value of propE.propE_1"
console.log(this_in_objects.propF.propF_2());
// Returns 'undefined'
this_in_objects.propX = function () {
return this.propA;
// Returns the value of this_in_objects.propA as expected.
};
this_in_objects.propA = 'The new value of propA !';
console.log(this_in_objects.propX());
// Returns "The new value of propA !",
// even though 'propA' value was changed AFTER declaring the function,
// returning the value of 'propA' at the time of function execution, not at the time of declaration.
这是基于以下信息:
- Meaning of "this" in node.js modules and functions
- https://www.w3schools.com/js/js_arrow_function.asp
希望这对您有所帮助,如果我错过了 this
的值可能不同的任何场景,请在评论中告诉我。
global
是NodeJS中真正的全局作用域对象的引用,有点像在浏览器JS环境中使用window
。
global.studentName = 'Kyle'
console.log(`Hello, ${ global.studentName }!`)
// Hello, Kyle!
console.log(`Hello, ${ studentName }!`)
// Hello, Kyle!
这里我想强调一个 属性 的全局 !
What you put there is accessible also directly
(确保检查 属性 标题和部分)
之前带的属性!让我们再次定义全局!
global是nodejs特有的语言关键字,引用全局命名空间object
因为已经在其他答案中描述过了!模块中的顶级作用域!不是全局的!并且仅限于该模块!
所以当你在一个模块中声明一个变量时,你不能在另一个模块中访问它!
https://nodejs.org/api/globals.html#globals_global
全局命名空间在给定进程中随处可见!在所有模块中!这包括您自己的模块和第三方模块!
节点 repl 中的控制台全局日志记录将给出:
Welcome to Node.js v13.14.0.
Type ".help" for more information.
> console.log(global)
<ref *1> Object [global] {
global: [Circular *1],
clearInterval: [Function: clearInterval],
clearTimeout: [Function: clearTimeout],
setInterval: [Function: setInterval],
setTimeout: [Function: setTimeout] {
[Symbol(nodejs.util.promisify.custom)]: [Function (anonymous)]
},
queueMicrotask: [Function: queueMicrotask],
clearImmediate: [Function: clearImmediate],
setImmediate: [Function: setImmediate] {
[Symbol(nodejs.util.promisify.custom)]: [Function (anonymous)]
}
}
undefined
属性:你放在那里的也可以直接访问
我要带的是这个!我在探索 laravel-mix 代码源时注意到了这一点!
If you set something on the global object! as like global.Hola = { print: () => console.log("Hola") };
. Then you can access the variable by it's name directly any where in the project code (multiple files [modules] & Whole node process code)! Meaning Hola.print()
in place of global.Hola.print()
!
这里是上面示例的节点 repl 屏幕截图:
> global.Hola = { print: () => console.log('Hola') }
{ print: [Function: print] }
> Hola.print()
Hola
undefined
不错属性!那是全局命名空间!
你可以注意到 clearInteraval
、clearTimeout
、setInterval
、setTimeout
、...等方法都定义在那里!我们过去常常通过名称直接访问它们!
Laravel 混合示例
这里有一些示例来自 laravel-mix 代码源!它用在什么地方!
如果你打开这个文件:
https://github.com/JeffreyWay/laravel-mix/blob/master/src/components/ComponentRegistrar.js
你注意到在导入部分没有! Mix
变量都不Config
!
但是它们被使用并且是代码的一部分!我当时想:what the heck
!
导入代码:
let Assert = require('../Assert');
let Dependencies = require('../Dependencies');
let mergeWebpackConfig = require('../builder/MergeWebpackConfig');
第68行:(link here)可以看到Mix
class变量的用法!
第 178 行的 Config
也是如此 (link here)
当我第一次看到它的时候!并检查导入部分!并使用 github 参考功能(什么都没有)!我是 What the heck
!
后来我检查了 Mix.js 文件!还有class!我找到了设置它们的代码!我凭直觉搜索了一下!
冲突以及为什么要使用全局命名空间
设置全局变量的问题是覆盖和冲突!这会导致错误和意外行为,直至完全崩溃!如果模块不假思索地开始使用它!一个模块会为另一个模块搞砸!就像使用第三方模块时一样!假设模块 request
将设置 Config var!你也设置了它!甚至另一个第三方模块!他们都依赖它!一个人会把它拧到另一个模块上!
这么简单!我们不应该使用全局变量! 不不! 是的!
这一切都取决于!
一个模块最好不要做!这样模块就完全隔离了!而且它更坚固!一般在某个模块中设置变量!并且每次都导入它!使用依赖注入 ...等等
然而在许多情况下,使用全局命名空间更灵活!
你可以这样做,不用担心!如果您正在 构建服务器 ! Config object 全局就可以了! 命令行界面工具或脚本!一些进程直接运行!
通常在构建模块时不要使用全局作用域! 一包! 图书馆! 一个组件! 可以重复使用! (可重复使用的交叉项目!没有全局范围!隔离它)!
例如 Laravel mix 是一个用于生成 webpack 配置的包! 运行 作为一个 cli 工具和进程!
但是 如果 Config 变量也被 Webpack 或一些社区插件或加载器设置了!然后 问题 会由于覆盖而发生!
一些简单的方法可以使更安全 添加一个域在命名!例如 Mix_Config
!
我刚刚在 NodeJS 环境中看到 this
关键字的奇怪行为。我用代码列出它们。我已经 运行 使用单个 JavaScript
文件编写了此代码 NodeJS v6.x
。
用一行代码测试如下,不管有没有'use strict'
语句,this指向一个空对象{}
.
console.log(this)
但是,当我运行在一个自执行函数中使用语句时,
(function(){
console.log(this);
}());
它正在打印一个非常大的对象。在我看来,NodeJS
环境创建的全局执行上下文对象。
并且在使用 'use strict'
语句执行上述函数时,预计它正在打印 undefined
(function(){
'use strict';
console.log(this);
}());
但是,在使用浏览器时(我只测试过 Chrome
),前三个示例生成 window
对象,最后一个示例按预期生成 undefined
。
浏览器的行为是可以理解的。但是,在 NodeJS
的情况下,它不会创建执行上下文,直到我包装在一个函数中吗?
因此,NodeJS
运行 中的大部分代码带有一个空 global object
?
非常有趣:
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 中是 undefined 因为它不会在严格模式下自动装箱到对象。这意味着在此上下文中没有根对象。如果您不使用严格模式,那么您的代码将被父级 scope.As 装箱,您可以在输出中看到,在 nodejs 中有很多关于节点内部内容的信息。
在 1)
中输出是一个空对象,因为在节点模块的顶级代码中,这相当于 module.exports 并且 module.exports 在这个例子中是空的.
虽然在浏览器中全局作用域是 window
对象,但在 nodeJS 中模块的全局作用域是模块本身,所以当你在 nodeJS 模块的全局作用域中定义变量时,它会是这个模块的本地。
您可以在 NodeJS documentation 中阅读更多相关信息:
global
<Object> The global namespace object.
In browsers, the top-level scope is the global scope. That means that in browsers if you're in the global scope var something will define a global variable. In Node.js this is different. The top-level scope is not the global scope; var something inside an Node.js module will be local to that module.
并在您的代码中编写:
console.log(this)
在一个空的 js 文件(模块)中它会打印一个空对象{}
引用你的空模块。console.log(this);
在自调用函数中,this
将指向全局 nodeJS 作用域对象,该对象包含所有 NodeJS 通用属性和方法,例如require()
、module
,exports
,console
...console.log(this)
与 strict mode inside a self invoking function it will printundefined
as a self invoked function doesn't have a default local scope object in Strict mode.
从 documentation 节点环境中的全局上下文开始
In browsers, the top-level scope is the global scope. That means that in browsers if you're in the global scope var something will define a 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.
每个 JS 文件都被视为一个模块。 Node 自动将 JS 文件的代码包装在一个 self IIFE 中,并以 exports, require, module, __filename, __dirname
作为函数的参数。
下面是使用node-debug
如果你 运行 下面的代码,打印 true
这意味着 this
引用 node.js 中的 exports
。最佳解释在此
console.log(this === exports);
这意味着在执行时,代码被包裹起来,类似于下面 Node.js 假设使用 wrapper function context or IIFE 技术将代码与全局上下文分开。
var context = (function (exports, require, module, __filename, __dirname) {
console.log(this) //This is my code
});
/** hypothetical module wrapper code **/
var module = {exports:{}};
context.apply(module.exports, [module.exports, require, module, "FILE_NAME", "DIR_NAME"]);
下一点的答案完全参考这个documentation:
A function's
this
keyword behaves a little differently in JavaScript compared to other languages. It also has some differences between strict mode and non-strict mode.
所以当你执行这段代码时
(function(){
console.log(this);
}());
打印 global
对象并在 use strict
模式下打印 undefined
记住:
在浏览器中,该函数不像 Node.JS 那样被 IIFE wrapper function 上下文包装,而是直接在 window
对象上执行。因此,调用上下文因 Node.JS 和浏览器而异。
另请阅读 this 文章。
节点模块中 this
的值:
NodeJS中的this
global scope是当前的module.exports对象,不是全局对象。这与全局范围是全局 window
对象的浏览器不同。考虑以下在 Node 中执行的代码:
console.log(this); // logs {}
module.exports.foo = 5;
console.log(this); // log { foo:5 }
首先我们记录一个空对象,因为这个模块的 module.exports
中没有值。然后我们将 foo
放在 module.exports
对象上,当我们再次记录 this
时,我们可以看到它现在记录更新的 module.exports
对象。
我们如何访问 global
对象:
我们可以使用 global
关键字访问节点中的 global
对象:
console.log(global);
global
对象公开了有关环境的各种有用属性。这也是 setImmediate
和 clearTimeout
函数所在的位置。
我写了一个全面的答案,涵盖了 this
在不同情况下的价值。在需要的地方添加解释作为代码注释。
let this_in_objects = {
propA: "let's figure THIS out!",
/*
* Object property set to a standard function.
* */
propB: function () {
return this.propA;
// Returns the value of this_in_objects.propA as expected.
},
/*
* Object property set to an arrow function (Introduced in ES6).
* */
propC: () => {
return this.propA;
// Should return 'undefined'
// In this case, 'this' refers to the surrounding scope, which could be one of the following :
// - 'module.exports' if the code is inside a nodejs module.
// - 'window' if the code is executed in a browser, or 'undefined' if running in a terminal due to the lack of 'window' global variable.
},
/*
* Object property set to a standard function that returns an arrow function.
* */
propD: function () {
let newArrowFunction = () => {
return this.propA;
// Returns the value of this_in_objects.propA.
// The first functions declaration binds 'this' to the current object
// then the second function scope is now the 'this' of the first function.
}
return newArrowFunction;
},
/*
* Object property set another object with 2 properties, one of which returns a standard function.
* */
propE: {
propE_1: "value of propE.propE_1",
propE_2: function () {
return this.propE_1;
// In this case, 'this' refers to the surrounding scope, which is the parent object 'propE'
}
},
/*
* Object property set another object with 2 properties, one of which returns an arrow function.
* */
propF: {
propF_1: "value of propF.propF_1",
propF_2: () => {
return this.propF_1;
// Should return 'undefined'
// There no change in the binding of 'this', so
// In this case, 'this' refers to the surrounding scope, which could be one of the following :
// - 'module.exports' if the code is inside a nodejs module.
// - 'window' if the code is executed in a browser, or 'undefined' if running in a terminal due to the lack of 'window' global variable.
}
},
};
console.log(this_in_objects.propB());
// Returns "let's figure THIS out!"
console.log(this_in_objects.propC());
// Returns 'undefined'
console.log(this_in_objects.propD()());
// Returns "let's figure THIS out!"
// Notice the double round brackets to call the nested anonymous functions.
console.log(this_in_objects.propE.propE_2());
// Returns "value of propE.propE_1"
console.log(this_in_objects.propF.propF_2());
// Returns 'undefined'
this_in_objects.propX = function () {
return this.propA;
// Returns the value of this_in_objects.propA as expected.
};
this_in_objects.propA = 'The new value of propA !';
console.log(this_in_objects.propX());
// Returns "The new value of propA !",
// even though 'propA' value was changed AFTER declaring the function,
// returning the value of 'propA' at the time of function execution, not at the time of declaration.
这是基于以下信息:
- Meaning of "this" in node.js modules and functions
- https://www.w3schools.com/js/js_arrow_function.asp
希望这对您有所帮助,如果我错过了 this
的值可能不同的任何场景,请在评论中告诉我。
global
是NodeJS中真正的全局作用域对象的引用,有点像在浏览器JS环境中使用window
。
global.studentName = 'Kyle'
console.log(`Hello, ${ global.studentName }!`)
// Hello, Kyle!
console.log(`Hello, ${ studentName }!`)
// Hello, Kyle!
这里我想强调一个 属性 的全局 !
What you put there is accessible also directly
(确保检查 属性 标题和部分)
之前带的属性!让我们再次定义全局!
global是nodejs特有的语言关键字,引用全局命名空间object
因为已经在其他答案中描述过了!模块中的顶级作用域!不是全局的!并且仅限于该模块!
所以当你在一个模块中声明一个变量时,你不能在另一个模块中访问它!
https://nodejs.org/api/globals.html#globals_global
全局命名空间在给定进程中随处可见!在所有模块中!这包括您自己的模块和第三方模块!
节点 repl 中的控制台全局日志记录将给出:
Welcome to Node.js v13.14.0.
Type ".help" for more information.
> console.log(global)
<ref *1> Object [global] {
global: [Circular *1],
clearInterval: [Function: clearInterval],
clearTimeout: [Function: clearTimeout],
setInterval: [Function: setInterval],
setTimeout: [Function: setTimeout] {
[Symbol(nodejs.util.promisify.custom)]: [Function (anonymous)]
},
queueMicrotask: [Function: queueMicrotask],
clearImmediate: [Function: clearImmediate],
setImmediate: [Function: setImmediate] {
[Symbol(nodejs.util.promisify.custom)]: [Function (anonymous)]
}
}
undefined
属性:你放在那里的也可以直接访问
我要带的是这个!我在探索 laravel-mix 代码源时注意到了这一点!
If you set something on the global object! as like
global.Hola = { print: () => console.log("Hola") };
. Then you can access the variable by it's name directly any where in the project code (multiple files [modules] & Whole node process code)! MeaningHola.print()
in place ofglobal.Hola.print()
!
这里是上面示例的节点 repl 屏幕截图:
> global.Hola = { print: () => console.log('Hola') }
{ print: [Function: print] }
> Hola.print()
Hola
undefined
不错属性!那是全局命名空间!
你可以注意到 clearInteraval
、clearTimeout
、setInterval
、setTimeout
、...等方法都定义在那里!我们过去常常通过名称直接访问它们!
Laravel 混合示例
这里有一些示例来自 laravel-mix 代码源!它用在什么地方!
如果你打开这个文件: https://github.com/JeffreyWay/laravel-mix/blob/master/src/components/ComponentRegistrar.js
你注意到在导入部分没有! Mix
变量都不Config
!
但是它们被使用并且是代码的一部分!我当时想:what the heck
!
导入代码:
let Assert = require('../Assert');
let Dependencies = require('../Dependencies');
let mergeWebpackConfig = require('../builder/MergeWebpackConfig');
第68行:(link here)可以看到Mix
class变量的用法!
第 178 行的 Config
也是如此 (link here)
当我第一次看到它的时候!并检查导入部分!并使用 github 参考功能(什么都没有)!我是 What the heck
!
后来我检查了 Mix.js 文件!还有class!我找到了设置它们的代码!我凭直觉搜索了一下!
冲突以及为什么要使用全局命名空间
设置全局变量的问题是覆盖和冲突!这会导致错误和意外行为,直至完全崩溃!如果模块不假思索地开始使用它!一个模块会为另一个模块搞砸!就像使用第三方模块时一样!假设模块 request
将设置 Config var!你也设置了它!甚至另一个第三方模块!他们都依赖它!一个人会把它拧到另一个模块上!
这么简单!我们不应该使用全局变量! 不不! 是的!
这一切都取决于!
一个模块最好不要做!这样模块就完全隔离了!而且它更坚固!一般在某个模块中设置变量!并且每次都导入它!使用依赖注入 ...等等
然而在许多情况下,使用全局命名空间更灵活!
你可以这样做,不用担心!如果您正在 构建服务器 ! Config object 全局就可以了! 命令行界面工具或脚本!一些进程直接运行!
通常在构建模块时不要使用全局作用域! 一包! 图书馆! 一个组件! 可以重复使用! (可重复使用的交叉项目!没有全局范围!隔离它)!
例如Laravel mix 是一个用于生成 webpack 配置的包! 运行 作为一个 cli 工具和进程!
但是 如果 Config 变量也被 Webpack 或一些社区插件或加载器设置了!然后 问题 会由于覆盖而发生!
一些简单的方法可以使更安全 添加一个域在命名!例如 Mix_Config
!