Possible strange behaviour with ES6 deconstruction syntax [duplicate] - javascript

This question already has answers here:
Babel 6 changes how it exports default
(4 answers)
Closed 6 years ago.
I've been using the deconstruction syntax { ...variable } for quite awhile now, but I've never really had a problem with it until today, while most of my use cases still work as expected this one is a bit confusing to myself.
I have a JS file that generates an object and exports it, ex:
var exports = {}
...
export default exports;
There are not any nested objects and by the end of the file it's a simple KVP.
When trying to import from this file any objects I attempt to get through deconstruction are undefined. For example:
import { Foo, Bar } from './my-object';
Foo.bar(); // Cannot read property bar of undefined
However, if I break it apart farther like so, everything is fine:
import MyObject from './my-object';
const { Foo, Bar } = MyObject;
Foo.bar(); // Works!
I've tried changing exports to a different variable name as I thought maybe, just maybe it was a confliction with module.exports, but that wasn't the problem.
In the past whenever I exported an object it was simple:
export default { ... }
I'm really confused on what the issue could be this time around as the result of console.log(exports) is the same thing:
{ Foo: foo, Bar: bar }
Where bar() is a function variable of foo
I should also add that trying to hack this to have the proper results doesn't work either, for example:
export default {
Foo: { bar: () => {} },
Bar: { foo: () => {} }
};
Still throws the same Cannot read property __ of undefined

If you are using Babel, it's because the export default statement is roughly translated to:
var foo = {};
exports["default"] = foo;
And import MyObject from './my-object' is translated to: var MyObject = require('./my-object').default;. Which is why your second example works.
However, when you're doing import { Foo, Bar } from './my-object', it is translated to var { Foo, Bar } = require('./my-object');
See this question for extra details.
In your case, I recommend just using the normal export statement. For example:
export class Foo {
myMethod() {}
};
export const Bar = { a: '1' };
Then you can do import { Foo, Bar } from './my-object';.

I think You just miss the basic concept.
In this case You are exporting a single object not multiple classes that is why your import is not working as you are thinking.
The syntax works when we have a file say sample.js with
export var A = (function () {
function A() {
}
return A;
}());
export var B = (function () {
function B() {
}
return B;
}());
export var C = (function () {
function C() {
}
return C;
}());
And if you are importing in other file with the following manner :
import { A, B, C } from './sample';
I have not tried this but I think It is working like this.

if you want to import { Foo, Bar} from './my-object', you need to explicitly export the Foo and Bar. e.g.
export const Foo = { bar() {} };
export const Bar = { foo() {} };

Related

JavaScript - How to call a method of a imported JS file

How to define a method 'foo' in a javascript file 'test.js' so that I can import that file into another javascript file and call the method 'foo'?
Before going further you'll need to figure out what kind of modules you're using, there're 2 common types of modules that I know CommonJS and ES
In either type of module you're using, in order for you to import your method, you will need to export it as a module first.
The details of their differences are found in the NodeJS document NodeJS Import
For the ES modules you can export your method 'foo' like this:
// normal function
export function foo1() {}
// arrow function
export const foo2 = () => {}
// or this grouping style that I prefer would look more elegant
function foo1() {}
const foo2 = () => {}
// we can export multiple methods at once
export {
foo1,
foo2
}
On the other hand, using the CommonJS module, you can export your method 'foo' like this:
// a single method
module.exports.foo1 = function() {}
module.exports = function foo2() {}
// multiple methods
module.exports = {
foo1: () => {},
foo2: () => {}
}
Once you've exported your methods as modules, you can now import them like this:
import { foo1, foo2 } from './test.js'
const exec = foo1();
or
import * as test from './test.js'
const exec = test.foo2();
Hope this help

Stop VS Code from adding 'as' or alias in destructured assignment when renaming in JavaScript or TypeScript

When I rename a variable in JavaScript or TypeScript, VS Code sometimes adds aliases in destructured assignments:
const { renamedProp: prop } = arg; // After rename
or it adds as in imports:
import { Foo as renamedFoo } from "./file"; // After rename
Why does VS Code do this and how can I disable this behavior? For example, if I rename prop in interface Foo for the following code:
export interface Foo {
prop: string;
}
function bar(arg: Foo) {
const { prop } = arg;
return prop;
}
VS Code changes the code to:
export interface Foo {
renamedProp: string;
}
function bar(arg: Foo) {
const { renamedProp: prop } = arg;
return prop;
}
I want it to be:
export interface Foo {
renamedProp: string;
}
function bar(arg: Foo) {
const { renamedProp } = arg;
return renamedProp;
}
By default, VS Code attempts to make renames safe. This means preserving the existing interfaces of types. In cases like the following example,
export interface Foo {
prop: string;
}
function bar(arg: Foo) {
const { prop } = arg;
return { prop };
}
If we rename prop without using aliases, the implicitly returned type of bar would change. And maybe this type was used to satisfy another interface that expects a property called prop. In this case, introducing an alias on rename preserves the existing type interfaces whichs ensures that the code continues to compile and work as expected
To disabled this behavior, just set:
"javascript.preferences.useAliasesForRenames": false,
"typescript.preferences.useAliasesForRenames": false,
These settings are only supported when using TypeScript 3.4+ in your workspace (this is the default in VS Code 1.33+)

Jasmine mockability of imported vs required named exports

I'll start with the setup, before I get into the problem. Let's start with the base file whose named exports we'll want to spy on:
// fileA.js
export function bar() {}
export function foo() {}
And then have two variations of classes that import these, one in CommonJS style, and one in ES6 style:
// es6Baz.js
import * as A from 'fileA'
export default class Baz {
callFoo() { A.foo(); }
}
// commonBaz.js
const A = require('fileA');
export default class Baz {
callFoo() { A.foo(); }
}
Then likewise, test files for these two same variants:
// testEs6A.js
import Baz from 'es6Baz';
import * as A from 'fileA';
it('test', () => {
spyOn(A, 'foo');
const b = new Baz();
b.callFoo();
expect(A.foo).toHaveBeenCalled(); // this will fail
});
// testCommonA.js
import Baz from 'es6Baz';
const A = require('fileA');
it('test', () => {
spyOn(A, 'foo');
const b = new Baz();
b.callFoo();
expect(A.foo).toHaveBeenCalled(); // this will pass
});
The main question here is: why does mocking work with the CommonJS approach, but not the ES6 one, assuming we're using Babel to compile?
My understanding was that ES6 live binds, while CommonJS copies, so I was surprised the former failed, and even more surprised the latter succeeded. My best guess is that a * import results in a locally namespaced object that's different in the files this is done in (i.e. A in es6Baz.js is not the same as A in testEst6A.js), but is that actually the case? And why would the require work, when this doesn't?

ES6 access exported 'default' instance from same file

I was wondering, when you export some data using the ES6 keyword export like so :
export default {
data: "Hello !"
}
How can you then from the same file, access that exact same exported data ?
EDIT: Of course, without declaring it before exporting the variable...
If you structure your file like that, you cannot.
Usually, you define functions and data that you want to expose before the export statement, and then reference them when you build the exported object/function.
Bad way:
export default {
data: 'Hello!',
myFn: function (str) {
console.log(str);
}
}
Good way:
var data = 'Hello!';
var myFn = function (str) {
console.log(str);
};
// code that uses data and myFn
// shorthand for { data: data, myFn: myFn }
export default { data, myFn };
Try the following
export const data = 'hello';
For my similar use case -- I wanted easy access to everything the ES6 module exported from within the same module just for debugging purposes. So:
export const data = 'hi'
export const someFunc = () => `important data: ${data}`
export default someFunc()
export const funcToDebug() => {
console.log(`what's going on here? ${myModule.exports.default}`)
}
var myModule = module
If you want to access internally the functions that you export, you should define them outside of the export statement. Like so:
const data = 'Hello !';
const someFunc = () => {
return data + ' Goodbye!'
}
export default {
data,
someFunc
}
Now the variables and functions can reference each other without being "stuck" inside the export function. For example the following will NOT work:
// WRONG!
export default {
data: 'Hello !',
someFunc: () => {
return data + ' Goodbye!';
}
}

Getting error when import instanceMethods function in Sequelize

I have created inside a file a function and export it using
export function foo(params...) {
// do something
}
inside the initialization of the model I import the function in this way:
import { foo } from "../path/..."
instanceMethods: {
foo: foo
}
the problem is the model is not initialized correctly. Do you know why?
the problem is the model is not initialized correctly
The following code works fine.
export function foo(params...) {
// do something
}
import { foo } from "./foo";
let instanceMethods = {
foo: foo
};
Error is elsewhere. Perhaps you meant to use = and used :? Note that if you don't use the variable it is erased form the output (ref).
#)-'--

Categories

Resources