I'm working on some React stuff, and I found this relevant codepen to my work. Looking through their source code, they used some syntax I'm unfamiliar with.
Specifically, this line in the _handleClick function confused me:
const wasOutside = !(event.target.contains === this.root);
In the context of the code, it's checking to see whether or not the user has clicked outside of a context menu that was generated with a right click. I under stand what it's doing, but I'm unclear on how it's doing it. I've tried to track down documentation on event.target.contains, but I've had no luck.
Here's what I think is happening. Event.target gives me a node location. This.root is also a node location on the dom. I think that event.target.contains is the same as node.contains, but per my reading of the documentation, I think that node.contains could only return a boolean true or false, and it would take an argument of some sort? So far as I can tell, there's no way for wasOutside to have any value except for true, and this code is unnecessary. Is this accurate? Am I missing something, or interpreting something incorrectly?
Related
I'm learning Javascript and I wrote the following code:
if (mystring.len > 0) {
// do stuff
}
I accidentally used .len instead of .length. To my surprise, no error was raised. mystring.len returned undefined and this made the comparison fail but the code kept right on running. I would prefer an actual error to be raised so I can fix the code. Adding "use strict" didn't help, nor did jslint.
I know there are ways to actively check whether or not a property exists, but that's not what I'm looking for. I want Javascript to tell me when I've made a typo in a property name.
Is there a way to cause Javascript to give an error in this case?
Nope - that is how JavaScript works and it's incredibly useful. Who is to say that checking len is something that needs fixing? Consider:
if(mystring.len === undefined) {
mystring.len = "Test";
}
The best you can do is to simply check that the thing is defined before using it:
if(mystring.len !== undefined) {
}
I appreciate the strangeness, and how it doesn't feel robust (having originally come from a C# background) but there isn't a lot you can do unfortunately. The fact that JavaScript is case sensitive makes this even more frustrating. You will learn to live with it though!
If you really really wanted to run some static analysis then you could considering creating a transpiler (e.g. Babel) extension to run this sort of analysis - but it would get really difficult if you ever expected something to be undefined which I find is common place.
edit
Here's a real example that I'd use where undefined is useful. I'm working with a library that needs to move stuff from one location to another. It can't do that unless the original location has been specified, so I might write something like the following, initializing values if I don't have them for some reason:
function update(node) {
if(node.x === undefined) { node.x = 0; }
node.y = node.y || 0; // This is the shorthand way I'd actually write it
// Do some other stuff
};
"use strict" (in my experience) is used so that variables that aren't explicitly declared/instantiated that are then referenced will throw errors (else, JS would just make a new var on the fly). So that wouldn't help here.
This sounds like an error that would typically be picked up by a compiler in other languages, but since JS is interpreted, you won't have that kind of explicit error checking unless you're in a beefy IDE. Are you using a text editor or something to write JS?
Thats not the way JavaScript considers your above code. Every variable in JS is an object. So, when you do mystring.len, its actually trying to access the len property of mystring obj and when it doesn't find that property, it will return undefined - which is how it should be. Thats why you will not be able to find any error using JSLint.
Just to give you an example -
var myObj = {name: 'Hello', id: 1};
console.log(myObj.name); // Returns 'Hello'
console.log(myObj.text); // 'undefined'
In order to prevent such code from giving you any errors, you can easily use the hasOwnProperty() method like follows-
if(myObj.hasOwnProperty('text')) doSomething();
Since myObj doesn't have any property text, the doSomething() function will never be called.
This is the behaviour of JavaScript as mentioned by many/all answers. However there is an option to prevent new properties you might want to try:
Object.seal https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/seal
The simple answer is JavaScript is not ment to be typesafe...You shouldn't check it, but if you still want to check you can do it by:
if ('len' in mystring){
}
You should look into Typescript if you ask this question...
I am trying to make sense of the onchange event of bootstrap-multiselect. In particular, I am trying to understand the function syntax and parameters.
$('#example-onChange').multiselect({
onChange: function(option, checked, select) {
alert('Changed option ' + $(option).val() + '.');
}
});
How to know what does the three parameters in the function mean? Where will I get these three parameters? I also tried looking at the code https://github.com/davidstutz/bootstrap-multiselect/blob/master/dist/js/bootstrap-multiselect.js#L263 but couldn't make much sense of it.
I know using alerts that in this function option refers to the selected option, checked shows whether the option was checked or unchecked. I keep getting undefined when doing console.log(select) inside the function, so not sure what does that mean.
Question: How to understand function parameters and syntax like these? This is just an example but knowing a generic procedure will help me decode other similar functions in future.
In short, it seems the library doesn't actually provide the select option.
In general, in situations where the documentation isn't very precise, the technique I often apply is to console.log the arguments, then inspecting what each of them look like.
In this situation, when doing:
$('#example-onChange').multiselect({
onChange: function(option, checked, select) {
console.log(arguments);
}
});
... I got the following output:
... from this you can see two arguments are provided. The first is the jQuery object of the option that was clicked. The second (you can assume) is a boolean as to whether the option is selected or not.
You can also see no select (3rd argument) was provided.
Another approach you can take is to search the source code, like you did; but I'd recommend finding where the function was called, rather than where it was defined. By searching for onChange in the source code, you can see onChange is called at least 3 times.
this.options.onChange($option, checked);
this.options.onChange($option, true);
this.options.onChange($option, false);
... none of which provide a 3rd argument. I say at least 3 times here, because it can be hard sometimes (particularly in large libraries) to find all call sites, since developers can mask them in all sorts of weird and wonderful ways
Other techniques you can use:
Setting a breakpoint within your handler function (either using the "breakpoint" functionality of your dev. tools, or via the debugger statement), triggering the handler, then following the callstack (again, using developer tools) to examine the call site, and to see what variables are provided.
Opening an issue on the respective GitHub project. You'll find plenty of library owners are more than happy to help.
Unfortunatly, all Javascript libraries must have a very robust documentation.
Moreover, Javascript is a dynamically typed language, so there is no informations about the required types for the formal parameters. It make libraries more difficult to understand without good documentation.
In order to quickly understanding, with experience, there is some thinking mecanisms which can be used. For example, the parameters of an event's delegate provide informations on the elements on which it occurs. It's like these parameters are values returned to you.
In your example, there is chance that option, checked and select are concerned by the option's element in the multiselect defined in #example-onChange which was changed (onChange).
Example 1 :
onClose:function(success)
{
//TODO
}
In this case, "success" should mean : this parameter is true if closing on my element has succeeded else "success" is false.
Example 2 :
afterSave:function(success, filename)
{
}
In this case, "filename" should be the filename of the saved element after perform save's action.
I doing my best for writting correct english, I hope it's understandable.
I have a large, messy JS codebase. Sometimes, when the app is being used, a variable is set to NaN. Because x = 2 + NaN results in x being set to NaN, the NaN it spreads virally. At some point, after it has spread pretty far, the user notices that there are NaNs all over the place and shit generally doesn't work anymore. From this state, it is very difficult for me to backtrack and identify the source of the NaN (and there could very well be multiple sources).
The NaN bug is also not easily reproducible. Despite hundreds of people observing it and reporting it to me, nobody can tell me a set of steps that lead to the appearance of NaNs. Maybe it is a rare race condition or something. But it's definitely rare and of uncertain origins.
How can I fix this bug? Any ideas?
Two stupid ideas I've thought of, which may not be feasible:
Write some kind of pre-processor that inserts isNaN checks before every time any variable is used and logs the first occurrence of NaN. I don't think this has been done before and I don't know how hard it would be. Any advice would be appreciated.
Run my code in a JS engine that has the ability to set a breakpoint any time any variable is set to NaN. I don't think anything does this out of the box, but how hard would it be to add it to Firefox or Chrome?
I feel like I must not be the first person to have this type of problem, but I can't find anyone else talking about it.
There is probably no solution for your problem aka: break, whenever any variable is set to NaN. Instead, you could try to observe your variables like this:
It was earlier stated, that the Chrome debugger offers conditional breakpoints. But, it also supports to watch expressions. In the Watch-Expressions menu you can set a condition to break, whenever the variable is set to a specific value.
Object.observe is a method that observes changes on a object. You are able to listen to all changes on the object, and call debug when any variable is set to NaN. For example, you could observe all change on the window object. Whenever any variable on the window object is set to NaN, you call debug. Please note, that Object.observe is quite cutting edge and not supported by all browsers (check out the polyfill in this case).
Take this opportunity to write a test case for every function in your code. Perform random testing and find the line of code that can create NaN values.
Another problem of yours is probably how to reproduce this error. Reloading your webpage over and over doesn't make too much sense. You could check out a so called headless browser: It starts an instance of a browser without displaying it. It can be leveraged to perform automatic tests on the website, click some buttons, do some stuff. Maybe you can script it in such a way that it finally reproduces your error. This has the advantage that you don't have to reload your webpage hundreds of times. There are several implementations for headless browsers. PhantomJS is really nice, in my opinion. You can also start a Chrome Debug Console with it (you need some plugin: remote debugger).
Furthermore, please notice that NaN is never equal to NaN. It would be a pity if you finally are able to reproduce the error, but your breakpoints don't work.
If you're doing a good job keeping things off of the global namespace and nesting things in objects, this might be of help. And I will preface this by saying this is by no means a fully complete solution, but at the very least, this should help you on your search.
function deepNaNWatch(objectToWatch) {
'use strict';
// Setting this to true will check object literals for NaN
// For example: obj.example = { myVar : NaN };
// This will, however, cost even more performance
var configCheckObjectLiterals = true;
var observeAllChildren = function observeAllChildren(parentObject) {
for (var key in parentObject) {
if (parentObject.hasOwnProperty(key)) {
var childObject = parentObject[key];
examineObject(childObject);
}
}
};
var examineObject = function examineObject(obj) {
var objectType = typeof obj;
if (objectType === 'object' || objectType === 'function') {
Object.observe(obj, recursiveWatcher);
if (configCheckObjectLiterals) {
observeAllChildren(obj);
}
} if (objectType === 'number' && isNaN(obj)) {
console.log('A wild NaN appears!');
}
};
var recursiveWatcher = function recursiveWatcher(changes) {
var changeInfo = changes[0];
var changedObject = changeInfo.object[changeInfo.name];
examineObject(changedObject);
};
Object.observe(objectToWatch, recursiveWatcher);
}
Call deepNaNWatch(parentObject) for every top level object/function you're using to nest things under as soon as they are created. Any time an object or function is created within a watched object/function, it itself will become watched as well. Any time a number is created or changed under a watched object--remember that typeof NaN == 'number'--it will check if it's NaN, and if so will run the code at console.log('A wild NaN appears!');. Be sure to change that to whatever sort of debugging output you feel will help.
This function would be more helpful if someone could find a way to force it onto the global object, but every attempt I made to do so simply told me I should sit in time out and think about what I've done.
Oh, and if it's not obvious from the above, on a large scale project, this function is bound to make pesky features like "speed" and "efficiency" a thing of the past.
Are your code communicate with your server side, or it is only client side?
You mention that it is rare problem, therfore it may happend only in some browsers (or browsers version) or on any situation which may be hard to reproduce. If we assume that any appearance of nan is problem, and that when it happend user notice bug ("there are NaNs all over the place"), then instead display popup with error, error should contain first occurence of nan (then users may raport it "Despite hundreds of people observing it and reporting it to me"). Or not show it, but send it to server. To do that write simple function which take as agument only one variable and check if variable is NaN,. Put it in your code in sensitive places (sensitive variables). And this raports maybe solate problematic code. I know that this is very dirty, but it can help.
One of your math functions is failing. I have used Number(variable) to correct this problem before. Here is an example:
test3 = Number(test2+test1) even if test1 and test2 appear to be numbers
Yeah man race conditions can be a pain, sounds like what it may be.
Debugging to the source is definitely going to be the way to go with this.
My suggestion would be to setup some functional testing with a focus on where these have been reproduced, set some test conditions with varied timeouts or such and just rerun it until it catches it. Set up some logging process to see that backtrace if possible.
What does your stack look like? I can't give too much analysis without looking at your code but since its javascript you should be able to make use of the browser's dev tools I assume?
If you know locations where the NaNs propagate to, you could try to use program slicing to narrow down the other program statements that influence that value (through control and data dependences). These tools are usually non-trivial to set up, however, so I would try the Object.observe-style answers others are giving first.
You might try WALA from IBM. It's written in Java, but has a Javascript frontend. You can find information on slicer on the wiki.
Basically, if the tool is working you will give it a program point (statement) and it will give you a set of statements that the starting point is (transitively) control- and/or data-dependent on. If you know multiple "infected" points and suspect a single source, you could use the intersection of their slices to narrow down the list (the slice of a program point can often be a very large set of statements).
(was too long for a comment)
While testing you could overwrite ALL Math functions to check if an NaN is being produced.
This will not catch
a = 'string' + 1;
but will catch things like
a = Math.cos('string');
a = Math.cos(Infinity);
a = Math.sqrt(-1);
a = Math.max(NaN, 1);
...
Example:
for(var n Object.getOwnPropertyNames(Math)){
if (typeof Math[n] === 'function') Math[n] = wrap(Math[n]);
}
function wrap(fn){
return function(){
var res = fn.apply(this, arguments);
if (isNaN(res)) throw new Error('NaN found!')/*or debugger*/;
return res;
};
}
I didn't tested, maybe an explicit list of the "wrap"ed methods is better.
BTW, you should not put this into production code.
I'm updating an existing website running on Expression Engine. So far, I've stayed away from any code I didn't write or couldn't understand. I recently must have altered some bit of code someplace (helpful, I know) and now a block of JS I didn't write is causing an error that seems to bypass the document.ready() event. The window.load() event however is still taking place.
In the Chrome DevTools Console, the error "Uncought TypeError: Cannot call method 'replace' of UNDEFINED" points to the definition of a function "fixedEncodeURIComponent" pasted below.
$("#MessageContainer.Counted").counter({
type: 'char',
goal: 250,
count: 'down'
}).change(function(){
var TEMP = fixedEncodeURIComponent($(this).val());
$("#Message").val(TEMP);
});
var TEMP = fixedEncodeURIComponent($("#MessageContainer.Test").val());
$("#Message").val(TEMP);
function fixedEncodeURIComponent (str) {
str=str.replace(/"/g, '');
return encodeURIComponent(str).replace(/[!'()*]/g, escape);
}
As I interpret the error, this function is being passed a variable that is not a string. I added an alert(str) to the function definition and the result was UNDEFINED as I expected. The first of several unknowns for me is which call to the function 'fixedEncodeURIComponent' is being passed a bad variable. I assume that it's the first call, but that's just a guess. It so happens that this first call contains a syntax I have never encountered before. I don't know how to interpret what happens when $(this) is passed as a function argument.
Any insights would be greatly appreciated. Also, if there's more information you need please let me know. The client's site is password protected but I can include any code you request.
Thank you.
I'm taking a guess that the }); on line 3 is exiting a document.ready context. If that's the case then your second call to fixedEncodeURIComponent may be getting called before the DOM is even loaded.
Start by wrapping
var TEMP = fixedEncodeURIComponent($("#MessageContainer.Test").val());
$("#Message").val(TEMP);
in a
$(function() {
// code
});
block. If that doesn't work, check that #MessageContainer.Test actually matches an element. Since this is code you inherited, the class name "Test" clues me in that the block in question might be a remnant of someone trying to debug an issue and maybe it should have been removed.
I suspect $("#MessageContainer.Test") since it looks like its supposed to be an ID selector instead of what it actually is when jQUery parses it(which is an ID selector combined with a class selector). $("MessageContainer\\.Test") allows you to select an element with ID MessageContainer.Test
Apologies for the vagueness of the title, I can't think of a succint way of summarising this question. I'm new to Javascript and JQuery and needed to respond to a checkbox being toggled, based on its value. Searching the site revealed lots of answers, mostly in the form:
$("input[type='checkbox']").click(function() {
if( $(this).is(':checked') ) {
//code here
}
})
In a flash of dynamic typing inspiration however, I tried typing this into my Javascript console:
$("input[type='checkbox']").click(function() {
if( this.checked ) {
//code here
}
})
...and to my surprise it worked! What's going on here behind the scenes? Is there a method defined called 'checked', or some kind of default property, or even a Ruby-style 'method missing' concept? Is this enabled by JQuery or is it intrinsic to Javascript?
It struck me as pretty awesome and I'd like to understand it better.
This basically boils down to the difference between this and $(this). (Read more here)
this is the DOM object for the current object where as $(this) is the jQuery wrapped version. This means you can do this.checked and is the same as calling normal Javascript.
What this does mean though is that, like #Val said you may run into cross browser issues as you are not relying on jQuery to solve these issues for you.
The reason it works is when the handler is called, its does something to the effect of:
callbackfn.call(<reference to event obj>, .. params .. )
If you go take a look at the JS reference, you'll see that the first parameter passed to .call is the context you want the function to run within. So in this case, since the object passed in is the clicked item, it will be the context.
I disagree with the other replies that this will cause you any trouble in xss browser compatibility, this is how you're supposed to do it and many many jQuery libraries rely on this.
See this stackoverflow article
$(this)[0] == this