es6 how to export native object - javascript

I want to extend js native object with a new function then export that function, I tried something like this
export Object.prototype.renameProperty = function () {
console.log('do stuff')
}
I got unexpected token error. What the right way to do this?

The whole point of using modules in ES6+ is that you don't need to modify the prototypes of objects you don't own. But if you must write it this way, you'll need to either just declare the code in the file without an export:
prototype.js
Object.prototype.renameProperty = function () {
console.log('do stuff')
}
And import it like so:
import "./prototype.js";
Or if you really need to both add it to the prototype and export it, then:
prototype.js
export const renameProperty = Object.prototype.renameProperty = function () {
console.log('do stuff')
};
And import it like so:
import {renameProperty} from "./prototype.js";
({}).renameProperty(); // do stuff
renameProperty.bind({})(); // do stuff

Related

Vue Composition API: Is there a better way in calling `emit` inside consumable file?

What is the correct way (or a better way) to access emit in the separated logic file?
This is what I did currently that works:
foo.js
export default (emit) => {
const foo = () => { emit('bar') };
return { foo };
}
Then on the consuming component:
import { defineComponent } from '#vue/composition-api';
import foo from './foo';
export default defineComponent({
setup(props, { emit }) {
const { foo } = foo(emit);
return { foo };
}
});
But I wonder if there is a more appropriate way on doing this? Or is it a bad practice to call emit inside a consumable file?
You probably have found the solution, but in case you would try similar way (as originally asked in question), there's this option called getCurrentInstance that has an emitter (the Vue 2 plugin for Composition API has one too).
import { getCurrentInstance } from 'vue';
export default () => {
const { emit } = getCurrentInstance();
const foo = () => {
emit('bar');
};
return { foo };
}
But bear in mind that this will only work for calling functions/components that have the SetupContext.
Edit
The above solution will work for Vue 3, yet with earlier version of Vue + the Composition API plugin, there is but a slight difference: As with the rest of the Instance Properties, you'll have to prefix it with $ to become $emit. (The following example now assumes Typescript as the target language, as mentioned on the comment).
import { getCurrentInstance } from '#vue/composition-api';
export default () => {
// Ugly workaround, since the plugin did not have the `ComponentInstance` type exported.
// You could use `any` here, but that would defeat the purpose of having type-safety, won't it?
// And we're marking it as `NonNullable` as the consuming components
// will most likely be (unless desired otherwise).
const { $emit, ...context } = getCurrentInstance() as NonNullable<ReturnType<typeof getCurrentInstance>>;
const foo = () => {
$emit.call(context, 'bar');
};
return { foo };
}
For Vue 3's Composition API, however, they do have this ComponentInternalInstance interface exported.
P.S. It's probably best to stick to the old-school way of assigning the instance to a variable and do context.$emit or vm.$emit rather than having to explicitly specify a context for everything. I initially came up with this idea without realizing that those Instance Properties are probably meant for internal uses, which is not exactly the case with the next Composition API.

Using async js imports in exported classes

Given a package that exposes async/dynamic exports. Which I currently import this way (but I could import it differently):
(async function() {
const libEd = await import("../../.cache/ed25519wars/index.js");
})();
I intend to re-expose some functions from libEd as part of a class:
export class Something {
static from_X() {
return libEd.genFromX();
}
do_Y() {
return libEd.doY();
}
}
How can I do this ?
For more info:
The package that exposes async/dynamic exports is generated by webpack packing webassembly. I'm not sure if I can change anything about this part
I could definitely change the way I import that package
I could also change the way I re-expose / group the functions (and use something else than a class)
There's a couple of ways I would approach this:
If the class doesn't need to be instantiated immediately, then I would await the library loading, then pass it to the class constructor. This is the cleanest way as the library is always defined within the class.
If the class must be instantiated before fetching the library, then methods in the class must handle the situation when it is not defined (e.g. not loaded yet). You can then call something like await myClassInstance.init() to fetch the library. I typically provide a fallback for each method if the library is not loaded yet, perhaps it returns an empty string or a dummy UI.
EDIT: adding TypeScript example for option 1
interface MyLibrary {
libraryMethod: () => void;
}
class ExampleClass {
localLib: MyLibrary;
constructor(lib: MyLibrary) {
this.localLib = lib;
}
myClassMethod() {
this.localLib.libraryMethod();
}
}
async function run() {
// first we fetch the remote library
const myLibrary: MyLibrary | undefined = await import('/lib.js');
// good practise to add some check here
if (!myLibrary) {
throw Error('failed to fetch myLib');
}
// then we create the class instance using the downloaded library
const myClassInstance = new ExampleClass(myLibrary);
// now we can call our class method which definitely has the remote library
myClassInstance.myClassMethod();
}
I ended up settling on either of three methods:
#Tim's method (accepted answer): include the import in the class properties, and await at constructor time.
But: there might be overhead associated with storing the import in each instance.
awaiting in each method of the class to have the import defined there:
export class Something {
static async from_X() {
const libEd = await loadLibProm();
return libEd.genFromX();
}
async do_Y() {
const libEd = await loadLibProm();
return libEd.doY();
}
}
But: the class API is now all async and more awkward to use.
Pre-loading the import at code start. And hoping the load is going to be finished when the class is called.
let libEd: typeof import("../../.cache/ed25519wars/index.js");
async function loadLibProm(): Promise<
typeof import("../../.cache/ed25519wars/index.js")
> {
libEd = await import("../../.cache/ed25519wars/index.js");
return libEd;
}
loadLibProm(); // this somehow starts running the promise ?? wut ? Anyways that's what we want
export class Something {
static from_X() {
return libEd.genFromX();
}
do_Y() {
return libEd.doY();
}
}
But: this needs better error handling for the case an instance of the class is created before the import is finished / after the import failed.

Can React Hooks have methods?

How does one write a React Hooks function to export methods in the export default?
I don't see examples anywhere, so I suspect that React Hooks don't work this way, but... I'm curious if it is possible to extend the hook function to export child methods.
Checkout.js:
import React from "react";
function Checkout() {
return <section className="checkout"></section>;
}
// Add Item Method
Checkout.addItemPrice = (item, price) => {
console.log("this is a method");
};
export default Checkout;
Checkout.test.js:
import React from "react";
import ReactDOM from "react-dom";
import Checkout from "./Checkout";
describe("Checkout Test Suite", () => {
it("Can add an item", () => {
var checkout = new Checkout();
checkout.addItemPrice('a', 1);
});
});
TypeError: checkout.addItemPrice is not a function
I haven't been able to find a way to write this in Hooks, but at the end of the day, I wind up splitting them into 2 functions, with 2 exports, and 2 imports.
Nothing to do with hooks. If you want your new Checkout() instance to have a addItemPrice method, then you should add it to the prototype:
Checkout.prototype.addItemPrice = (item, price) => {
When you execute:
var checkout = new Checkout();
an object of type reactComponent is returned to a checkout variable regardless of New keyword is used or not.
This object doesn't have a method you are trying to call.
You may try to define your method using a prorotype chain of this object (of reactComponent), but this object may be protected against any changes.
Even if you manage to set a method to reactComponet, this is not a good thing and surely not a React way to do things.

How to properly import namespaced code used in Webpack/es6/babel?

I'm currently working on a ReactJS project and I'm trying to come up with an effective way to namespace my code. The most obvious solution I have is to do the following:
let API = {
init: function() {
// Do some type of initialization here
}
makeACall: function() {
// Make a call
}
};
Previously, I'd make a file of functions each of which were exported like:
export function makeACall() {
// Make a call
}
And then I'd import it into another file using: import { makeACall } from 'utils/api';
However the problem here is that I may have another function in the imported file called makeACall. So what I'd like to do is namespace it. Question is: how do I import individual functions from an object/namespace or is this not possible?

Patch/mock function inside another function for testing in javascript

Basically I'd like to patch functions that another function calls so that I can confirm they've been called. Is this possible in js? (I'm using Mocha/Chai/Sinon for testing).
A simplified version of what I'd like to do:
// in render.js
export helper = function() {}
export default = function() {
helper()
}
// in the render-test.js
import render, { helper } from 'render'
// what I'd like to to:
helper = sinon.spy()
render()
assert(helper.called, true)
It's possible, but it does require some rewriting, most notably the way you're calling helper in render.js.
Here's an example that works:
// render.js
export function helper() {}
export default function() {
exports.helper()
}
// render-test.js
import render, * as renderFuncs from 'render'
...
sinon.spy(renderFuncs, 'helper');
render()
assert(renderFuncs.helper.called)
The reason you need to call exports.helper() instead of just helper() is because the latter is a local reference to the helper function, which you can't access from the test file.
The exports object is accessible from the test file (it's given the name renderFuncs), so Sinon can change the reference to helper and wrap it with a spy.

Categories

Resources