Imported function name clash with current module function name in JS - javascript

The odds are that this question has been asked many times, but still can't find the answer.
Imagine I have two modules A and B, and function foo defined in module A. In module B, I have a function foo which needs foo from A:
module B:
import { foo } from './A'
export const foo = (payload) => {
foo() // meaning module A function
}
I get error
Identifier 'foo' has already been declared
Any way to solve this leaving the function names the same ?

No, you cannot leave the identifiers the same, you need to alias either the imported one
import { foo as aFoo } from './A'
export const foo = (payload) => {
aFoo()
};
import * as A from './A'
export const foo = (payload) => {
A.foo()
};
or change the local function name:
import { foo } from './A'
const bBoo = (payload) => {
foo()
};
export { bFoo as foo }

Related

Change ESM export bindings

I'm wondering how the exported bindings of an ES6 module work when destructuring. I'm exporting an object (thing) as a named export -- but also one of its properties (foo), too, which I'm later updating.
This update works when I import the object and reference its prop, but not when I directly import foo, as shown below. I'm guessing the export const... creates a new, immutable binding, but is there any way to retain its reference to the original object upon export?
// module: 'thing.js'
let thing = {
foo: (x) => console.log(x)
};
const init = () => {
thing.foo = (x) => console.log("updated");
};
export { init, thing };
export const { foo } = thing;
// index.js
import { foo, thing, init } from "./thing";
init();
foo("test"); // does not work
thing.foo("test"); // update is reflected, here
codesandbox
There is not issue with export/import
see this example:
let thing = {
foo: (x) => console.log(x)
};
const init = () => {
thing.foo = (x) => console.log("updated");
};
const foo = thing.foo;
init();
foo("test"); //test
thing.foo("test"); //updated
Variable foo and field thing.foo contains different functions after you rewrite thing.foo inside init function

Dynamically import functions into a component with Vue 3

I would like to dynamically (not statically) import functions into a component inside <script setup> ... </script>
Functions are in a pme-check.js file.
import { useStore } from 'vuex';
const store = useStore();
function foo() {
console.log('foo');
}
function bar() {
console.log('bar');
}
export { foo, bar };
In the component, I dynamically import my functions like this and it works correctly
import(`../composables/profil/${store.state.formation.profil}-check`).then(
(module) => {
console.log(module.foo());
// -> 'foo'
console.log(module.bar());
// -> 'bar
}
);
But in this way, my functions cannot be accessed by name in the component.
How to get foo() and bar() anywhere in the <script setup> tags of the component.
Thank you
If you want to use foo() and bar() anywhere in the file then you should use require instead of import and the code should look like this:
const profil= require(`../modules/${store.state.profil}`);
// once you required it, you can use it in any place in the component.
profil.foo();
profil.bar();
Everything works for me in Vue 3.
You can assign the imported functions to refs 1️⃣, and then use the functions through the ref's value 2️⃣:
<script setup>
import { ref, watchEffect } from 'vue'
let foo = ref()
let bar = ref()
watchEffect(() => {
import(`../composables/profil/${store.state.formation.profil}-check`)
.then((module) => {
1️⃣
foo.value = module.foo
bar.value = module.bar
})
})
const fooAndBar = () => {
2️⃣
foo.value()
bar.value()
}
</script>
demo

difference between export default { name } and named export { name }

I am trying to deprecate a module with many named exports like so:
const Foo = () => 'foo';
const Bar = () => 'bar';
export { Foo };
export { Bar };
which is fine when consuming via:
import { Foo, Bar } from './something';
My thoughts about enabling deprecation warnings was to use a default export of type object with a property getter override for each key that prints the deprecation and then returns the module.
The shape then becomes something like:
const something = {};
Object.defineProperty(something, 'Foo', {
get(){
console.warn('Foo is deprecated soon');
return Foo;
}
});
// etc
export default something;
My thinking had been that the destructuring import would figure it out so
import { Foo, Bar } from './something';
... would continue to work as before. Instead, webpack complains that something does not have a named export Foo or Bar
using this, however, works:
const { Foo, Bar } = require('./something');
I can also have import something from './something'; const { Foo, Bar } = something and that works but it defeats the purpose if I have to refactor every import that exists.
So the question really is about how import { Foo, Bar } from './something'; works compared to the require() - I'd have thought that if the default export is an object, it would figure it out and destructure, but no joy.
Is there an easy way to do this 'proxying' without changing how the exports are being consumed elsewhere?
I think i made it work. Bare in mind that this is a workaround.
Given that you said that the library is being "re-exported" from a single file you could add an additional "layer" to the "re-export" where we turn the "re-exportation" file into a JS file and write our own associated typing file for it.
Working repl: https://repl.it/#Olian04/CelebratedKlutzyQuotes
Code snippets:
// index.ts
// consuming the library
import { Foo } from './demo';
console.log(Foo());
// library.ts
// the library it self
const Foo = () => 'foo';
export { Foo }
// demo.js
// the workaround implementation
const depricatedLibrary = require('./library');
const something = new Proxy(depricatedLibrary, {
get(obj, key) {
if (typeof key === 'string') {
console.warn(key + ' is deprecated soon');
}
return obj[key];
}
});
module.exports = something;
// demo.d.ts
// the workaround types
export * from './library';

react-native imported(?) function arguments is so weired

My react native project skeleton here
-app
--component
--LoginScreen.js
--container
--styles.js
-index.ios.js
-index.android.js
and styles.js....
...
export const colors = {
'green' : '#######'
....
}
export const test = () => {
console.log(arguments);
}
...
and LoginScreen.js
import { test } from '../styles';
export default class LoginScreen {
....
constructor () {
test();
}
....
}
so watch chrome debug console...
Arguments[5]
0:DedicatedWorkerGlobalScope
1:_require(moduleId)
2:Object
3:Object
4:null
callee:(global, require, module, exports)
length:5
Symbol(Symbol.iterator):values()
__proto__:Object
what is this?
imported function always return arguments[5]
I don't know why return that arguments.
I think that this related import? function.
Let me know please
Arrow functions do not bind their arguments. If you want to use variable number of arguments in React Native, you can use rest parameter syntax ... to get an array of arguments.
export const test = (...args) => {
console.log(args);
}
The arguments object should work with named function expressions:
export function test() {
console.log(arguments);
}

ES6 default and named exports

I am trying to understand named and default exports. I have a seemingly basic requirement which I don't understand how to setup.
I want to be able to import both:
//app.js
import Mod from './my-module'
import { funcA, funcB } from './my-module'
console.log('A', Mod.funcA(), funcA()); // A a a
console.log('B', Mod.funcB(), funcB()); // A a a
When I try, the closest way of doing this I get to is the following:
//my-module.js
export function funcA() { return 'a'; };
export function funcB() { return 'b'; };
export default {funcA, funcB}
My trouble is that I don't want to reindex each functions in the default export. I just want to define my functions and then make sure they are exported so I can use them either way.
Suggestions? Or do I have to use import * as Mod from './my-module';?
You can omit the default export and use import as syntax:
//app.js
import * as Mod from './my-module'
import { funcA, funcB } from './my-module'
console.log('A', Mod.funcA(), funcA()); // A a a
console.log('B', Mod.funcB(), funcB()); // B b b
//my-module.js
export function funcA() { return 'a'; };
export function funcB() { return 'b'; };
Import entire module's contents once using * as name:
import * as Mod from './my-module';
Then assign them to separate constants using destructuring:
const { funcA, funcB } = Mod;
For export just use the named exports:
export function funcA() { return 'a'; };
export function funcB() { return 'b'; };

Categories