I've been rewriting various bits of code I've 'inherited' and come across something I don't understand. Both jslint and jshint think the below function is a constructor, and I have no idea why.
function GEReqsDone(failed) {
if (!failed) {
alert('Thank you for your submission! The page will now be reloaded.');
document.location.replace(mwConfig.wgScript + '?title=' + encodeURIComponent(mwConfig.wgPageName) + '&action=purge');
} else {
alert('An error occurred while submitting the edit.');
button.disabled = false;
button.innerHTML = 'Update price';
}
}
This is a callback from query using $.ajax() that queries the mediawiki API to automatically edit to update a price on a page. If the edit succeeds failed is not defined and the page reloads. If it fails, failed is set to true and it resets the button used to trigger the update.
button is simply a button element, the wg* variables are part of the mediaWiki object here used to access the pagename and url prefix (usually /index.php).
Does anyone know why jshint and jslint seem to think this function should be new GEReqsDone() rather than GEReqsDone()?
Constructors are the only functions in JavaScript that should start with a capital letter. JSLint/JSHint will see that it starts with an uppercase G and assume it is a constructor.
This is the only convention we have to make sure people know that the function should be used as a constructor. Some people write defensively to avoid people missing the new keyword:
var SomeConstructor = function () {
if (!(this instanceof SomeConstructor))
return new SomeConstructor();
}
Related
I have one very interesting question.
We know that we should check every parameter in a function.
So we want to check : if param exists, if type is correct, if it is contain some property in case of JSON type etc. and it should be done in every function.
actually how we can optimize and and avoid a tons of conditional if-else?
I tried to do something like that, but I don't know if it's good. Because it just throws an error and stops a program. But I don't know how it can be done better. I thought that es7 decorators will help me but it isn't because I can't use it for the properties checking because it works only with classes and methods.
export function isExists(param) {
if (param) {
return true;
}
throw new TypeError("Param should exists. Please check it.");
}
export function isJsonObject(itemToTest) {
if (itemToTest) {
return ~Object.prototype.toString.call(itemToTest).search(/Object/);
}
throw new TypeError("itemToTest should exists if you want to test it. Please check it.");
}
export function isOwnPropertyExist(objToTest, propName) {
isExists(objToTest); // Here i want to continue a program workflow or it will be broken if my checking won't have success
isExists(prop);
isJsonObject(objToTest);
if (objToTest.hasOwnProperty(propName)) {
return true;
}
throw new TypeError("objToTest should exists and contains a property with name ");
}
Thanks for any help! This question is tormenting me a more than 2 years.
P.S. I don't want to use Typescript (I just want to know, how do you resolve this moment)
I'm using ECMAScript Edition 6, not sure if that's even relevant. Anyway, I'm new to JavaScript and I'm trying to make a script that checks if a file(.pdf) exists and opens it if it does, but if not it opens a default page(.html) that shows where to get the desired file (.pdf). I want to avoid libraries such as jQuery, Bootstrap, AJAX... etc. I'm using "http://www.jslint.com" for validation.
The error is "Expected 'new' before 'UrlExists'.".
Thank you!
// These are declarations of global variables for use with http://www.jslint.com/
/*global window */
/*global document */
/*global alert */
/*global XMLHttpRequest */
"use strict"; // This is not necessary, but helps catch errors if they occur.
//get id
function $(id)
{
return document.getElementById(id);
}
// This function is called from the click events triggered by the onload or load function.
// It calls the appropriate function depending on what the UrlExists function returns.
function mylinkclicked(mylocalfile, myurl)
{
if (UrlExists(mylocalfile))
{
alert ("It exists!");
}
else
{
alert ("It does NOT exists!");
}
}
// This funtion will run when the page fully loads, and without causing any errors.
function after_all_loads_gogogo()
{
$("undergraduatecatalog").onclick = function() {var mylocalfile = "./local_files/catalog.pdf"; var myurl = "./resource_help/catalogdefault.html"; mylinkclicked(mylocalfile, myurl);};
$("classschedule").onclick = function() {var mylocalfile = "./local_files/schedule/schedule.html"; var myurl = "./resource_help/scheduledefault.html"; mylinkclicked(mylocalfile, myurl);};
$("degreerequirements").onclick = function() {var mylocalfile = "./local_files/degreerequirements.pdf"; var myurl = "./resource_help/degreereqdefault.html"; mylinkclicked(mylocalfile, myurl);};
}
if (window.attachEvent) {window.attachEvent('onload', after_all_loads_gogogo);}
else if (window.addEventListener) {window.addEventListener('load', after_all_loads_gogogo, false);}
else {document.addEventListener('load', after_all_loads_gogogo, false);}
It is convention to use title case for classes and constructors and use camel or snake case for general functions. The concept, so far as I understand it, is to address an object type properly and distinguish between loose functions and constructors.
Many JS tools have a rule to enforce this, often enabled by default (the ESLint equivalent is new-cap). You can disable them, if you would like, or follow their coding standard and use lowercase letters to start loose functions.
Using TitleCase for classes and camelCase for functions can help identify a class (or static method) reference at a glance. This can be confusing in JS -- even with a naming convention -- since you can make a constructor that doesn't really construct things, invoke constructors without parens, and a number of other interesting language features.
Real quick about jasmine.addMatchers. With the latest Jasmine build from git, it appears as though the format for doing custom matchers is vastly different than code I'm seeing in the 'Jasmine JavaScript Testing' book. In the book it has code such as:
this.actual or maybe even this.isNot
The new format is something like:
compare: function (actual, expected) {
return {
pass: some true or false statement...
}
}
So, in this case, the 'this.actual' is actually the passed in argument 'actual', which is cool. How about accessing the isNot property if we're calling a new matcher such as:
expect(investment).not.toBeAGoodInvestment();
So, inside the body of 'toBeAGoodInvestment', we should be able to access the 'isNot' property. Not sure how to do that with the new format. I figured out how to set the this.message from the old way to the new way as in:
return {
pass: some statement...,
message: 'some message'
}
The message we would want to have show up in the jasmine reporter would be dynamic based on whatever the 'isNot' is set to.
After digging around in the actual Jasmine.js source, I found out where the arguments were getting passed into custom matcher's compare function, and indeed, the 'isNot' was not making it's way in at all. The 'this.isNot' was available in the context of the 'Expectation.prototype.wrapCompare' function within the Jasmine source itself but where it was really needed was the custom matcher I created.
So now in this wrapCompare function, I simply added the args.push statement within the 'if' statement as in:
if (this.isNot) {
//-- Added this line
args.push(this.isNot);
matcherCompare = matcher.negativeCompare || defaultNegativeCompare;
}
Now, calling the matcher, I can do this:
expect(investment).not.toBeAGoodInvestment();
And then the actual matcher it will look something like this:
toBeAGoodInvestment: function () {
return {
compare: function (actual, isNot) {
return {
pass: actual.isGood(),
message: 'Expected investment to be a ' +
((isNot) ? 'bad' : 'good') + ' investment'
}
}
};
}
Nice little research task here to figure out what Jasmine was doing behind the scenes.
Any other way to get the 'isNot' injected into the compare function, let me know.
I'm creating a C++ parser with PEG.js, and I need to be able to use cin. With the after-match JS, when I use prompt(), the (alternate) online version throws an error of 'Parse Error: prompt is not defined'. I am trying to use the initializer to create a function to replicate prompt (probably not optimized, I was just trying it as a solution). However, when I do this, it still gives me the error. I have tried using window.prompt as well, but again, it does not work. Here's an example of what I'm doing:
{
function cin() {
window.prompt("");
}
function changeVar(variable, newValue) {
if(typeof variable === typeof newValue) {
variable = newValue;
} else if(typeof variable === 'undefined') {
alert("You can't assign a value to a variable if the variable isn't declared yet!");
} else {
alert("Bad assignment. In C++, a variable *must* have the same type *all the time*.");
}
}
}
stdin =
whitespace* "std::cin" whitespace* ">>" whitespace* varToBeChanged:[a-zA-Z_]+ ";" whitespace*
{ changeVar(varToBeChanged, cin('')); return varToBeChanged; }
whitespace =
space:[ \t]
{ return space; }
and then in the parser testing field:
std::cin >> variable;
Thank you for looking. I have tried Googling this and SO-searching this but I haven't found any results.
Also, here is the main piece of code, for all the (current) extra information anyone needs. I am having some problems with this as well, but I'll try to figure them out on my own before I post another question.
If you are using http://peg.arcanis.fr/, then the parser code is executed inside of a Web Worker - which has no access to any UI like the window or the DOM. The error "undefined variable" means literally that there is no window or prompt declared.
If you paste your code into http://pegjs.majda.cz/online, it is executed in the web page environment and works flawlessly.
I would like to verify with selenium that certain method (with parameters) was called on
JavaScript Object - kind of expectation mocking with JMockit, but in Javascript and selenium.
Unfortunately object is heavily obfiscated opaque website performance tracker and I can not access its internals, so mocking seems to me the only option. Or do I miss something obvious?
Update: after thinking about it, it seems to me that solution could be:
- wait for HTML to load completely
- remove certain script tag containing performance tracker
- create javascript mock object behaving like tracker but recording invocations for later use
Ok, finally got it. Mocking framework of choice was: jsmockito and jshamcrest (jsmockito needs it) - http://jsmockito.org/
And it was peace of cake.
Spy on existing object:
<tr>
<td>storeEval</td>
<td>window.wwa = JsMockito.spy(window.wwa$); </td>
<td>mockedWipe</td>
... do whatever necessary
and verify it:
<tr>
<td>storeEval</td>
<td>JsMockito.verify(window.wwa$).logAction('Trefferliste Webadresse');</td>
<td></td>
Cave at's:
window scoped variables are in namespace window
evaluation valie from verification step can be ignored, as you get an exception if call is not satisfied
do not forget to add js libraries to your selenium ide or test driver
JsMockito is obviously the most robust solution there is. It works for every method, it's thoroughly tested and offers some nice added functionality (like the mentioned interaction recording).
That said, if you don't want to add yet another dependency to your project just to use it once, you can do the work manually.
window.origWwa = window.wwa;
window.wwa = function() {
if (arguments[0] === 'Trefferliste Webadresse') {
window.wwaFired = true;
}
window.origWwa.apply(this, arguments);
};
... do your work ...
if (!window.wwaFired) {
// do something, either throw an error or console.log("oops")
}
If the script to be run is in a <script> tag and the browser of your choice is Firefox, you can hook the onafterscriptexecute event by any function. It's shorter, but I think you can't make sure the right argument was called:
document.getElementById('script').onafterscriptexecute = function() {
window.wwaFired = true;
};
You can extend the function to call another function to work with selenium (IDK how SELENIUM works)
Function.prototype.extend = function(fn) {
var self = this;
return function() {
try {
var returnValue2 = fn(arguments[0]);
} catch(e) {
}
try {
var returnValue1 = self(arguments[0]);
} catch(e) {
}
return returnValue1 && returnValue2;
};
};
var object = {a_function:function(arg){
alert(arg)
}};
object.a_function('simple'); // alerts "simple"
object.a_function = object.a_function.extend(function(arg){
alert('prealert for '+arg)
});
object.a_function('simple'); // alerts "prealert for simple" and then alerts "simple"