Can I export an object using `export` as "`module.export`" - ecmascript-6

I think what I am asking for is not possible OOB, but I want to confirm.
We are in a process of upgrading to ES6 (using Babel). Project is a web-site, using AMD (requirejs). I would like to turn a utility module (foolib) into ES6, but consume it from either ES6 (using import) or existing ES5/AMD module.
// foolib.es6
export { // as expected, this doesn't work
method1: function () { ... },
value1: 123.456
};
// consumer1.es6
import foolib from "foolib";
// consumer2.js
define(["foolib"], function (foolib) {});
I understand that the solution is to change foolib.es6 as follows:
export function method1() { ... };
export let value1 = 123.456;
However in reality number of entries returned from foolib is ridiculous. So I was hoping there is a way to export existing object literal without rewriting every line.
Furthermore, I realize that this is most likely impossible, due to the differences between AMD import (using define) and import mechanism (later works with exports object that has values hanging off of it, including default value, while former expects a single value to be returned).
One possible solution that I think might work is to export my object as default from foolib.es6, and then tweak requirejs default loader to inspect imported value for being an esModule and return default value: value && value.__esModule && value.default || value. Should this work? (I'm still hoping there is an easier solution).

The syntax you are using to export the object is invalid because you are not giving the object a name, so it cannot be a named export, and you are not specifying that it is the default export, so it cannot be the default export. Change it to be the default export:
// foolib.es6
export default {
method1: function () {},
value1: 123.456
}
// consumer.es6
import foolib from "foolib";
console.log(foolib.value) //=> 123.456
You can use the babel-plugin-add-module-exports Babel plugin to reinstate a default export as the value of module.exports in Node-land.
And as you discovered, make sure you include this plugin before any other -modules- plugins, for example transform-es2015-modules-amd.

This might be late but alternatively you can use the named export as well which is a little different from the default approach that #sdgluck mentioned.
const method1 = function () {};
const value1 = 123.456;
export { method1, value1 };
I like this approach because you can import them directly like
import { method1, value1 } from 'foolib';
without reaching out to the default variable.

Related

Is there a way to print value in variable in angular4 component from console?

I save simple key in a variable in a component using angular 4, when the app closed every value will erased and i know it.
this is a simple sample :
export class LoginComponent implements OnInit {
data : any;
constructor() {
this.data = "Hello";
}
}
I just want to know is there a way using browser console to show value in this.data without console.log()?
Yes you can.
Start by finding some HTML that belongs to your component in your page. Then, inspect it.
In Chrome, you will see a $0 besides it. That's a variable reference.
Now, go into your console and type
ng.probe($0).componentInstance
This will log you your whole component, with the variables that are in it. You can simply give it a reference
const myRef = ng.probe($0).componentInstance
Then delete your component as you want, and log it again from the console directly
console.log(myRef) // or shorthand
myRef

Importing constants are undefined react redux

I have something like this:
//ActionTypes.js
export const a = 'a';
//Reducer.js
import a from './ActionTypes';
//export reducer function that uses string a
//Actions.js
import a from './ActionTypes';
return {type: a, data: 'something'}
but in both reducer.js and actions.js 'a' is undefined. There is no circular dependancy as far as i know. Pls help
I would export a with curly braces like so:
import { a } from './ActionTypes'
a is a named export because you gave it a variable name when you declared it like this:
export const a = 'a';
The syntax for importing named exports necessitate the use of {}.
The syntax that you've used apply to default exports. See below for an example:
export default function a() {
return 'a';
};
Default exports would not work for constants because you would want to declare a name for the variables. You may not use var, let or const with export default.
For more info, please see MDN docs for export
One other thing, it is convention to use ALLCAPS when naming constants.

Vuex how to declare constant root mutations

So I have a very similar Application Structure to the example below
https://github.com/vuejs/vuex/tree/dev/examples/shopping-cart
However, there is no root mutations defined there. I need to create one since I have to update the state that is dynamically created in vue-tables-2.
In my mutation-types.js I declared the name of the mutation as
export const UPDATE_CLIENTTABLE = 'UPDATE_CLIENTTABLE'
However, I'm not sure how to write the mutations in mutations.js There's no module defined because the state is dynamically created by vue-tables-2. I'm doing something like below but it doesn't work
[types.UPDATE_CLIENTTABLE] (state, data) {
state.ClientTableLine.data = data
}
You'll need to export your mutation in your mutations.js file
export const [types.UPDATE_CLIENTTABLE) = (state, data) => {
state.ClientTableLine.data = data
}
Then import it into your vuex set up
import * as mutations from './mutations'
export default new Vuex.Store({
mutations,
actions,
getters,
modules: {
cart,
products
},
strict: debug,
plugins: debug ? [createLogger()] : []
})
This is assuming your vuex set up is taken from the shopping car example

Typescript: how to get function name as string without TS2339 error

I found the following example in the Function.name documentation
const o = {
foo(){}
};
o.foo.name; // "foo";
The problem in typescript (typed here):
const o: { foo: () => void } = {
foo: () => {
}
};
o.foo.name;
comes when I want to retrieve
o.foo.name, where I will get an error
TS2339 (property "name" does not exist)
How can I deal with it, keeping the object typing?
I want to avoid having to cast the property "foo" like (<any>o.foo).name
PS: The use case is to keep the typing for further refactoring. For instance the following is safe to be refactored:
spyOn(o, (<any>o.foo).name)
While this one is not
spyOn(o, "foo")
PS 2: It seems retrieving function name could be problematic on ts: Get name of function in typescript
The problem is that this code only works for newer versions of Javascript. If you change the target on the typescript compiler settings to es2015 the problem goes away. If you target es5 the definitions for that version do not include the name property because it might not work on older Javascript runtimes.
If you are ok with targeting es2015, that is ok, if not you should come up with a different solution that works for es5.
If you are targeting an environment that supports this property but you don't yet trust the es2015 implementation for all features, you could just add the the Function interface the missing property. At the top level in one of your files you can redefine the Function interface, and this will be merged into the default definition, adding the extra property:
interface Function {
/**
* Returns the name of the function. Function names are read-only and can not be changed.
*/
readonly name: string;
}
Post ES2015, this:
const o: { foo: () => void } = {
foo: () => { }
};
console.log(o.foo.name);
should work just fine.
Check it in the Typescript Playground, and observe the produced JavaScript. You will see the common sections with the foo example you mentioned.
Here is the console, nice and clean:
Pre-ES2015, this wouldn't work and I think you would have to cast it, if targeting post-ES2015 is not an option.

es6 import as a read only view understanding

There is no detalied explanation of what exactly es6 import and export do under the hood. Someone describe import as an read only view. Check the code below:
// lib/counter.js
export let counter = 1;
export function increment() {
counter++;
}
export function decrement() {
counter--;
}
// src/main.js
import * as counter from '../../counter';
console.log(counter.counter); // 1
counter.increment();
console..log(counter.counter); // 2
My question is if two modules import the same counter module and the first module increment the counter, will the second module also see the the counter as incremented? What under hood do the "import" and "export" do? Under what context is the increment function executing on? What is variable object of the increment function?
// lib/counter.js
export let counter = 1;
export function increment() {
counter++;
}
export function decrement() {
counter--;
}
// src/main1.js
import * as counter from '../../counter';
console.log(counter.counter); // 1
counter.increment();
console..log(counter.counter); // 2
// src/main2.js
import * as counter from '../../counter';
console.log(counter.counter); // what is the result of this, 1 or 2?
It seems to me that the "export" is creating a global object that can be accessed by different modules and it is setting the context of the exported function to that object. If this is the case, the design is wired for me, because modules is not aware of what other modules do. If two modules are importing the same module(counter), one module calls the increment function(example above) which cause the value(counter) changed, the other module does not know that.
See section 16.3.5 here
As mentioned:
The imports of an ES6 module are read-only views on the exported entities. That means that the connections to variables declared inside module bodies remain live, as demonstrated in the following code.
//------ lib.js ------
export let counter = 3;
export function incCounter() {
counter++;
}
//------ main.js ------
import { counter, incCounter } from './lib';
// The imported value `counter` is live
console.log(counter); // 3
incCounter();
console.log(counter); // 4
How that works under the hood is explained in a later section.
Imports as views have the following advantages:
They enable cyclic dependencies, even for unqualified imports.
Qualified and unqualified imports work the same way (they are both
indirections).
You can split code into multiple modules and it will
continue to work (as long as you don’t try to change the values of
imports).
The answer depends on what is your entry module. For example, if you define an entry module as:
// index.js
import "./main1";
import "./main2";
Then the output is:
1 // from main1
2 // from main1
2 // from main2
ES6 modules are allowed hold state, but are not allowed to manipulate others modules state directly. The module itself can expose a modifier function (like your increment method).
If you want to experiment a bit, rollupjs has a nice online demo that shows how the standard imports and exports should work.