Just starting out with mocha and cannot for the life of me figure out why it thinks Helper is undefined at the indicated line/columns below:
test.js
var assert = require('assert'),
helper = require('../src/js/helper.js');
describe('helper', function() {
describe('#parseValue', function() {
it('should return number of minutes for a properly formatted string', function() {
assert.equal(1501, (new Helper()).parseValue('1d 1h 1m', 'when'));
^^^^^^^^^^^^
});
});
});
helper.js
(function(exports) {
'use strict';
function Helper(opts) {
this.opts = opts || {};
/**
* Parse a value based on its type and return a sortable version of the original value
*
* #param {string} val input value
* #param {string} type type of input value
* #returns {mixed} sortable value corresponding to the input value
*/
this.parseValue = function(val, type) {
switch (type) {
case 'when':
var d = val.match(/\d+(?=d)/),
h = val.match(/\d+(?=h)/),
m = val.match(/\d+(?=m)/);
if (m)
m = parseInt(m, 10);
if (h)
m += parseInt(h, 10) * 60;
if (d)
m += parseInt(d, 10) * 1440;
val = m;
break;
default:
break;
}
return val;
};
}
exports.helper = Helper;
})(this);
I wrote a quick test in the browser without mocha to ensure my helper.js functions were accessible and it worked fine, so I really am at a loss. I am running this directly on my server by calling mocha from the command line in my directory.
You never define Helper in test.js—only helper on this line:
var helper = require('../src/js/helper.js');
Use the lower case helper that you defined.
By the way, you might want to change your exports line in helper.js from this:
exports.helper = Helper;
To this:
exports.Helper = Helper;
Then use helper in test.js like so:
assert.equal(1501, (new helper.Helper()).parseValue('1d 1h 1m', 'when'));
Or just do something like this:
var Helper = require('../src/js/helper.js').Helper;
Related
Let's say I have 3 simple files:
app.js
const A = require('./a');
const B = require('./b');
let first = new A("hello");
let second = new B(first);
a.js
/**
* #constructor
* #param {*} val Value
*/
function a(val) {
this.val = val;
}
module.exports = a;
b.js
/**
* #constructor
* #param {a} a - a instance
*/
function b(a) {
this.a = a;
console.log(this.a.val); // no hint / autocomplete suggestions
}
module.exports = b;
Is it possible to get Intellisense to show fields/methods of class "a" in file "b.js" without importing/requiring it when it's passed as argument?
Is there a way to ignore some documented symbols conditionally?
I'd like to do something like this (pseudo-code):
/**
* #ignore if dev
*/
var a = 42;
/**
* #ignore if prod
*/
var b = 24;
In this example I would like to have my JSDoc generator to only document var a if I configured my generator to dev and vice versa for var b.
Is this possible?
You can implement your own jsdoc plugin to test an ignore condition and set its value in doclet.ignore property. Setting it to true will prevent the doclet being processed - not adding it to the final documentation.
exports.defineTags = function(dictionary) {
var env = require('jsdoc/env');
/*
* Usage: #customIgnore prod, test
*/
dictionary.defineTag('customIgnore', {
mustHaveValue: true,
onTagged: function(doclet, tag) {
var i;
// "envParams" is a property of your jsdoc.json
var environments = env.conf.envParams;
// Will hold "prod, test"
var tagValue = tag.value;
var conditionValues = tag.value.split(",");
for (i = 0; i < conditionValues.length && !doclet.ignore; i++) {
if (environments.indexOf(conditionValues[i].trim()) !== -1) {
doclet.ignore = true;
}
}
}
});
};
How does one implement 'protected variables' in javascript?
var DIM = {
makeOneDim: function(x) {
var magic = Math.random();
return {
dist: function() {
return x * magic;
}
};
},
makeTwoDim: function(x,y) {
var o = DIM.makeOneDim(x);
o.dist = function() {
magic *= Math.random();
return Math.sqrt(x*x+y*y) * magic;
// !! cant access 'private' variable magic !!
}
return o;
}
};
var o = DIM.makeOneDim(123);
var oo = DIM.makeTwoDim(1,2);
console.log(o.dist() + oo.dist());
I know in this example it would be possible to make a 'public getter', but i would still want to mutate the magic variable from within makeTwoDim's scope and hide it from its instances.
It would also be nice if I could somehow prevent recreating the dist functions on each creation of an instance.
Does this suit your needs? It uses a revealing module pattern to make magic private and return the functions. As such there is no need to call makeOneDim from makeTwoDim.
var DIM = (function () {
var magic = Math.random();
function makeOneDim(x) {
return {
dist: function() {
return x * magic;
}
};
}
function makeTwoDim(x, y) {
return {
dist: function() {
magic *= Math.random();
return Math.sqrt(x * x + y * y) * magic;
}
}
}
return {
makeOneDim: makeOneDim,
makeTwoDim: makeTwoDim
}
});
var o = DIM().makeOneDim(123);
var oo = DIM().makeTwoDim(1,2);
DEMO
There are a lot of ways you could engineer this, but the simplest would be to just keep the functions together:
var DIM = {
makeOneDim: function(x) {
var magic = Math.random();
var dist = function() {
return x * magic;
};
var dist2 = function(y, y) {
magic *= Math.random();
return Math.sqrt(x*x+y*y) * magic;
};
return {
dist : dist,
dist2 : dist2,
};
}
};
(and, did you really mean to change the value of magic with each call?)
You should be able to determine the value of magic within makeTwoDim by dividing o.dist() by x
var o = DIM.makeOneDim(x);
var magic = o.dist() / x;
console.log(magic)
You need to make environment with scope function.
The jQuery way :
var myClass;
(function () {
var a = 0; // private var
function protect_function() {
//...
}
window.myClass = {
public_function: function () { }
};
})();
I know I'm likely to collect rotten tomatoes, but I'd like to say that I disagree with the use of "protected" or "private" variables in the scope of JavaScript OOP. There are no builtin safeguards in JavaScript, developpers are doomed to be better than the others, that's it :-D Don't try to mimic Java, just take it as an opportunity to improve your programming skills. Thus, this code looks perfect to me:
AClass = function () {
// `rdm` should never change
this.rdm = Math.random();
};
I am aware that similar questions have been asked before, but methodology changes quickly so I'm seeking to understand current best practices. (In fact, as recently as 2 days ago, Chad Killingsworth added a comment to an accepted answer from three years ago that #expose annotation is now deprecated.)
I'm using the module pattern. Working JSFIDDLE of the below code:
/** #const */
var MATHCALCS = (function () {
'use strict';
var MY = {};
/**
* #constructor
* #param {!Object} obj
* #expose
*/
MY.ModuleStruct = function (obj) {
/** #expose */
this.color = (obj.color !== undefined) ? obj.color : null;
/** #expose */
this.size = (obj.size !== undefined) ? obj.size : null;
};
/**
* #expose
*/
MY.ModuleStruct.prototype.clone = function () {
return new MY.ModuleStruct({
"color": this.color,
"size": this.size
});
};
MY.moduleProperty = 1;
/**
* #type {function(!Array<number>)}
* #expose
*/
MY.moduleMethod = function (a) {
var i, x = 0;
for (i = 0; i < a.length; i += 1) {
x = x + a[i];
}
return x;
};
return MY;
}());
window["MATHCALCS"] = MATHCALCS;*
Currently, using #expose annotation, above can be minified with Closure in advance mode and the following calls work (minified example):
// call a public method
alert(MATHCALCS.moduleMethod([1, 2, 3]));
// allocate a new structure
var ms = new MATHCALCS.ModuleStruct({
"color": "red",
"size": "small"
});
alert(ms.color + '\t' + ms.size);
// clone a second instance
var ms2 = ms.clone();
alert(ms2.color + '\t' + ms2.size);
alert(ms !== ms2); // cloned objs are not equal
// and directly update the properties of the object
ms2.color = "white";
ms2.size = "large";
alert(ms2.color + '\t' + ms2.size);
If possible, without changing away from the module pattern, I would like to update code (approx 10,000 lines) to use #export annotation. However, when I replace #expose with #export Closure raises this error:
ERROR - #export only applies to symbols/properties defined in the global scope.
Q: Is it possible, and if so, how should the above code be annotated to work with ADVANCED_OPTIMIZATIONS?
I am aware that I can possibly use this type of notation:
MY["ModuleStruct"] = MY.ModuleStruct;
MY["ModuleStruct"]["prototype"]["clone"] = MY.ModuleStruct.prototype.clone;
but exporting object properties this way will become tedious. Further JSLint complains about weird assignments so I would rather use JSDocs annotation.
Until the issue raised by #ChadKillingsworth is resolved, here's a solution which will enable you to use #export with only minor modifications to your code:
/** #const */
var MATHCALCS = {};
goog.scope(function () {
'use strict';
var MY = MATHCALCS;
/**
* #constructor
* #param {!Object} obj
* #export
*/
MY.ModuleStruct = function (obj) {
this.color = (obj.color !== undefined) ? obj.color : null;
this.size = (obj.size !== undefined) ? obj.size : null;
};
/**
* #export
*/
MY.ModuleStruct.prototype.clone = function () {
return new MY.ModuleStruct({
"color": this.color,
"size": this.size
});
};
MY.moduleProperty = 1;
/**
* #type {function(!Array<number>)}
* #export
*/
MY.moduleMethod = function (a) {
var i, x = 0;
for (i = 0; i < a.length; i += 1) {
x = x + a[i];
}
return x;
};
});
The changes are:
Change the #expose tags to #export.
Create an empty MATHCALCS object outside the module wrapper function, and make the MY alias point to it.
Instead of executing the module wrapper function immediately (IIFE), pass it to goog.scope(). This enables aliasing within scope functions, allowing the compiler to work out that the exported symbols are being defined on the global MATHCALCS object. This prevents the compiler from raising the error ("#export only applies to symbols/properties defined in the global scope").
Remove the following items, which are not needed:
The #export tags on this.color and this.size
return MY;
window["MATHCALCS"] = MATHCALCS;
When compiled with this command:
java -jar compiler.jar \
--js closure/goog/base.js \
--js mathcalcs.js \
--js_output_file mathcalcs.min.js \
--compilation_level ADVANCED_OPTIMIZATIONS \
--generate_exports \
--formatting PRETTY_PRINT \
--output_wrapper '(function() {%output%}).call(window);'
you'll get:
(function() {var f = this;
function g(a, d) {
var b = a.split("."), c = f;
b[0] in c || !c.execScript || c.execScript("var " + b[0]);
for (var e;b.length && (e = b.shift());) {
b.length || void 0 === d ? c[e] ? c = c[e] : c = c[e] = {} : c[e] = d;
}
}
;function h(a) {
this.color = void 0 !== a.color ? a.color : null;
this.size = void 0 !== a.size ? a.size : null;
}
g("MATHCALCS.ModuleStruct", h);
h.prototype.clone = function() {
return new h({color:this.color, size:this.size});
};
h.prototype.clone = h.prototype.clone;
g("MATHCALCS.moduleMethod", function(a) {
var d, b = 0;
for (d = 0;d < a.length;d += 1) {
b += a[d];
}
return b;
});
}).call(window);
The g() function is the compiled version of goog.exportSymbol() – see the #export docs for more details.
Note: if you want to run the code uncompiled, you'll need to load the Closure Library, or define goog.scope() yourself:
var goog = {};
goog.scope = function(fn) {
fn();
};
Here's a fork of your JSFiddle with all these changes.
And I am sorry to bother with this noob-stuff, but currently new to all this. But learning slowly.
In the first lines of code im getting a return (in this code i get 20*2=40. in the next phase I want to multiplie the return (40) with 20. = 800. so in the outcome it will show 40 And 800. But i only get it to be in the outbox [function], it says. and a msg; "it looks like you didnt print out a value for newNumber".
What do I do wrong? Thanks for all help!
var timesTwo = function (number) {
return number * 2;
};
timesTwo(20);
var newNumber = function (tal) {
(timesTwo * tal);
console.log(newNumber);
};
newNumber(20);
What you need to do is assign the result to a variable, and in the second function return the result:
var timesTwo = function(number) {
return number * 2;
};
var twoTimesResult = timesTwo(20);
var newNumber = function (tal) {
return twoTimesResult * tal;
};
var result2 = newNumber(20);
console.log(result2);
If you wanted to be fancy you could also do the following:
function multiplier(num, multiplier) {
var by = num * multiplier;
return function (number) {
return number * by;
};
}
var multiplyResult = multiplier(20, 2);
console.log(multiplyResult(20));
I'm answering this question too because I think these types of things are fun.
Another approach you could take is the OOP approach.
From your example you have a common multiplier of 20 and a beginning constant of 2.
I would personally attack this problem like so to avoid multiple variables:
// Create a calc object
var Calc = (function () {
// Constructor
Calc = function () {
// Initial constant
this.current_val = 2;
}
// Prototype methods
Calc.prototype = {
// inc() method
inc: function () {
return this.current_val * 20;
}
}
// Return object
return Calc;
})();
// Object Instance
var obj = new Calc();
// Initial call to inc() -> 40
obj.current_val = obj.inc();
// Log
console.log(obj.current_val);
// Second call to inc() -> 800
obj.current_val = obj.inc();
// Log
console.log(obj.current_val);
// Third call to inc() -> 16000
obj.current_val = obj.inc();
// Log
console.log(obj.current_val);
I made a jsfiddle so you can see the output.