Entire JS inside one global variable? - javascript

I've got a school assignment of creating an app and one of the restrictions were that only one global variable was allowed, named "App". So I need to put the whole JS inside this variable.
I thought of doing something like:
App = function() { this.test = () => alert("test"); }
And then calling it with App.test().
But this doesn't work, the error I'm getting is:
Uncaught TypeError: App.test is not a function at HTMLLIElement.onclick (index.html:25)
Am I doing something wrong?

You need to define your app in a variable as an object and then you can use those members of the object such as:
// Object creation
window.App = {};
Then you add more properties like functions or variables and use it later inside of that variable.
window.App.test = function() {
alert('test');
}
window.App.variable = 'my variable';
console.log( App.test() );
console.log( App.variable );
Another thing is you can omit the word window from App.

Keeping most of your approach as it is, you could return an object that has functions as properties.
App = function() {
return {
test: () => alert("test"),
test2: () => alert("test2")
};
}
App().test();
App().test2();

To be able to use your function that contains this.test..., you'll need to use it as a "constructor function" because this in a function declaration means "instance property", meaning you will need to explicitly create an instance of App with the new keyword:
// Declare the global
var App = function() { this.test = () => alert("test"); }
// Make an instance of an object via the constructor function
var myApp = new App();
// Invoke the functionality via the instance
myApp.test()
Or, set up App as an object, connect that object to the Global window object and set test as a property of App all without any instance properties (this references), which avoids having to make the explicit instance:
// Declare the global property as an Object
// and set up a "test" property that stores
// a function in that object:
window.App = { test: function(){alert("test");}}
// Invoke the functionality directly
App.test()

The test function is not defined before executing the App function:
App = () => test = () => alert("test")
<button onclick='App(); test()'>:</button>
App can be defined as object instead:
App = { test: () => alert("test") }
<button onclick='App.test()'>:</button>

Just to piggyback on to what the other answers have suggested, this technique is most commonly used (in browser developement) when you "namespace" some JS code. Namespacing is useful because it helps the developer reduce global variable pollution by adding all their code under one namespace under window.
This also helps the developer modularise the code.
Here's a pattern you might see from time to time that adds code to a single namespace under window.
// This first function is what's known as an Immediately-invoked
// function expression (IIFE). `window` is passed in as an argument
// to the function - all other declared variables are local to the scope
// of the function so you don't get anything leaking to global.
// PS, the semi-colon is there before the opening parenthesis to prevent
// any errors appearing if you minimise your code
;(function (window) {
// Here we declare something new to add to the namespace
// It could be another object, a string, an array, or a constructor
// like Model
function Model() {...}
// If namespace `window.app` doesn't exist instantiate it with
// an empty object. If it _does_ exist it probably means that another
// module like this one has already been added to the namespace.
window.app = window.app || {};
// Then assign your new module as a property under that namespace
window.app.Model = Model;
})(window);
You can then use it later something like this:
var model = new app.Model();
var game = new Game(model);
For further reading: Addy Osmani on namespacing.

Related

Can not bind 'this' to imported function - javascript

I am a beginner and I want to bind 'this' to helper-functions which I have imported from an other file (that I can use the variables, I created in the current lexical environment ).
But I have recognized, that I can bind these imported functions to any object - which I have created in the file, into I have imported them - but not to the current this.
node.js example:
https://github.com/sdeli/issues-with-this
// random-js-file.js
// this is the function I import in app.js
function logOutThis() {
console.log(this);
}
module.exports = logOutThis;
// --------------------------------
// app.js
const importedFn = require('./random-js-file.js');
// this is now the global of random-js-file.js
importedFn();
console.log('--------------------------------');
var monkey = {
chimp : 'chimp'
}
// this is now the object 'monkey'
var myfunction = importedFn.bind(monkey);
myfunction();
console.log('---------------------------------');
//this should be now the current this
var myfunction2 = importedFn.bind(this);
myfunction2();
// console.log displays '{}' and i can not refer to the variable in this lexical environment
So I dont understand why I can not bind 'this' into a function which I have imported but I can bind it to any object.
Thank you for your suggestions
There isn't a way to access the inner context of an imported module unless it explicitly exports the bits you want (or provides functions that expose them). Javascript this doesn't behave like Java this, and modules aren't classes.
There's some other cases, but basically, if the function you're currently is called someFunc and it was called with syntax a.someFunc(), then this will be the same as a. Here's a worked example:
const someObject = {
someFunc() {
//Here, "this" will be the same as someObject, because of the way we called it
someOtherFunction();
}
};
someObject.someFunc();
function someOtherFunc() {
//"this" is still someObject because it's inherited from the calling function which was not called using a method syntax
x.y(); //inside the y() function, "this" will now be x
}
Basically, IMHO, this is a broken mess in Javascript and is one of the key reasons I avoided using it whereever possible. That means I don't use classes, and I get everything I need from closures.

Javascript Namespaces and undefined function

Can someone explain how to do this properly
foo(); //outputs 'foo'
function foo(){
console.log('foo');
}
but this gives 'function is undefined' error
MY_NAME_SPACE ={};
MY_NAME_SPACE.foo(); //undefined
MY_NAME_SPACE.foo = function(){
console.log('foo');
}
I can see that in the second example, the call was made before the function was added to the My_NAME_SPACE object, but if this is the case,how would one use this type of "name space" if the ordering is important?
Yes, if you are going to use this namespace pattern, you will need to create and populate the namespace before trying to invoke methods or access property values that have not yet been assigned to the namespace.
Instead of defining the namespace object and then defining each consecutive method in the namespace, eg:
var MY_NAME_SPACE = {};
MY_NAME_SPACE.foo = function() {
console.log('foo');
}
I prefer to use what is referred to as the module pattern, as the methods that I want contained in MY_NAME_SPACE are visually wrapped in the module:
var MY_NAME_SPACE = (function () {
var foo = function () {
console.log('foo');
};
return { foo: foo };
})();
MY_NAME_SPACE.foo()
Also, if the methods you wish to wrap in a namespace or module are independent and reusable, it would makes sense to create a separate file, maybe my_name_space.js, and include this file in projects that need access to the methods in MY_NAME_SPACE (the MY_NAME_SPACE API).

javascript typeerror it's not a constructor

There is a javascript file with require js framework
init: function(){
var self = this;
self.commonSolutionManager = new solution.CommonSolutionManager();
},
I am creating jasmine test cases for testing the above code . I am creating an object for the above file with this constructor
function solution()
{
CommonSolutionManager = function(){};
}
but it's throwing error "TypeError: solution.CommonSolutionManager is not a constructor"
This block of code places your constructor inside a closure which scopes the constructor to ONLY be accessible with in the closure.
function solution()
{
CommonSolutionManager = function(){};
}
This block of code tries to access the constructor as if it where a property of solution; but it's not, it's more like a private variable with in the solution function.
self.commonSolutionManager = new solution.CommonSolutionManag();
You probably wanted your constructor to be defined in the following way.
// create the solution object and store it in the global namespace
solution = window.solution || {};
// create the constructor
solution.CommonSolutionManag = function() {};
// now you can use the constructor
var csm = new solution.CommonSolutionManag();
NOTE: If you're using requireJS, then this probably isn't the approach you want to take. See RequireJS: How to define a constructor?
You're using solution as an object but it's a function. Not clear on how it should work but the following should fix the problem:
var solution = new function() {
this.CommonSolutionManager = function(){};
}
And you can then use new solution.CommonSolutionManager()

Communication between scripts | Three methods

How do I properly communicate data betweens two scripts.
In this particular case I have an element in one script, but I want to append it in another script.
The simplest way I could do this is by using the global window object as go-between.
But globals are not best practice.
What is the correct way to pass this element to another script?
Both script are encapsulated in the module pattern.
Script 0 Create Element Point
var element = document.createElement( "div" );
element.innerHTML = response_text;
Script 1 Append Element Point
Vi.sta = {
// implemented in the boot loader - shared global space - appended child already - you don't have to append until now.
// Static data has already been composed.
// Pull off window and append or best practice
};
Both are encapsulated in the module pattern
(function(){
// the code here
})()
All JS scripts are run in the global scope. When the files are downloaded to the client, they are parsed in the global scope.
So if you've got
// File_1.js
var myObj = { colour : "blue" };
There's nothing stopping you from doing this:
// File_2.js
var otherObj = { colour : myObj.colour };
As long as File_1.js is loaded before File_2.js
If you are namespacing, ie: MYNAMESPACE = {}; and each file extends your namespace through modules (rather than "module pattern" referring to returning interfaces from immediately-invoking functions), then check for the module's existence.
If you ARE writing modules for a namespaced app, and you DO need access to variables from one module to another, then you should be providing an interface for that.
If you are SANDBOXING modules, then you need to provide them all a proxy similar to a service-locator or a "registry", or develop a messaging-system based on a mediator-pattern.
window.sharedSpace = {};
sharedSpace.sharedValue = 'foo bar';
That way you only have one global object instead of several.
Why don't you just pass the element to a function in the module?
var module1 = (function () {
return {
func1: function () {
// get your element
var someElement = ...;
// pass it to the other module
module2.func2(someElement);
}
};
}) ();
var module2 = (function () {
return {
func2: function (someElement) {
// do whatever you want with someElement
}
};
}) ();

How should I wrap up my engine?

I'm creating a game engine, or more like a large library of useful classes and functions, for Javascript. I plan to use it both for some scientific simulations on the server side and on the client side, so the spectrum of functionality will be quite broad, but always it will revolve around a virtual world (a game, for example).
I'm not sure how to wrap it up, though. If I just provide all the classes, it would pollute the global namespace, which is quite bad. Can I just place everything inside one object, that acts as a namespace? Should the framework itself be a class that can be instanced?
If the later option is chosen, how do I handle classes inside classes (constructor functions)?
var Engine = function()
{
this.someVar = 4;
}
Engine.prototype.Scene = function()
{
this.entities = [];
//What if the scene object needs some classes that are in the engine? How does it get it's parent engine object?
}
Engine.prototype.Scene.prototype.render = function()
{
//"this" should now represent an instance of a scene. But how can I get someVar from the engine? How can I traverse up in the hierarchy of classes?
}
I prefer to use what's sometimes called a "revealing module" (... pattern). It looks like:
var Engine = (function($)
{
$ = $ || {};
var someVar = 4;
$.Scene = function()
{
this.entities = [];
}
$.Scene.prototype.render = function()
{
// this function can access someVar just fine because of JavaScript's scoping rules
}
return $;
})(Engine);
This uses what's called an immediately-invoked function expression (hereafter referred to as an IIFE) to form a closure within the Engine object. Due to JavaScript's handling of scope, someVar is accessible to any function defined within the IIFE. The implication, however, is that no function can define it's own someVar if it wants to refer to the someVar you define in the IIFE.
The magic comes from the return statement. You can see that an object is returned, and within this object you must define anything you want to be "public".
The constructors, utility methods, etc. can then be accessed via Engine.Scene, which nicely namespaces your code.
As for the $ argument, this is so that you can pass Engine to the function in each file, add some methods/properties/constructors (or create a new one if it doesn't exist) and then pass the return value to another IIFE for further expansion.
This is the method used in many popular JavaScript frameworks including jQuery, dojo and LimeJS
scene.js:
var Engine = (function ($) {
// this creates a new object if Engine is undefined in the
// invocation below, and keeps the old object otherwise.
// alternatively: if ($ === undefined) { $ = new Object; }
$ = $ || {};
$.foo = "foo";
$.Scene = function () {
// blah blah
}
// Engine holds either a newly created object,
// or the old one if it was already defined
return $;
})(Engine);
sprite.js:
var Engine = (function ($) {
$ = $ || {};
$.Sprite = function () {
// totally works
this.bar = $.foo;
}
return $;
})(Engine);
You can then use them with something like:
<script type="text/javascript" src="bar.js"></script>
<script type="text/javascript" src="foo.js"></script>
<script type="text/javascript">
var mySprite = new Engine.Sprite;
var myScene = new Engine.Scene;
</script>
You can substitute $ with whatever you like, $$ is common, or you can be clever. It's just a placeholder for the global object you're adding on to.
I don't think you need or even should organize your classes like that. Even though the Scene and Engine classes are related, the Scene class doesn't have to be a children of Render. Use a flat class hierarchy instead, that will be easier to maintain and scale.
Finally, you should indeed put all these classes under the same namespace so as not to pollute the global namespace.
// Define the namespace only if it doesn't already exist. That
// way you can split the definition of your classes in various
// files, without having to worry in which order they are loaded.
if (typeof gameEngine === 'undefined') gameEngine = {};
gameEngine.Engine = function()
{
this.someVar = 4;
}
gameEngine.Scene = function()
{
this.entities = [];
}
// Add a new function to define which
// scene the Engine should render:
gameEngine.Engine.prototype.setScene = function(scene)
{
this.scene = scene;
}
gameEngine.Engine.prototype.render = function()
{
// render this.scene
}

Categories