problems with list scope javascript - javascript

I trying to make a function that tries to access the first item in a list to make a konami code website. The list is defined and then the function is defined to edit the list. This is code
<html><body>
<script>
var keys = [38,38,40,40,37,39,37,39,66,65];
function keyhandler (e) {
e = e || event;
console.log(e.keyCode);
var key = keys[0];
if (key == e.keyCode) {
console.log("correct key");
if (keys.length == 1){
console.log("konami");
} else {
var keys = keys[1,keys.length];
}
}
else {
var keys = [38,38,40,40,37,39,37,39,66,65];
}
}
document.onkeydown = keyhandler;
</script>
</body></html>
when I trigger the function by a key-press I get this error :
Uncaught TypeError: Cannot read property '0' of undefined the error is caused by the var key = keys[0] line

You're initializing another variable named keys inside of your function (var keys = keys[1, keys.length]). This shadows the outer variable. Remove the var keyword to access the correct variable.
Also, I believe you want to remove the first element from the list. To do so, use shift.
keys.shift();
This will modify the array directly so you don't need to assign the result to anything.

var keys = keys[1,keys.length];
You've created a new (locally scoped) keys variable inside your function and it is masking the one containing the array you are trying to read. Remember: var statements are hoisted.
Use different names for those two variables (or if they are supposed to be the same variable, remove the var statement from the inner one).
NB: In JavaScript, [1,keys.length] is just a comma operator it isn't a slice.

As Quentin said, hoisting is happening in your function.
Other posters here also said it, you are defining a new local variable in your function.
Let me just show your function with hoisting happening when Javascript interprets your code:
var keys = [38,38,40,40,37,39,37,39,66,65];
function keyhandler (e) {
// Javascript defines all the local variables at top.
// This is what hoisting is
var key;
var keys;
e = e || event;
console.log(e.keyCode);
// at this point, local variable keys isn't initialized,
// that's why you are getting the undefined error.
key = keys[0];
if (key == e.keyCode) {
console.log("correct key");
if (keys.length == 1){
console.log("konami");
} else {
// you are referencing a local variable here
keys = keys[1,keys.length];
}
}
else {
// you are referencing a local variable here
keys = [38,38,40,40,37,39,37,39,66,65];
}
}
document.onkeydown = keyhandler;
As other posters mention, simply removing the var from keys may fix your issue, if that's what intended, but I think it's important to understand what Javascript technically does in this situation.

the issue was that
var key = keys[0];
is not a javascript expression as mentioned in the comment it needed to be replaced with
var key = keys.slice(0,2);

Related

How to access property in function by sending values from function call

i am sending values from function call
this.checkname("models", "name");
this.checkname("designers", "name");
i want to access my object.method by using a function call=>
checkname = (key, value) =>{
const models = this.state.model;
const designers = this.state.designers;
if(key.value === ""){
console.log("Unanamed");
}
}
i am not able to access (key.value) how to do that?
You can’t use a variable to access an objects property with the „.“ notation instead use: key[value].
This of course only works, if the value supplied as „key“ argument is an object (as was pointed out in the comments).
Edit: Ok now I seem to actually understand what you’re trying to do. If you want to use either this.state.models or this.state.designers depending on what string is supplied as key, you will have to supply some kind of condition (if-else) to decide which to use. Something along the lines of:
let person;
if (key === "models") {
person = this.state.models;
} else if (key === "designers") {
person = this.state.designers;
}
if (person[value] === "") {
...
}

Can I reference a function within a function that is in parent space?

My function is not behaving as expected and I'm trying to determine if it's because I have a misunderstanding of scope.
The function below searches through an array called dataLayer to see if any of the objects have a eventAction property matching a string.
The idea is that if I cannot find a matching value, then push a value into dataLayer array, else do nothing.
I have a function that references another function. getNegativeErrs() references getByValue().
What would the appropriate way of getting it to work be? How can I make getByValue() available to other functions?
Code:
var errors = [
'Your password must be at least 6 characters long.',
'Please enter a valid email address.'
];
getNegativeErrs(errors);
function getNegativeErrs(ers) {
for( i in errors ) {
var errobj = getByValue(dataLayer, errors[i]); //updated based on comments
if(!errobj) { // if errobj is undefined continue. errobj is undefined when it should have a value so getByValue() not working as expected
dataLayer.push({
'event': 'negative_errors',
'unseen': errors[i]
})
}
}
}
function getByValue(arr, value) {
for (var j=0, jLen=arr.length; j<jLen; j++) {
if (arr[j].eventAction == value) return arr[j];
}
}
Is the second argument to getByValue supposed to be a string or an integer? Currently it is an integer, which is the index of the errors array that you loop over. Your loop is invoking getByValue like this:
getByValue(dataLayer, 0)
getByValue(dataLayer, 1)
If you mean to pass in the value and not the index, change getByValue(dataLayer, i) to getByValue(dataLayer, errors[i]).
If that is the extent of your code, getByValue() is in the global scope and should be accessible.
If this is it, it looks like this might not be working because dataLayers is not defined.
http://jsbin.com/bivepitafe/
Also, note that getNegativeErrors() is not using the ers parameter passed to it, but the errors variable that is also in the global scope.
function getNegativeErrs(ers) {
for( i in errors ) {
there is a problem with the function getNegativeErrs, you are not using the argument that you passed into it. it should look like this
function getNegativeErrs(ers) {
for( i in ers ) {
var errobj = getByValue(dataLayer, ers[i]); //updated based on comments
if(!errobj) { // if errobj is undefined continue. errobj is undefined when it should have a value so getByValue() not working as expected
dataLayer.push({
'event': 'negative_errors',
'unseen': ers[i]
});
}
}
}
Also, you are checking the dataLayer array for errors matching the key eventAction but then in the above function you are adding the key event... either one will work, you just need to make them the same.
I don't see an issue of scope though. If you want to completely rule that out though, just cut and paste the getByValue function above the getNegativeErrs function.

Javascript "with" operator removal

I recently ran into some issues with a plugin and outlined the issue in this post: With operator & dashes in object keys and wanted to know if the modifications I've made below cover the scenarios that the with scope blocks would have covered.
I've modified some code to remove the with operator and I'm wondering if I've replicated everything properly in doing so.
Here is the original code:
var test = new Function('$f','$c','with($f){with($c){return{'+ declarations +'}}}'));
Where $f and $c are passed objects (From what I could tell, $f shouldn't ever have a property of $c). The declarations variable is a string that has a colon in it (EX: "value:color") and available within the scope.
Here is my modified code:
var test = function($f, $c, declarations) {
var result = {};
var value = "";
var split = declarations.split(":");
if (split.length < 2) {
throw new Error("Declaration is in an invalid format");
}
if ($f[$c] !== undefined && $f[$c][split[1]]) {
value = $f[$c][split[1]];
}
else if ($c[split[1]]) {
value = $c[split[1]];
}
else if ($f[split[1]]) {
value = $f[split[1]];
}
else {
value = "" + split[1];
}
var key = split[0];
result[key] = value;
return result;
};
Everything appears to work as it did previously, but this modification now handles the use case where the declarations variable could have a dash in it (EX: "value:background-color"). Additionally the declarations variable is passed into the function, to ensure it's defined.

accessing methods of an object within an array

I have an array which I'm adding objects to dynamically like so
var _plugins = [];
this.registerPlugin = function(plugin){
_plugins.push(plugin);
plugin.onInit()
},
This is all within a class and I am trying to use a method like this which should run the method passed in to meth
this.runPluginMethod = function(meth, call_obj){
for (x in _plugins){
x[meth](call_obj)
}
}
The Objects I am adding to the _plugins array are created like this
var ourPlugin = Object.create(babblevoicePlugin);
Object.defineProperty(ourPlugin, 'onInit', {value : function()
{
console.log('this is from reflex oninit')
}});
When I try running mianClass.runPluginMethod('onInit', 'a') It does nothing, doesn't run console.log like it should to my mind.
Can anyone help? am I doing something wrong? is this possible?
I think the problem is here:
this.runPluginMethod = function(meth, call_obj){
for (x in _plugins){
x[meth](call_obj)
}
}
You're trying to access a property of a key instead of the object you're looking for. Changing it to the following should work.
this.runPluginMethod = function(meth, call_obj){
for (x in _plugins){
_plugins[x][meth](call_obj)
}
}
EDIT
As another example, check the output of the following in a js console:
x = ['a','b','c'];
for (i in x){ console.log(i, x[i]) };

strange behaviour with javascript map/object

I am using javascript map to store keys and values. Later on I check if specified key is present in map or not, but it sometimes gives correct result but sometimes it don't. I tried to print the map using console.log(mapname), it shows all keys, but if I try to check if some specified key is present - sometimes it gives wrong answer.
Am using following code:
// following code is called n times in loop with different/same vales of x
myMap : new Object();
var key = x ; // populated dynamically actually
myMap[key] = "dummyval";
if(myIdMap[document.getElementById("abc").value.trim()] != null)
alert('present');
else
alert('not present');
What can be the possible problem? Can alphanumericstring/integers values can be used as keys?
var myMap = {};
// ...
//simulating your inner loop; is this close enough?
//Note: A MacGuffin is a plot device to move the story forward.
// Like a time machine, or a space ship.
for (var key in macGuffin) {
myMap[key] = macGuffin.processItem(key);
}
// ...
var myKey = document.getElementById("abc").value.trim();
//Note the use of !==; false == null == 0 == '', but null only === null
if (myMap[myKey]!==null)
//Better? (typeof myMap[myKey] != 'undefined')
console.log('present');
else
console.log('not present');
Be sure you're aware that the value stored with the key could be null, as the following code shows:
a = {
"mykey": null
}
for (x in a) {
if (a[x] == null) {
alert(x + " is null!");
}
} // produces a single alert: "mykey is null!"
I think you have to store keys in some temporary table or objects like session or cookies for future retrieve.
you have dynamically store x position value in mymap[key] but every time it loads and overwrite your new values. you something doing wrong there..

Categories