I am hoping my explanation provides enough information and that the answer is simple. This is for a project I have started recently and first exposure to JavaScript ES6 syntax.
We use RequireJS, and each page has two primary pages required: reports/pages/common and reports/pages/settings_page I believe these pages are analogous somewhat to controllers in Angular (which I have a little experience with).
The code is transpiled by gulp.
My question is, how do I call (from a method inside class SettingsPage) a method in an instance of the class CommonPage class? I do not know what the name of the CommonPage instance is but here is the script at the bottom, just before the </html> tag:
$(document).ready(function() {
// always loading bootstrap to enable data attributes to work
// only loading bootstrap once, see comment above.
require(['bootstrap', 'babelPolyfill', 'reports/pages/common', 'reports/pages/settings_page'], function(bootstrap, babelPolyfill, common, page) {
if ((window.fin) && (window.fin.pageInitArguments)) {
page.init(window.fin.pageInitArguments);
} else {
page.init();
}
common.init();
});
});
My question is, how do a reference (from a function inside class SettingsPage) a function in the class CommonPage?
It would be clearer if you used the term "method" instead of "function" here. I also presume when you say "reference a function in the class", you actually mean "call a method in the class on an instance of that class".
Well, an instance of a class is just a regular old object with methods sitting on its prototype. You call a method on such an object in the same way you have for years, by saying
object.method()
Related
so, i instantiate a new class in javascript, and then add it to a list ... Later I go through the list and instantiate all the classes again, to work with them.
the Javascript:
var BPmanager = Java.type('paperVS.tabs.blueprint.BlueprintManager');
var abstractFunction= Java.extend(Java.type('paperVS.logic.function.Function'));
var getYPos = new abstractFunction("getYPos") {
//Some Functions
}
BPmanager.allFunctions.add(getYPos);
and later in Java:
for (Function fun : allFunctions) {
try {
Class<?> c = Class.forName(fun.getClass().getName());
Object object = c.newInstance();
instances.add((Function)object);
} catch (Exception e) {
e.printStackTrace();
}
}
Exeption:
java.lang.ClassNotFoundException: jdk.nashorn.javaadapters.paperVS_logic_function_Function
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at paperVS.tabs.blueprint.BlueprintManager.getFromList(BlueprintManager.java:176)
This code works for all classes except the Javascript classes.
The Javascript works fine (loading and executing the single instance), but not instancing of the Class. The normal ClassLoader does the same
Java ClassLoaders use a delegation model, where the system instantiates a "primordial" (or "system") class loader, and then class loaders can be created that look in specialized places for classes, and if not found, look in the ancestor (or delegate) class loader.
Nashorn has its own internal class loaders to deal with script classes; see Java 8 ScriptEngine across ClassLoaders. So you are creating classes in those class loaders, and then trying to use them in an ancestor class loader (you can see that in the stack trace) by name.
So that's one problem to solve.
Another is that these types created by Java.extend are Nashorn-managed objects, bound to a particular Nashorn script context, and will be inconvenient to use from other Java code (see comments below, where the OP notes that the classes can't be used easily, even if they're accessible).
If you want to use the JavaScript-created objects in Java code, you'll want to create Java objects and then pass them back to Java. You seem to be doing this, so perhaps you're just using them incorrectly. Making guesses based on your class names, etc., I am guessing that rather than:
Class<?> c = Class.forName(fun.getClass().getName());
Object object = c.newInstance();
instances.add((Function)object);
... you may just want something like:
instances.add((Function)fun);
In javascript, if i'm not using a class, i can do something like this:
const Module = (function(){
const myArray = [];
const myObject = {};
return { //this is my interfaces
myArray,
myObject,
myMethod1,
myMethod2,
myMethod3,
myMethod4,
myMethod99,
}
function myMethod1(){}
function myMethod2(){}
function myMethod3(){}
function myMethod4(){}
function myMethod99(){}
})
This provides me with some kind of structuring that let me list all the publicly available properties and methods on top so it's easier to navigate between module and see what are the available things in a module, and also it's easier to navigate to the function when using Intellisense from IDE such as Visual Studio Code, just go to the module, click the method you want to go to, then press F12, it will bring you to the function.
Now different case with class in javascript:
class Module{
constructor(){}
myMethod1(){}
myMethod2(){}
myMethod3(){}
myMethod4(){}
myMethod99(){}
}
in this case i can't separate the interface and implementation making it hard to navigate through the code. Is there any possibility that the Javascript can handle this kind of case?
There are no private members in JavaScript, yet. There exists a proposal which includes this feature, and while it is at Stage 3, it has not yet landed.
There are also no interfaces in JavaScript, (since there's barely even a type-system) and it's unlikely that one will be added in the future.
Consider using TypeScript, it has both of those features.
I'm trying to understand the video "Understanding Function Currying" on Vimeo ( http://vimeo.com/41238143 but not necessary to view it in order to understand this question).
The example I understand
Early in the video, We’re told that there’s a problem with this code:
The problem with this code: the use of callback on line 11 and 14 won’t work because it’s out of scope — onSuccess exists in the buildCRUD scope, not the create scope. (I'll call this the "callback example".)
OK, that makes sense to me. Solutions are considered including using a single class variable (I know this terminology is off because javascript doesn't have classes, but you know what I mean).
The example I don't understand
Here's where I'm confused. At the end of the video, we're told that this code for a different part of the function will work. (Notice the "className" variable parameter; I'll call this the "className example".)
(Sorry, I cut off the line that says "var ...", just trust me that it's up there and createFn, getFn, etc. are all being declared as part of a long "var" line.)
As you can see, the implementation of these functions such as createFn do use the className variable, though it wasn't passed into the function as a parameter.
Here's my question: why is className in scope inside createFn? It seems to me that it’s no more in the forClass scope than onSuccess was in the create scope.
Does this have something to do with...
the fact that the function in the callback example is never being assigned as a variable inside the create function context, only called?
the callback example using promises?
My apologies everyone. The Vimeo recording may have had some errors.
To demonstrate a working solution, I created a working version of the Book CRUD service to demonstrate Partial Applications in JavaScript... used within an AngularJS application.
getFn = function (objectId, callback) {
// Simulate $http to get book information for
// specified ID.
var deferred = $q.defer(),
book = {
url : buildRequestURL(objectId),
title : "Learn to use Javascript Partial Applications"
author: "Thomas Burleson"
},
notifyFn = onSuccess(callback);
$timeout(function() {
notifyFn( book );
deferred.resolve( book );
});
return deferred.promise;
}
#see Full Source & Live CodePen Demo
There is a website, which uses this code below to create website functionality:
$(document).ready(function(){
{
function I_WANT_TO_ACCESS_THIS_METHOD(){
CODE HERE
},
SOME OTHER CODE
}
});
I want to update this website with a greasemokey script, but I don't want to duplicate code already written. That's why I want to access methods that are part of such objects (in the code above it is the I_WANT_TO_ACCESS_THIS_METHOD()).
I'm not a JS master and I'm not sure if it is even possible, but I think that this is the right place to ask ;)
I_WANT_TO_ACCESS_THIS_METHOD() is not a method of an object, but just a function defined inside another function. So you can't access it outside that function(the domcument ready callback function) scope.
For performance optimization I'm using a single JavaScript file to handle all the pages of the website I'm working on.
The basic structure I'm using is as followed:
(function($) {
// Shared functions ...
// A function for every page
function Page1() {
}
Page1.prototype = {
init: function() {
//...
},
//more functions
};
// more pages
$(document).ready(function() {
if ($('#page1uniqueidentifier').length) {
var page1 = new Page1();
page1.init();
}
// more pages
}
}) (jQuery);
I'm not an experienced JavaScript programmer so I've been searching a lot about best practices and different ways of structuring my code and I've ended up choosing this one but I'm not really sure about it and I have a few questions:
Is it worth it to use prototype if I'm never gonna have more than a single instance of a page? I think I understand how prototype works and that I'm not gaining any performance there. But I'm using it just as a best practice because in the case different instances would exist, these functions would be the same in every instance.
Is there a better way to structure the code?
Should I put the call of the init function inside the constructor and then only call new Page1()?
function Page1() {
this.init();
}
if ($('#page1uniqueidentifier').length) {
new Page1();
}
For performance optimization I'm using a single JavaScript file to
handle all the pages of the website I'm working on
That makes no sense. You should separate code into files, and then run all your js files thru a minimizer/concatenator to package it up.
Anyway, to answer your questions,
if you are only going to have 1, then prototype won't buy you anything. However, if you are going to use more than 1, would you go back and change it? Plus, using prototype wont hurt you either, so you might as well do it for learning.
You should create the files that make sense according to the functionality implemented. I would separate your object definition into its own file, for example, so when you look at that file, all you see is the code for that object.
If you have a constructor function, you don't really need init, do you?