ES6 class store [duplicate] - javascript

This question already has an answer here:
ES6 classes : what about instrospection?
(1 answer)
Closed 6 years ago.
I just can't find out where the references to declared ES6 classes are stored, I would have expected them in the window Object, bit they don't appear there.
I don't think it's a duplicate of ES6 classes : what about instrospection? since he is asking for a existance check of a class, what I want is a list of available classes.
For example:
class Test {
constructor() {
}
}
window.Test // undefined
What I want is a list of all classes that extend a class of mine
To clarify that I have a structure that looks something like this:
class Base {
constructor(components) {
for(let component of components) {
window[component](); // window.Test2 not defined
}
}
start() {
new this();
}
}
class Test2 extends Base {
constructor() {
super();
}
}
class Test extends Base {
constructor() {
super(['Test2','Test2']);
}
}
Test.start();
That's just an abstraction of my structure, in short I have to use strings at super(['Test2', 'Test2'])
At the moment I'm doing something like this
Base.register(Test2);
for every class and I want to get rid of that.

You can use Class expressions to store them in some sort of array, although I probably wouldn't do it, if I were you.
var Test = class Test {
constructor() {
}
}
allClasses.push(Test);

JavaScript classes are introduced in ECMAScript 6 and are syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax is not introducing a new object-oriented inheritance model to JavaScript. JavaScript classes provide a much simpler and clearer syntax to create objects and deal with inheritance.
Basically ES6 classes are compiled to plain old-fashioned Javascript functions. You may "store" them at the window object but this is a major pitfall as you are killing the whole module patter ES6 introduced.

If you want sort of a "module" of classes, you could theoretically do something like this:
// some-class.js
export default class SomeClass {}
Then:
// another-class.js
export default class AnotherClass {}
And your entry file:
// index.js
import SomeClass from './some-class.js' // extensions optional; here just for clarity
import AnotherClass from './another-class.js'
export default {
SomeClass,
AnotherClass
}
If you have all of those embedded in the same directory (we'll call the directory example), you can just import that entire module wherever you need it:
// something-that-requires-your-module.js
// this will by default enter through the `index.js` file of your `example` directory
import Example from './example';
console.log(Example.SomeClass);
console.log(Example.AnotherClass);

Related

Javascript set required library as module export for purposes of inheritance

One small request before I begin. Please hold back on the "classes are syntax sugar" responses. That could turn my question to a place where I don't actually get an answer. I get the idea on that and this is a specialized project where classes are a must.
What I am doing is setting up a convenience class that is used to include common libraries in several other classes; ex: loggers, etc...
The idea is to setup a general class with required libraries assigned to class properties, and have other classes extend the general class and receive the required libraries.
I have this working. The question is if it is a bad idea or practice to setup class inheritance for this purpose?
// base_class.js
const SomeUtility = require('../common/utility/utility');
class BaseClass {
constructor() {
this.SomeUtility = SomeUtility;
}
}
//api_class.js
const BaseClass = require('./base_class.js');
class APIClass extends BaseClass {
constructor() {
super();
}
apiCall(req, res) {
this.SomeUtility.logReq(req); //super.SomeUtility also works...
}
}

How can I export classes from Typescript factory functions?

I'm working on an Angular/Typescript application that has been partially converted from Javascript (there are class definitions, but fields and variables are mostly untyped, and the style remains very js-like).
Many classes are defined inside factory functions like this:
export default function SomeClassFactory($http) {
class SomeClass {
constructor() {
// initialise
}
someMethod($http) {
// do something with $http
}
}
return SomeClass;
}
It seems to be impossible to export inner classes defined in this way for use in import statements. I have tried moving the class declaration outside the factory function, but this fails when the class uses values that Angular injects, as in the example. (Presumably these injected values are effectively static members of the class.)
How can I export a class defined in this way?

Can I define an ES6 static method from an imported object?

If I define some class:
class MyClass {
static myVar = { someKey: someVal };
...
}
but instead of defining the static variable from within the class, I want to import it from another file:
// utils.js
export const someObject = { someKey: someVal };
...
Will this work?:
import { someObject } from './utils.js';
class MyClass {
static myVar = someObject;
...
}
edit: The title to this question would more accurately be: "Can I define an ES6 static field from an imported object?" Static fields are currently a stage-2 proposal for JS. See #T.J.Crowder's answer below. and require the "babel-preset-stage-2" transpiler.
That's not a static method, it's a static field (which isn't standard yet; static fields are currently at Stage 2, although it's common to transpile the syntax as the basics of it seem unlikely to change).
But provided the semantics when static fields are standardized are as they currently stand (and it would be weird if they weren't), yes, you can do that. The initializer of a field can be any expression, including one that uses an imported binding.
If you want to do it now, without transpiling or waiting for static fields to become standard, just do the assignment afterward:
import { someObject } from './utils.js';
class MyClass {
// ...
}
MyClass.myVar = someObject;

Difference between Class and Object in typescript

Someone could explain me what is the difference between class and object in typescript.
class greeter{
Name: string;
Sayhello(){
console.log("hello")
}
}
Before I using this
var greeter = {
Name : "",
Sayhello: function sayhello(){
console.log("hello");
}
}
It is up to you. Both of these are valid and idiomatic TypeScript:
export class Greeter {
name: '';
sayHello() {
console.log('hello');
}
}
and
export const greeter = {
name : '',
sayHello: () => {
console.log('hello');
}
}
// if you need just the type of greeter for some reason
export type Greeter = typof greeter;
If you don't have a need for the class, don't use them.
But you may find benefits of classes if you want to:
manage your dependencies with Dependency Injection
use multiple instances
use polymorphism
If you have multiple instances, using classes or prototype constructor functions, allow you to share method implementations across all instances.
Even if you are in a purely functional paradigm, using prototype constructor functions or classes can be useful for creating monads.
If you only have one instance, and do not need for a constructor, an object is is probably fine.
There are many differences. On a basic level, a class is an object that can be used to create other objects with a specific shape and functionality. It provides syntactic sugar for functionality that would be a lot more work to accomplish with plain objects and functions.
You should take some time to read about what classes are in the TypeScript Handbook because answering your question in detail would be equivalent to writing a few chapters of a book—especially when tailoring it for TypeScript.

How to namespace es6 classes (for React components)

This is part ES6 question part React question. I'm trying to use namespaced components in React with ES6 classes and Babel. So I guess the real question is how to name space es6 classes so I can do what is explained here: https://facebook.github.io/react/docs/jsx-in-depth.html#namespaced-components
Since I get an unexpected token error:
class Headline extends Component { ... }
class Headline.Primary extends Component { ...
^
The ECMAScript-6 class declaration syntax expects a standard BindingIdentifer as the class name. A dot is not a valid character inside an identifier name.
In the context used in the link in OP, the "namespace" is an object, and properties are added to that object one by one using the dot notation for property access.
You could replicate that by using a class expression instead:
'use strict'
var ns = {}
ns.MyClass = class {
constructor() {
console.log('in constructor')
}
}
new ns.MyClass()
This doesn't really change with ES6, you still will have to do an assignment:
Headline.Primary = class Primary extends Component { … };
However, using classes like Headline as namespaces is getting pretty deprecated with ES6 (and has previously been a questionable practice anyway), you should instead leverage the new module system. Export Primary as a named export, and instead of importing the Headline class rather do import * as headlines from ….
This link also relates to this question.
In the Module objects section, it is described that you can do something like this:
// headline.js file
export {Headline, Primary}
class Headline {}
class Primary {}
// In another module...
import * as Headline from "headline";
let h = new Headline.Headline();
let hp = new Headline.Primary();
It's not exactly what you are trying to do, but is an alternative.
Another way of doing it is almost like #Bergi has already pointed out, but I'm just clarifying it further:
let Headline = class Headline extends Component { }
Headline.Primary = class Primary extends Component { }
export {Headline as default}
// in another module:
import Headline from 'headline';
let headline = new Headline();
let primary = new Headline.Primary();

Categories

Resources