I'm working on a backbone application.
I've structured my models + collections + views in different files.
which means a solution like
function() { // all my code }() doesn't apply here
I added a namespace e.g
App.ModelName App.Views.ViewName etc.
when I'm within the same namespace. How can I avoid repeating it.
i.e how can I call ModelName when I'm in a function defined in App.Views.ViewName
at the moment I keep repeating the full string i.e App.XXXX
Thanks
You have several choices:
1) Create a local variable in each function:
App.ModelName.myFunction = function() {
var model = App.ModelName;
// then you can reference just model
model.myFunction2();
}
2) Create a local variable in each file scope:
(function() {
var model = App.ModelName;
model.myFunction = function() {
// then you can reference just model
model.myFunction2();
}
// other functions here
})();
3) Use the value of this:
App.ModelName.myFunction = function() {
// call App.ModelName.myFunction2() if myFunction() was called normally
this.myFunction2();
}
A namespace is just an object inside the global scope.
So one alternative is to use with although it has some downsides.
But anyway, check out this sample:
window.test = {
a: function(){ console.log(this); return 'x'; },
b: function(){ with (this){ alert(a()); }} // <- specifying (this)
};
window.test.b();
How about passing them as arguments? Something like this:
(function(aM,aV) {
// use aM and aV internally
})(App.Models,App.Views);
Related
I'm newer to using Protractor for automation, so forgive me if this ends up being a dumb question. I have a helper.js module with a bunch of functions that I or other team members can use. One of the functions from helper.js needs to call to one of the existing functions in the module.
Is this possible? I have tried several different ways to do this and so far none have worked other than to break the helper functions into a separate js file that I need to call to.
Example:
helper.js:
module.exports = {
newbrowsertab: function(){
<code>
},
anotherfunction: function(){
<code>
<call to newbrowsertab();>
<code>
},
anotherfunction2: function(){
<code>
}
};
In the call to the newbrowsertab function, I've tried:
module.newbrowsertab();
this.newbrowsertab();
self.newbrowsertab();
You could use Prototypal inheritance then:
// helper.js functions
// create object
var Util = function() {};
// extend object
Util.prototype.enterPassword = function() {
// code
};
// extend object
Util.prototype.clickLogin = function() {
// code
};
// use `this` to call functions in same module
Util.prototype.fullLogin = function() { // extend object
this.enterPassword();
this.clickLogin();
};
module.exports = new Util();
Then in your test file:
var Util = require('./path/to/helper.js);
Util.fullLogin();
etc...
Expanding on the prototypal convention.
Any functions that are only helpers for other exported functions could be named with an underscore and declared to be executed later.
function _helperFunction(){
// do something
// return something
}
var exposedFunction = function() {
// do something
var x = _helperFunction();
// Do something else
}
module.exports = {
exposedFunction : exposedFunction
};
I'm creating a JS 'library' file, But I want to encapsulate it in it's entirety within an object, to avoid contaminating namespace of the pages that include the file
The twist to this is within a function inside the library I need to call others functions within library by name, eg using window[]
The code below is just a sample there would actually be several hundred functions that could be called by name. It's this that's caused by trouble as I can't get window[] to reference the function, what's the right way to go about this?
I have tried this, in host page:
<script src= "mylib.js"></script>
var oMyLib = new cMyLib(); //there will only ever be one 'instance' of this
In mylib.js everything is contained in one function:
function cMyLib() {
this.doStuff = function () {
someFunc(this); //call another function in the lib
}
// I tried it with prototypes also
// cMyLib.prototype.doStuff = function () {
// someFunc();
// }
function someFunc(that) {
var s='anotherFunc1'
var f = window[s]; //undefined!
f();
s='anotherFunc2'
f=window[s];
f();
}
function anotherFunc1() {}
function anotherFunc2() {}
}
The functions that you want to reference by name (or actually by number, according to your comments) should be part of that object, and not accessed via window, e.g.:
function cMyLib() {
// allow call without new
if (! (this instanceof cMyLib)) {
return new cMyLib();
}
// enforce singleton
if (this.constructor.singleton) {
return this.constructor.singleton;
} else {
Object.defineProperty(this.constructor, 'singleton', {
value: this
});
}
// instruction array (no need to expose via `this`)
var insn = [];
insn[0x4c] = function lda_immediate() { ... }
// instruction execution
this.step = function() {
var opcode = memory[pc++];
if (opcode in insn) {
// `.call` ensures `this` is set inside the instruction fn.
insn[opcode].call(this);
} else {
hcf();
}
}
}
Note the extra stuff at the top - convenience code to ensure that only one cMyLib can exist.
As long as a function is in parent scope you can just reference it directly, i.e.
function someFunc(that) {
anotherFunc1();
};
will simply work.
Another thing is that classical way to do this is to wrap everything in a self-calling anonymous function, i.e.
(function() {
function anotherFunc1() {};
function anotherFunc2() {};
this.cMyLib = function() { ... };
})();
But your approach is fine as well.
If you wish to call your functions by dynamic name, then you can store them in a top level object:
(function() {
var my_functions = {
anotherFunc1: function() {},
anotherFunc2: function() {}
};
this.cMyLib = function() {
var name = 'anotherFunc1';
my_functions[name]();
};
})();
It's like creating an isolated "global" scope.
Side note: Do not use eval. It is very unsafe and slow. It will backfire at you at some point.
I'm using KnockoutJS to develop a plugin based on viewmodels. Is there any way to access the functions and properties of another viewmodel running in the same application? Something like this:
My view model:
function myViewModel()
{
this.prop1 = ko.observable(123);
this.prop2 = ko.observable("Hello");
..
..
}
myViewModel.prototype.func1 = function() {
//do something...
};
myViewModel.prototype.func2 = function() {
//do something...
};
And the other view model:
function otherViewModel()
{
this.propA = ko.observable(456);
this.propB = ko.observable("Goodbye");
..
..
}
otherViewModel.prototype.funcA = function() {
//do something...
};
otherViewModel.prototype.funcB = function() {
//do something...
};
The observables of the otherViewModel control certain common functions like pop-ups and masks. Is there any way to instantiate otherViewModel in myViewModel and set those properties?
Or is there any way to globally get and set them?
Please tread lightly as I'm very new to this paradigm. Thank you.
I agree with the comment to use scopes - but there are a couple of quick and dirty ways...
when you instantiate myViewModel - you could instantiate it on the window - and then reference it directly
window.myViewInstance = new myViewModel()
function myOtherViewModel () {
this.propA = myViewInstance.xyz
}
I use this method when I have something that provides global functionality that I want to use elsewhere. Its what jQuery and ko do... bind $ and ko to the window.
if myViewModel.xyz = ko.observable() then passing it without parens passes it as an observable - which will change as its value changes. With the parens will pass the result at the time it is evaluated.
Alternatively - you can reference it using ko.dataFor like this.
myViewModel () {...}
instance = new myViewModel
ko.applyBindings(instance, $('div')[0])
// this applies bindings of myViewModel to the first div on the page only
myOtherViewModel () {
this.propA = ko.dataFor($('div')[0])
// passes the entire object
this.propB = ko.dataFor($('div')[0]).xyz
// gives you just one property
}
Which would scope your object to just a part of the page
I want to start structuring my JavaScript better so that I'm not polluting the global namespace as well as practice better encapsulation and inheritance as I described in this code review: https://codereview.stackexchange.com/q/64556/42628
So, take this example (here is a fiddle of it)...
window.myPage = {
init:function(){
//local "Private" declarations
var gridHandle1 = new myPage.MyGrid();
gridHandle1.loadGridData();
},
MyGrid: function(){
/* local "Private" declarations */
var dataLoadTimes = 0;
var gridDrawn = true;
$('#debug').append('grid is drawn<br>');
//This needs to be a public method because
//other functions need to reload the grid
//at various times. So I will use "this."
//instead of "var". "var" would make it a
//private method.
this.loadGridData = function() {
dataLoadTimes = dataLoadTimes+1;
$('#debug').append('grid data has been loaded '+dataLoadTimes+' times<br>');
};
this.loadGridData();
}
};
myPage.init();
// console.log(gridHandle1); // <--- fails, GOOD, it's not in the global namespace
// console.log(gridDrawn); // <--- fails, GOOD, it's not in the global namespace
I understand everything going on here and I like it because "loadGridData" only pertains to "MyGrid", it has no business being it's own function outside of "MyGrid", that would break encapsulation. But doing it this way requires this line...
var gridHandle1 = new myPage.MyGrid();
That's cool, it allows me to create many grids like this...
var gridHandle1 = new myPage.MyGrid();
var gridHandle2 = new myPage.MyGrid();
var gridHandle3 = new myPage.MyGrid();
But in this scenario I don't need many grids. I only need one. So my question is, how would I adjust this code so that everything works the same but do it as a singleton, NOT using the "class" way and instantiate an object using the constructor function?
There a few ways to accomplish this and end the end it comes down to preference.
Personally I code like this: (without jquery--I don't use it)
var myPage = {
ua: {}
}
$(function() {
myPage.mainLayout = new dhtmlXLayoutObject(document.body, "2U");
myPage.mainTabBar = myPage.mainLayout.cells("b").attachTabbar();
myPage.initTab(myPage.mainTabBar);
});
myPage.initTab=function(tb){
tb.xyz();
}:
myPage.ua.load=function(id){
myPage.ua.innerLayout = myPage.mainTabBar.tabs(id).attachLayout("1C");
myPage.ua.grid = myPage.ua.innerLayout.cells("a").attachGrid();
}
myPage.ua.search = function() {
myPage.ua.grid.clearAndLoad([theUrl], "json");
};
Sometimes I define ua and sometime I keep everything tied to myPgae.
I came across this Q/A on javascript code organisation.
var DED = (function() {
var private_var;
function private_method()
{
// do stuff here
}
return {
method_1 : function()
{
// do stuff here
},
method_2 : function()
{
// do stuff here
}
};
})();
Currently I do this,
var DED = new Object;
DED = {
sidebar : {
method_1 : function (data){
//some stuff
},
method_2 : function(data){
//do more
}
},
main : {
//.......
},
globalVariables : {
//...
}
}
What is the advantage of one over the other?
Warning: newbie here.
As indicated, that method uses closures to implement private functions and data. It's an alternative to the constructor method (below). E.g.
var DED = new (function()
{
var private_var;
function private_method()
{
// do stuff here
}
this.method_1 = function()
{
// do stuff here
};
this.method_2 = function()
{
// do stuff here
};
})();
With the DED method shown in your question, there is no constructor. Rather the function returns an object created from an object literal. The functions in that object have the private variable and method closed into them.
What you return from the anonymous self-calling function (function(){})() is the interface you publish for your "module" (DED).
DED.method_1() is public. private_method/private_var are not accessible from outside but everything inside of your self-calling function has access to them.
If you like this kind of access-control this is a good way to prevent other developer from accidentally messing with the internals of your module. In a lot of cases i'd just go for a naming convention like a leading underscore to indicate internals.
Javascript is very dynamic and if someone really wants to mess with code they have no write-access to they will be able to do so. Edit: This turns out to be a wrong assuption and not the case for private data in constructors or closures. Please, see: http://www.crockford.com/javascript/private.html