What is the 'global' object in NodeJS - javascript
I've just seen a weird behaviour of the this keyword in NodeJS environment. I'm listing them with code. I've run this code with NodeJS v6.x, with a single JavaScript file.
While testing with one line of code as follows, whether with or without the 'use strict' statement, this points to an empty object {}.
console.log(this)
But, when I'm running the statement within a self executing function like,
(function(){
console.log(this);
}());
It's printing a really big object. Seems to me the Global execution context object created by NodeJS environment.
And while executing the above function with a 'use strict' statement, expectedly it's printing undefined
(function(){
'use strict';
console.log(this);
}());
But, while working with browser (I've tested only with Chrome), the first three examples yield the window object and the last one gave undefined as expected.
The behaviour of the browser is quite understandable. But, in case of NodeJS, does it not create the execution context, until I'm wrapping inside a function?
So, most of the code in NodeJS runs with an empty global object?
Value of this in a node module:
this in NodeJS global scope is the current module.exports object, not the global object. This is different from a browser where the global scope is the global window object. Consider the following code executed in Node:
console.log(this); // logs {}
module.exports.foo = 5;
console.log(this); // log { foo:5 }
First we log an empty object because there are no values in module.exports in this module. Then we put foo on the module.exports object, when we then again log this we can see that it now logs the updated module.exports object.
How can we access the global object:
We can access the global object in node using the global keyword:
console.log(global);
The global object exposes a variety of useful properties about the environment. Also this is the place where functions as setImmediate and clearTimeout are located.
While in browsers the global scope is the window object, in nodeJS the global scope of a module is the module itself, so when you define a variable in the global scope of your nodeJS module, it will be local to this module.
You can read more about it in the NodeJS documentation where it says:
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.
And in your code when you write:
console.log(this) in an empty js file(module) it will print an empty object {} referring to your empty module.
console.log(this); inside a self invoking function, this will point to the global nodeJS scope object which contains all NodeJS common properties and methods such as require(), module, exports, console...
console.log(this) with 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.
Very interesting:
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));
}());
will produce:
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
In 3) this is undefined as it is not autoboxed to an object in strict mode. That means that there is no root object in this context. If you do not use strict mode then your code is boxed by a parent scope.As you can see in the output, within nodejs there is lot of information about node internal stuff.
In 1) the output is an empty object because in the top-level code in a node module, this is the equivalent to module.exports and module.exports is empty in this example.
To start with documentation on Global context in node environment
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.
Each JS file is treated as a module. Node automatically wraps the code of a JS file in a self IIFE with exports, require, module, __filename, __dirname as parameters to the function.
Below is the screenshot of execution context using node-debug
If you run the below code, prints true which means this refers to exports in node.js. Best explained in this answer.
console.log(this === exports);
Which means at execution the code is wrapped something similar as below in Node.js separating your code from global context using a wrapper function context or IIFE technique hypothetically.
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"]);
Answer to the next point refer this documentation completely:
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.
so when you execute this code
(function(){
console.log(this);
}());
prints the global object and in use strict mode prints undefined
Remember:
In browser the function is not wrapped by IIFE wrapper function context as done in Node.JS, it's directly executed on window object. Hence the calling context varies for Node.JS and Browser.
Also read this article.
Here i want to highlight one property of global !
What you put there is accessible also directly
(make sure to check the Property title and section)
Before bringing the property! Let's define global again!
global is a language keyword specific to nodejs and reference The global namespace object
As it was already described on other answers! The top scope in a module! Is not global! And limited to only that module!
So when you declare a variable in one module you can't access it in another!
https://nodejs.org/api/globals.html#globals_global
The global namespace is accessible everywhere in a given process! In all modules! That's include your own module and third party modules!
console Logging global in node repl will give this:
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
The property: What you put there is accessible also directly
What i wanted to bring is this! I get to notice this when i was exploring laravel-mix code source!
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()!
Here a node repl screenshot for the example above:
> global.Hola = { print: () => console.log('Hola') }
{ print: [Function: print] }
> Hola.print()
Hola
undefined
Nice property ! That's the global namespace!
You can notice the methods like clearInteraval, clearTimeout, setInterval, setTimeout, ... are defined there! And we used to access them directly by there name!
Laravel mix example
Here some examples from laravel-mix code source! Where it use that!
If you open this file:
https://github.com/JeffreyWay/laravel-mix/blob/master/src/components/ComponentRegistrar.js
You notice in the import section there is no! Mix variable neither Config!
But they are used and part of the code! I was like: what the heck!
Imort code:
let Assert = require('../Assert');
let Dependencies = require('../Dependencies');
let mergeWebpackConfig = require('../builder/MergeWebpackConfig');
On line 68 : (link here) you can see the usage of Mix class variable!
And same thing for Config at line 178 (link here)
When i first got to see it! And get to check the import section! And using github reference feature (came with nothing)! I was What the heck!
Later on when i checked the Mix.js file! And class! I found the code that set them! I got the intuition and googled after!
Conflicts and Why one would want to use the global namespace
A problem to setting globals is overriding and conflicts! Which leads to bugs and unexpected behaviors, up to a total crash! If modules start to use it without thoughts! One module will screw it for another! Like when using a third party module! Imagine module request will set Config var! And you set it too! Or even another third party module! And they are all dependent on it! One will screw it for the other module!
So simply put! We should not use globals! No no! And yes!
It all depends!
It's preferable for a module to not do! That way the module is completly isolated! And it's more robust! Generally setting the variable in a certain module! And importing it each time! Using dependency injection ...etc
In many cases however it's more flexible to use the global namespace!
You can do so and not worry! If you are building a server! Config object can go on the global! A command line Interface tool or script! Some process that run directly!
Generally don't use the global scope when you are building a module! A package! A library! A component! Which gonna be reusable! (Reusable cross projects! no global scope! isolate it)!
Laravel mix for instance is a package that is used to generate webpack config! That get to run as a cli tool and process!
However if the Config variable for example was also set by Webpack or some of the community plugins or loaders! Then problems can occure due to overriding!
Something simple could make it safer is to add a domain in the naming! For instance Mix_Config !
global is a reference to the real global scope object in NodeJS, somewhat like using window in a browser JS environment.
global.studentName = 'Kyle'
console.log(`Hello, ${ global.studentName }!`)
// Hello, Kyle!
console.log(`Hello, ${ studentName }!`)
// Hello, Kyle!
I've written a comprehensive answer that covers the value of this in different contexts. Explanation is added as code comments where needed.
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.
This is based on information found on:
Meaning of "this" in node.js modules and functions
What is the 'global' object in NodeJS
https://www.w3schools.com/js/js_arrow_function.asp
I hope this helps and please let me know in the comments if I missed any scenarios where the value of this might be different.
Related
Invalid configuration for rule "react/jsx-sort-props"
I'm trying to sort props names alphabetically using the plugin eslint-plugin-react but I'm getting this error: [Error ] .eslintrc.json: Configuration for rule "react/jsx-sort-props" is invalid: Value {"callbacksLast":true,"shorthandFirst":false,"shorthandLast":true,"multiline":"last","ignoreCase":true,"noSortAlphabetically":false} should NOT have additional properties. This is my .eslintrc.json file: { "extends": [ "eslint:recommended", "plugin:react/recommended", "next/core-web-vitals" ], "rules": { "react/jsx-sort-props": [ "2", { "callbacksLast": true, "shorthandFirst": false, "shorthandLast": true, "multiline": "last", "ignoreCase": true, "noSortAlphabetically": false } ] } } What I'm missing?
There are two issues: The severity option, if you're using a number, should be a number, not a string that contains a number - 2, not "2". (Though, personally, I'd suggest using "error" instead - it makes it clearer from reading the config what the rule means for your project - "error" makes more intuitive sense than 2) There is a bug in the linter rule's jsx-sort-props.js - although the docs reference a multiline property, said property does not exist anywhere in the lint rule implementation, and so an error is thrown when you pass in an object containing that property. Remove it. "rules": { "react/jsx-sort-props": [ 2, { "callbacksLast": true, "shorthandFirst": false, "shorthandLast": true, "ignoreCase": true, "noSortAlphabetically": false } ] }
Having trouble trying to grab a specific key value from Stripe API using dot notation with JSON
I'm pulling data from the Stripe API from a test invoice. I'm trying to narrow down to pull a specific key value pair using dot notation, but I'm having trouble pulling the data from a specific key value as it seems nester deeper than the rest of the data (not sure if that's the right terminology). The data I'm trying to pull the data from is from period: end: and from period: start: roughly from lines 44-46. If I use dot notation in my code it works when the key value pair is on the same line, such as sheet.getRange(3,2).setValue([content.amount_due]);. But it seems as if "period: end" and "period: start" are nested deeper. I tried doing something like [content.lines.data.period.end] but it didn't work. It returns this error: TypeError: Cannot read property "end" from undefined. Here's the full data pulled from the API (note: "xxxxxxxxxxxxxxxx" represents data that's been hidden): ""id"": ""in_xxxxxxxxxxxxxxxx"", ""object"": ""invoice"", ""amount_due"": 800, ""amount_paid"": 800, ""amount_remaining"": 0, ""application_fee"": null, ""attempt_count"": 1, ""attempted"": true, ""auto_advance"": false, ""billing"": ""charge_automatically"", ""billing_reason"": ""subscription_cycle"", ""charge"": ""ch_xxxxxxxxxxxxxxxx"", ""closed"": true, ""created"": 1552077120, ""currency"": ""usd"", ""custom_fields"": null, ""customer"": ""cus_xxxxxxxxxxxxxxxx"", ""date"": 1552077120, ""default_payment_method"": null, ""default_source"": null, ""description"": null, ""discount"": null, ""due_date"": null, ""ending_balance"": 0, ""finalized_at"": 1552080770, ""footer"": null, ""forgiven"": false, ""hosted_invoice_url"": ""https://pay.stripe.com/invoice/invst_xxxxxxxxxxxxxxxx"", ""invoice_pdf"": ""https://pay.stripe.com/invoice/invst_xxxxxxxxxxxxxxxx/pdf"", ""lines"": { ""object"": ""list"", ""data"": [ { ""id"": ""sub_xxxxxxxxxxxxxxxx"", ""object"": ""line_item"", ""amount"": 800, ""currency"": ""usd"", ""description"": null, ""discountable"": true, ""livemode"": false, ""metadata"": { }, ""period"": { ""end"": 1554755515, ""start"": 1552077115 }, ""plan"": { ""id"": ""xxxxxxxxxxxxxxxx"", ""object"": ""plan"", ""active"": true, ""aggregate_usage"": null, ""amount"": 400, ""billing_scheme"": ""per_unit"", ""created"": 1407529859, ""currency"": ""usd"", ""interval"": ""month"", ""interval_count"": 1, ""livemode"": false, ""metadata"": { }, ""name"": ""sdf"", ""nickname"": null, ""product"": ""prod_xxxxxxxxxxxxxxxx"", ""statement_description"": null, ""statement_descriptor"": null, ""tiers"": null, ""tiers_mode"": null, ""transform_usage"": null, ""trial_period_days"": null, ""usage_type"": ""licensed"" }, ""proration"": false, ""quantity"": 2, ""subscription"": null, ""subscription_item"": ""si_xxxxxxxxxxxxxxxx"", ""type"": ""subscription"", ""unique_line_item_id"": ""sli_xxxxxxxxxxxxxxx"" } ], ""has_more"": false, ""total_count"": 1, ""url"": ""/v1/invoices/in_xxxxxxxxxxxxxxxx/lines"" }, ""livemode"": false, ""metadata"": { }, ""next_payment_attempt"": null, ""number"": ""77E3C02-0025"", ""paid"": true, ""payment"": ""ch_1xxxxxxxxxxxxxxxx"", ""payment_intent"": ""pi_xxxxxxxxxxxxxxxx"", ""period_end"": 1552077115, ""period_start"": 1549657915, ""receipt_number"": ""2258-2679"", ""starting_balance"": 0, ""statement_description"": null, ""statement_descriptor"": null, ""status"": ""paid"", ""status_transitions"": { ""finalized_at"": 1552080770, ""marked_uncollectible_at"": null, ""paid_at"": 1552080772, ""voided_at"": null }, ""subscription"": ""sub_xxxxxxxxxxxxxxxx"", ""subtotal"": 800, ""tax"": null, ""tax_percent"": null, ""total"": 800, ""webhooks_delivered_at"": 1552077123 }"``` [1]: https://stripe.com/docs/api/invoices/retrieve
data is an array, try content.lines.data[0].period.end.
How to access variable from Ajax FormData.append?
I am sending an uploaded file from my HTML form to my server and am trying to add a custom attribute to FormData(), but it's not showing up on my server side. I add my custom attribute by doing var formData = new FormData();, then appending by doing formData.append("airlinename",airline_name);, but once I get the data on the Server side, I look in the req object and can't find airlinename. How do I access my custom attribute? I am able to access the file just fine, but I can't find how to access the custom attribute I appended to formData. HTML Form <form role="form"> <input type="text" id="load_db_name" name="load_db_name"> <input type="file" id="load_db_dir" name="load_db_dir"> </form> <button id="load_generateDiagram" onClick="loadPastDiagram();" type="button">Load</button> Client JS function loadPastDiagram() { var db_dir = document.getElementById('load_db_dir').files[0] || null; var _files = [db_dir]; var airline_name = document.getElementById('load_db_name').value.trim(); loadDiagram(airline_name,_files); } function loadDiagram(airline_name, files) { var formData = new FormData(); for (var f in files) { formData.append("files", files[f]); } formData.append("airlinename",airline_name); //<--- can't find this on the server side $.ajax({ url: '/loadDiagram', type: 'POST', success: function(res) { console.log("Success"); }, error: function(err) { console.log("Error ",err); }, data: formData, //Options to tell jQuery not to process data or worry about content-type. cache: false, contentType: false, processData: false }); } Server JS app.post('/loadDiagram', function(req,res){ console.log("[FILES]" + JSON.stringify(req.airlinename)); console.log("[FILES]" + JSON.stringify(req.files.airlinename)); console.log("[FILES]" + JSON.stringify(req.files.files)); }); Output [DEV] [FILES]undefined [DEV] [FILES]undefined [DEV] [FILES]{ "fieldName": "files", "originalFilename": "Tool_fresshhh.tar.gz", "path": "../Output-Files/2833-fwh0ql.tf9od2t9.gz", "headers": { "content-disposition": "form-data; name=\"files\"; filename=\"Tool_fresshhh.tar.gz\"", "content-type": "application/x-gzip" }, "ws": { "_writableState": { "objectMode": false, "highWaterMark": 16384, "needDrain": true, "ending": true, "ended": true, "finished": true, "decodeStrings": true, "defaultEncoding": "utf8", "length": 0, "writing": false, "corked": 0, "sync": false, "bufferProcessing": false, "writecb": null, "writelen": 0, "bufferedRequest": null, "lastBufferedRequest": null, "pendingcb": 0, "prefinished": true, "errorEmitted": false, "bufferedRequestCount": 0, "corkedRequestsFree": { "next": { "next": null, "entry": null }, "entry": null } }, "writable": false, "domain": null, "_events": { "error": [null], "close": [null] }, "_eventsCount": 2, "path": "../Output-Files/2833-fwh0ql.tf9od2t9.gz", "fd": null, "flags": "w", "mode": 438, "autoClose": true, "bytesWritten": 449781, "closed": true }, "size": 449781, "name": "Tool_fresshhh.tar.gz", "type": "application/x-gzip" } Versions jQuery v1.11.1 Express Version: 3.14.0 Node Version: v6.5.0
I know this is "uncool"... But I saw this question as it was posted, more than 1 hour ago, and saw (quite fast!!) the solution posted as a comment. I waited on him or her to post it, so I could learn something. But since Jaromanda X was actually last seen 5 minutes ago without posting the answer... I guess he or she is not really interested about rep. points! So just to mark this question as answered... ;) Server JS app.post('/loadDiagram', function(req,res){ console.log("[FILES]" + JSON.stringify(req.body.airlinename)); // <-- console.log("[FILES]" + JSON.stringify(req.files.files)); }); «First one to post it, gets it! »
gulp-jscs Object.keys called on non-object
I'm a novice at gulp, and trying to play with it. I get this error when I try to use gulp-jscs 'default' errored after 98 ms [16:58:00] TypeError: Object.keys called on non-object at Function.keys (native) at NodeConfiguration.Configuration._throwNonCamelCaseErrorIfNeeded (/home/kbadr/Node_Projects/demo/membership/node_modules/gulp-jscs/node_modules/jscs/lib/config/configuration.js:440:12) at NodeConfiguration.Configuration.load (/home/kbadr/Node_Projects/demo/membership/node_modules/gulp-jscs/node_modules/jscs/lib/config/configuration.js:51:10) at StringChecker.configure (/home/kbadr/Node_Projects/demo/membership/node_modules/gulp-jscs/node_modules/jscs/lib/string-checker.js:66:29) at Checker.configure (/home/kbadr/Node_Projects/demo/membership/node_modules/gulp-jscs/node_modules/jscs/lib/checker.js:26:39) at module.exports (/home/kbadr/Node_Projects/demo/membership/node_modules/gulp-jscs/index.js:31:11) at Gulp.<anonymous> (/home/kbadr/Node_Projects/demo/membership/gulpfile.js:22:15) at module.exports (/home/kbadr/Node_Projects/demo/membership/node_modules/gulp/node_modules/orchestrator/lib/runTask.js:34:7) at Gulp.Orchestrator._runTask (/home/kbadr/Node_Projects/demo/membership/node_modules/gulp/node_modules/orchestrator/index.js:273:3) at Gulp.Orchestrator._runStep (/home/kbadr/Node_Projects/demo/membership/node_modules/gulp/node_modules/orchestrator/index.js:214:10 and here's my gulpfile var gulp = require('gulp'); var jscs = require('gulp-jscs'); gulp.task('default', function () { return gulp.src('src/app.js') .pipe(jscs()); });
This seems to happen if jscs doesn't have read access to your .jscsrc or if it doesn't exist. This happened to me after copying and pasting it from an old git repro. To fix this open the file with a text editor and resave it, accepting the prompt to overwrite as well as starting with a '.' (e.g. .jscsrc) Run your task again and it will complete.
I had the same problem: "Unable to load JSCS config file at /Desktop/node/My_Project_Name/.jscsrc Unexpected end of input...." I was able to solve the problem by first checking to see if the file existed in the root of my project. in terminal run this command: ls -ld .?* The file was never created for me so I created the .jscsrc file then I added the following code: { "excludeFiles": ["node_modules/**", "bower_components/**"], "requireCurlyBraces": [ "if", "else", "for", "while", "do", "try", "catch" ], "requireOperatorBeforeLineBreak": true, "requireCamelCaseOrUpperCaseIdentifiers": true, "maximumLineLength": { "value": 100, "allowComments": true, "allowRegex": true }, "validateIndentation": 4, "validateQuoteMarks": "'", "disallowMultipleLineStrings": true, "disallowMixedSpacesAndTabs": true, "disallowTrailingWhitespace": true, "disallowSpaceAfterPrefixUnaryOperators": true, "disallowMultipleVarDecl": null, "requireSpaceAfterKeywords": [ "if", "else", "for", "while", "do", "switch", "return", "try", "catch" ], "requireSpaceBeforeBinaryOperators": [ "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", "&=", "|=", "^=", "+=", "+", "-", "*", "/", "%", "<<", ">>", ">>>", "&", "|", "^", "&&", "||", "===", "==", ">=", "<=", "<", ">", "!=", "!==" ], "requireSpaceAfterBinaryOperators": true, "requireSpacesInConditionalExpression": true, "requireSpaceBeforeBlockStatements": true, "requireLineFeedAtFileEnd": true, "disallowSpacesInsideObjectBrackets": "all", "disallowSpacesInsideArrayBrackets": "all", "disallowSpacesInsideParentheses": true, "validateJSDoc": { "checkParamNames": true, "requireParamTypes": true }, "disallowMultipleLineBreaks": true, "disallowCommaBeforeLineBreak": null, "disallowDanglingUnderscores": null, "disallowEmptyBlocks": null, "disallowMultipleLineStrings": null, "disallowTrailingComma": null, "requireCommaBeforeLineBreak": null, "requireDotNotation": null, "requireMultipleVarDecl": null, "requireParenthesesAroundIIFE": true } Save this file to the root of your project, then run the gulp task command again it should work.
Updated the dependency in bower.json on ngCordova and resolved the issue !!!
Knockout.js mapping ignore
We're working with knockout.js and knockout.mapping.js on .NET MVC 4. Let's say I have such JSON: { "deliveryPointType": "0", "deliveryPointTypes": [ { "id": 0, "text": "Pridėti rankiniu būdu" }, { "id": 1, "text": "Siųsti visiems regiono objektams" } ], "showRegionSelection": false, "showDeliveryPointSelection": true, "regionId": "", "userHasRegions": "False", "propertyNames": { "deliveryPointTypeName": "Pridėti rankiniu būdu" }, "initialMaterials": [ { "quantity": 0, "materialTypeId": "", "propertyNames": {}, "validMaterial": true, "showMaterialError": false, "materialTypeAjax": { "quietMillis": 300, "cache": false, "dataType": "json", "type": "GET", "url": "/lt-LT/Material/MaterialTypeNameLookup" } } ], "deliveryBuildings": [ { "clientId": "1", "buildingId": "1", "regionId": "", "newBuilding": false, "validClient": true, "validBuilding": true, "validRegion": true, "showClientError": false, "showBuildingError": false, "showRegionError": false, "propertyNames": { "clientName": "klientas", "buildingName": "ASD project, Antagynės gatvė, Kaunas, Lietuvos Respublika" }, "clientAjax": { "quietMillis": 300, "cache": false, "dataType": "json", "type": "GET", "url": "/lt-LT/Task/PayerLookup" }, "buildingAjax": { "quietMillis": 300, "cache": false, "dataType": "json", "type": "GET", "url": "/lt-LT/Object/GetClientAddressListByQuery" }, "regionAjax": { "quietMillis": 300, "cache": false, "dataType": "json", "type": "GET", "url": "/lt-LT/Object/RegionNameLookup" } } ], "hasNewBuildings": false, "showBuildingValidation": false, "showMinimumBuildingRequiredValidation": false, "showMaterialValidation": false, "validRegion": true, "showRegionError": false, "regionAjax": { "quietMillis": 300, "cache": false, "dataType": "json", "type": "GET", "url": "/lt-LT/Object/RegionNameLookup" } } On form submit fail (if something goes wrong/invalid in service) it is repopulated with previous values. We convert ViewModel to JSON on form submit with $('#BuildingsJSON').val(ko.mapping.toJSON(viewModel.deliveryBuildings)). On form repopulating, we parse JSON with ko.mapping.fromJSON(deliveryBuildings, mapping, viewModel.deliveryBuildings)(); mapping is just an empty object for now (tried "ignore" with no luck). We use select2 fields to select addresses of buildings from a list (using ajax). Thing is, fromJSON populates almost every json property as observable, which I don't need. On select2 open we get an exception: Uncaught TypeError: Object function observable() { if (arguments.length > 0) { // Write // Ignore writes if the value hasn't changed if (!observable['equalityComparer'] || !observable['equalityComparer'](_latestValue, arguments[0])) { observable.valueWillMutate(); _latestValue = arguments[0]; if (DEBUG) observable._latestValue = _latestValue; observable.valueHasMutated(); } return this; // Permits chained assignments } else { // Read ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a "read" operation return _latestValue; } } has no method 'toUpperCase' I've debugged where it breaks - on type property of ajax call. I figured that we need to exclude ajax properties from casting to observable. So, the question is: how can one not cast specific properties of specific objects to observable()? Is it enough using mapping plugin, is additional plugin needed or is it even impossible?
Have you looked at using the copy keyword in your mapping binding? This just copies the value over into a js property rather than making it an observable. From the documentation: var mapping = { 'copy': ["propertyToCopy"] } ko.mapping.fromJS(data, mapping, viewModel);