I'm working with babel-loader inside webpack for the first time, and I'm very new to ES6 as well. I'm trying to export a base class from one file and import it into another. Exporting and importing has worked fine throughout my file thus far, and I am just now hitting a problem with it for the first time while trying to create classes.
Here's what my code looks like:
BaseClient.js
export default class BaseClient {
// snip...
};
SessionClient.js
import BaseClient from './BaseClient';
// outputs "undefined":
console.log(BaseClient);
// throws "Uncaught TypeError: Super expression must either be null or a function, not undefined":
export default class SessionClient extends BaseClient {
// snip...
};
Am I doing something wrong? Is there any relevant information I'm missing from my question that's needed before diagnosing? Thanks!
Yeah, I met the issue as well. It's caused by circular reference between different files in very long reference chain.
Like following:
Related
I have a huge list of permissions, and I'm only interested in importing three of them. I'm also interested in grouping them in an object and assigning a variable to that object.
Can I do any better than the following?
import {
firstPermission,
secondPermission,
thirdPermission,
} from '#constants/permissions';
const relevantPermissions = { firstPermission, secondPermission, thirdPermission };
I was inclined to try using the as keyword in the import step, but I couldn't get any such thing to work.
(This feels like an ignorant question; please forgive.)
as keyword is intended to import named exports under different names, not group them.
The code listed in the question is the way this should be done. If relevantPermissions is supposed to be used in multiple places, it's beneficial to re-export them:
export {
firstPermission,
secondPermission,
thirdPermission,
} from '#constants/permissions';
...
import * as relevantPermissions from './relevant-permissions';
This way named imports have a chance to be tree-shaken if some of them remain unused, also may get other benefits of ES modules such as improved code completion in IDEs.
I am doing the following (both of the exported are objects):
SlateInfo.js
export default {SlateRules, SlateSchema};
and then in another file
import {SlateRules, SlateSchema} from 'SlateInfo';
But what I get is that SlateRules is defined as an object containing SlateRules and SlateSchema
SlateSchema is left undefined.
Where am I going wrong/what am I misunderstanding?
import {SlateRules, SlateSchema} from 'SlateInfo'; is for importing named exports. However, export default {SlateRules, SlateSchema}; is a default export, exporting an object with two properties.
If you want named exports then you need to omit the default:
export {SlateRules, SlateSchema};
Or use a default import and destructure the object:
import SlateInfo from 'SlateInfo';
const {SlateRules, SlateSchema} = SlateInfo;
When should I use curly braces for ES6 import? has a lot of examples showing how named and default exports work.
I have created a simple parser package called parseLine.
I have it in a package in my project.
In parseLine I have a class called "myParse".
I can import it just fine.
import parseLine.myParse.*;
But when I compile I get an error "1172:Definition parseLine.myParse could not be found.".
This is pretty basic I know but would appreciate any help anyone my be able to offer.
myParse is not a package, it is a class, so you are importing it incorrectly.
Basic structure of a package:
src / my / package / name / ClassName
To import ClassName, you would use this:
import my.package.name.ClassName;
or
import my.package.name.*;
In ClassName, it must have the following setup:
package my.package.name {
public class ClassName {
// class code goes here
}
}
As an additional tip, you should follow standard naming schemes for AS3.
Package names should be all lowercase. Even if it is multiple words. my.packagename is proper, whereas my.packageName is not.
Class names should be UppercaseCamelcase. So ClassName is proper, whereas className and classname are not
All objects, including functions, should be lowercaseCamelcase. So var someObject is proper, whereas var SomeObject is not (same for function doSomething() vs function DoSomething())
Constants should be UPPERCASE_UNDERSCORE_SEPARATED. So const SOME_CONSTANT_VALUE is proper, whereas const someConstantValue is not.
Not using those rules won't break anything, but they are the accepted standards in AS3 which makes your code easier to read and maintain in the future.
public function starttank(event:MouseEvent):void
{
var Tankdrive:TankDrive = new TankDrive();
Tankdrive.tankstart();
}
It's saying that something in that function contains invalid data.
I have no idea what it is, i checked TankDrive and tankstart(); and both are correct, tankstart() is a public function...
I'm stumped...
EDIT: Error:
Error #2136: The SWF file file:///C|/Users/BigRed/Desktop/TankDrive/TankDrive.swf contains invalid data.
at mainmenu/starttank()
That's the error...
And above the starttank() function is still the same...
Ok, I looked over the files.
I'm puzzled by what you are trying to do.
Your Document class is TankDrive, and it creates an instance of mainmenu, which create ANOTHER instance of TankDrive when you click a button. Which is not what I think you want to do, or you think it's allowing you to access your document class. -- it's not. It's attempting to create a whole new instance of your game.
In short, your design is not making sense, and it's also causing a conflict with the document class resulting in that error.
The quick solution is to NOT have your EventListener & handler for the click in the mainmenu class, and then call the tankstart() method of your document class instead of attempting to create a new instance of TankDrive.
First move that listener into the document class and modify like this :
main.enterTank.addEventListener(MouseEvent.CLICK, starttank);
and then move your handler to the TankDrive class and modify as follows :
public function starttank(event:MouseEvent):void
{
tankstart();
}
This is not the only way to do this, and not really the way that I would do it. But I think that discussion is beyond the scope of this question.
If you want you can contact me at prototype.in.training#gmail.com for more details on that.
The problem is that you have an instance name that's also a class name (and the compiler has assumed that you meant to reference the latter). You probably meant to call your TankDrive variable 'tankDrive', so changing your code snippet to the following will probably help:
public function starttank(event:MouseEvent):void
{
var tankdrive:TankDrive = new TankDrive();
tankdrive.tankstart();
}
It's common and recommended to start all public variable names with a lower case letter, private variables with an underscore, and class names with a capital, though this isn't enforced by the language itself, so this kind of thing can happen.
Here are some guides on conventional variable and function naming that can help you keep track of what each of your vars and functions are supposed to do:
http://www.adobe.com/devnet/actionscript/learning/as3-fundamentals/variables.html
http://www.adobe.com/devnet/actionscript/learning/as3-fundamentals/functions.html
Good luck!
I am using flash.utils.getDefinitionByName in an attempt to grab an art asset. I use this function quite a bit and haven't had trouble until now. Check it:
assetName = Assets.MegaBerry; // works
assetName = getDefinitionByName("Assets.MegaBerry") as Class; // doesn't work
What the heck?? Error response for the second line is "Variable not found."
If it matters: Assets is a file in my root source directory (it has no package; Assets is the fully qualified name) and I've tried putting:
import Assets;
at the top with no luck.
For reference, in Assets.as I have:
[Embed(source = "../art/Inventory/MegaBerry.png")]
public static var MegaBerry:Class;
Your problem is that embedding the resource into the Assets class will create a static variable of type Class that belongs to that class - which is what you are referencing when you use Assets.MegaBerry: A variable(!) of type Class.
It does not, however, register the MegaBerry class to a fully qualified class name. To do this, you have to use - who would have guessed it - registerClassAlias at some point in your application:
registerClassAlias("Assets.MegaBerry", Assets.MegaBerry);
After that, it will be available everywhere else when calling getDefinitionByName.
** EDIT **
Well that's some unexpected behavior... It turns out, the class that was embedded is in fact automatically registered, but under {className}_{variableName}, instead of the notation you would expect. So using:
getDefinitionByName("Assets_MegaBerry") as Class;
should to the trick.
registerClassAlias also works, but then you need to call getClassByAliasinstead of getDefinitionByName. Sorry for the mix-up.
** END EDIT **
You can also use the Embed tag to inject the resource into a separate class file, which you can then reference as expected by using getDefinitionByName, or simply using an import:
package assets {
[Embed(source="../art/Inventory/MegaBerry.png"]
public class MegaBerry extends BitmapData {
}
}
Instead of calling
assetName = getDefinitionByName("Assets.MegaBerry") as Class;
, instead just use:
assetName = Assets["MegaBerry"];
try:
[Embed(source = "../art/Inventory/MegaBerry.png" , symbol="MegaBerry")]
public static var MegaBerry:Class;
In actionscript, objects actually have a name property that is different from the actual variable name as it shows in code.
For example, if you create a variable as follows,
var myBerry = new MegaBerry();
Then getDefinitionByName("myBerry") will return null.
Only when you set the name of the variable by writing myBerry.name = "myBerry", will getDefinitionByName("myBerry") return what you want it to. The name of the object doesn't necessarily have to be equal to the variable name in code.
In your specific case, I don't think you need to use any of that anyways. Have you tried assetName = new MegaBerry() ?
If you want to find out what the fully qualified name of you class really is, you may do the following:
trace(getQualifiedClassName(Assets.MegaBerry));
You may do that from inside Assets.as, for instance.
You can feed that string back to getDefinitionByName() and get a reference to the class.
trace(getDefinitionByName(getQualifiedClassName(SomeClass)));
// output [class SomeClass]
And remember, getDefinitionByName() only gets you references for classes that are in the same scope as the getDefinitionByName call itself. So, if you are loading external SWFs, getting class references will depend on the application domain you are using and the place, where this code executes.