I have an Object called Button_Objs, its purpose is to hold all my Button Objects. I made a function in my Button_Objs which iterates through each of its variables. Here is where the issue is, I have a if statement that says: if (i typeof Button){}. I do this so it only selects the Button Objects that are stored.
Here is the JSFiddle of this: http://jsfiddle.net/MichaelMitchell/vcZTR/15/
var Button_Objs = function() {
this.getButtons = function() {
var i;
for (i in this) {
if (type of i == Button) { //PROBLEM, also does not work with instanceof.
document.getElementById('console').innerHTML += ( "button: " + i + "<br />");
}
}
};
};
I also tried instanceof, but alas it will not work :(
i typeof Button is invalid syntax and type of i == Button as well.
When you use a for...in loop to iterate over an object, the loop variable will hold the name of the property, not the value. You can use the name to get the value:
if(this[i] instanceof Button)
Read more about the for...in loop (I recommend to have a look at MDN to learn about JS basics).
Apart from this, I don't see why you need a constructor function to create a container for your buttons. You could just use a plain object:
var buttons = {};
// somewhere
buttons['button' + i] = new Button(...);
and then again use the for...in loop to iterate over the object.
And if you don't actually need the names (they just seem to be some sort of enumeration), why don't you use an array?
var buttons = [];
// somewhere
buttons.push(new Button(...));
and then use a for loop to iterate over all buttons. You would not even have to test for their type.
Related
I am trying to make a user-defined function to work on variables by using the dot(.) operator rather than sending as the parameter. So in my program, I have an array of integer and I need to perform for each on that not by using forEach built-in function. I know this sound rubbish. So I have created a function named somefunc and have a variable called arr.
code that I have done
var somefunc = function()
{
console.log('this function executed');
}
var arr=[1,2];
arr.somefunc();
The code I am trying to mimic
var friends = ["Mike", "Stacy", "Andy", "Rick"];
friends.forEach(function (eachName, index){
console.log(index + 1 + ". " + eachName); // 1. Mike, 2. Stacy, 3. Andy, 4. Rick
});
I want to execute a function like that forEach.
Try to add your function to array proptotype to create desired behavior. Access the current array using this.
Array.prototype.customIterator = function() {
// this.forEach(() => {})
}
You should use Prototypes here. Add somefunc to a prototype of a JS built in Array type.
Array.prototype.somefunc = function() {
this.forEach(function (eachName, index) {
console.log(index + 1 + ". " + eachName);
});
// or you can use other ways to itarate over all array elemets
// like a simple for loop for (let i=0; i < this.length; i++) {...}
// 'this' here refers to an array you are running somefunc on
}
var friends = ["Mike", "Stacy", "Andy", "Rick"];
friends.somefunc();
Each function like forEach , map , etc. is also present in prototype of an Array, they are properties of a prototype. You can see it by doing console.log(Array.prototype); You can see that the prototype of Array has many built in methods available to you out of the box which you can call by using the dot. So you just add your own functions alongside with them by assigning a new function property to Array.prototype as show in a snippet above.
Please check the code below -
custom_array.push(...) is working
but
custom_array[i] = "n"
is not working.
There are a couple more things which i am not sure why it is not working. Please note the comments with "?" which is not working. Please refer fiddle - http://jsfiddle.net/vc0bbm3d/
The reason that setting items using bracket syntax doesn't work for your object inheriting an array, is that it's not actually an array.
An array has special code for handling property assignment (which is what you do with the bracket syntax) when the property name is an integer. If the index is outside the current length, the length property is adjusted.
When you assign a value to a property in your object, there is no special code to handle the length. The property is just assigned as usual, and the length is never adjusted. As the object already has code for handling what's happening when you use the bracket syntax, the array that it inherts never comes into play.
For the bracket syntax to work in that way, the object has to be an actual array.
try
ar[3] = 2;
ar.length =4
That way it knows you have added something.
Here's an example of what I mean when I say create a layer around the default array object to extend functionality:
var SuperArray = function(){
this.arr = Array.prototype.slice.call(arguments);
};
//abstraction of default array functionality
SuperArray.prototype.set = function(index, value){
this.arr[index] = value;
return this;
};
SuperArray.prototype.unset = function(index){
this.arr.splice(index, 1);
return this;
};
//extension of default array functionality
SuperArray.prototype.consoleList = function(){
var arr = this.arr;
for(var i = 0, l = arr.length; i < l; i++){
console.log(arr[i]);
};
return this;
};
var extArr = new SuperArray(1,2,3);
extArr.set(2, 25); //does array[2] = 25;
extArr.unset(1); //removes array[1]
extArr.consoleList();//console.logs all items in array
extArr.set(2, 25).unset(1).consoleList();//same thing
this simple object accepts arguments and sets them directly into an array, which we then manipulate how we wish. You can then add any utility functions that you need, check for existing array functionality, etc.
I'm working on an Exercism JavaScript exercise and I've gotten stuck. The exercise is to create a function which loops over a string, then creates an object with each word as a key and the number of times that that word appears as the corresponding value. Simple right? Well, now I'm stuck on one of the later steps, the input string contains the word "constructor" and you need to put it into the object as a key. Here's the code I have so far, as well as the Jasmine spec which tests it:
function words(words){
count = {};
splits = words.split(" ");
for(var i = 0; i < splits.length; i++){
splits[i] = splits[i].replace(/[;:!&#$%\^,]/g, "").toLowerCase();
if([splits[i]] == ""){
continue;
}else if(count[splits.i] !== null){
count[splits[i]]++;
}else{
count[splits[i]] = 1;
}
}
return count;
};
words("constructor Constructor")
describe("words()", function() {
it("counts constructor", function() {
var expectedCounts = { constructor: 2 };
expect(words("constructor Constructor")).toEqual(expectedCounts);
});
});
Problem is, using either dot or bracket notation in the second conditional, it evaluates to true as "constructor" is inherited from the Object prototype up the chain and so it tries to increment a NaN value. I've tried to find a work around but have come up empty. And as much as I love JS, it's inheritance has it's quirks. Is there any way to prevent inheritance in this case or another work around that anyone can think of?
Instead of comparing to null to see if you've already set a property on count, use hasOwnProperty. hasOwnProperty doesn't include properties that come from up the prototype chain, only ones directly on the object.
if (count.hasOwnProperty(splits[i])) {
count[splits[i]]++;
} else{
count[splits[i]] = 1;
}
I am trying to serialize non enumerable properties inside the replacer function.
What is wrong here?
help please.
var obj = {x:1,y:2};
Object.defineProperty(obj,"x",{enumerable:false});
var s = JSON.stringify(obj,function(key,value){
if(this.propertyIsEnumerable(key) == false){
Object.defineProperty(this,key,{enumerable:true});
}
return value;});
//"{"y":2}"
// x remains not enumerable
I guess non enumerable properties is being filtered out before the execution of replacer function. Not sure.
If .stringify filters out non-enumerable properties, then yes, they aren't available in the callback - it has already done that filter. Why don't you just loop through all the keys of the object before you stringify, and use your logic inside to set it as enumerable if it isn't already. Then, just simply call JSON.stringify(obj);. Unfortunately as you pointed out, for in loops and jQuery's $.each does not loop over non-enumerable keys. I found that .getOwnPropertyNames should accomplish what you want - https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames
Here's an example of using it, similar to your code you provided:
http://jsfiddle.net/9Em82/
var obj = {x:1,y:2};
Object.defineProperty(obj,"x",{enumerable:false});
var all = Object.getOwnPropertyNames(obj);
for (var i = 0, j = all.length; i < j; i++) {
console.log("KEY: " + all[i]);
}
I am trying to remove an element from a Javascript associtive array using the value to find it, but I am having trouble. I have tried splice and JQuery's grep method and neither have worked for me. This is what I currently have.
var array_path = new Array();
function bulk_upload(){
var temp_array = new Object();
for (var i = 1; i<8; i++){
temp_array[i] = $('#path' + i).val();
if(temp_array[i]!='' && temp_array[i]!=null){
array_path['path' + i] = $('#path' + i).val();
}
}
process_txt();
}
function process_txt(){
//alert(array_path.indexOf(full_path)); //returns nothing
var removed_element = array_path.splice(getKey(array_path), 1);
//array_path = $.grep(array_path, function(val) { return val != full_path; });
alert(removed_element);//return nothing, just blank alert box
}
function getKey(data) {
for (var prop in data)
return prop;
}
The way to do this is to use the delete operator.
delete array_path[getKey(array_path)]
Some Background Information
In JavaScript, almost everything descends from Object.prototype. JavaScript, being an open and dynamic language allows you to create/modify properties of objects by simple assignment. This is very similar to what an associative array -- a structure that contains keyed values.
Under the hood an array is just an object that descends from Array.prototype with numeric keys and a special property called length. The length property just returns one greater than the highest numeric property. In essence, an Array is an object with different semantics.
If you're wanting an associative array then Array is not the object you want to descend from. You would want to descend directly from Object. There are two ways to do that, you could either use the new operator or an empty object literal. The syntax for both is below:
var o = new Object();
var o = {};
The second is preferred since it's a little bit more concise.
I wrote a blog post about this a while back, have a look if you want a little bit more info.
There is no such thing in JavaScript as an "associative array" per se. The data structure which corresponds to this concept is simply a JavaScript Object.
Of course, a JavaScript Array (like essentially everything in JavaScript) is an Object, but one with additional capabilities. So you can use an Array as a key-value map, but it's really not the correct structure for that.
To remove a key from an Object, you just do something like this:
var myObj = {};
var myKey = "blah";
myObj[myKey] = 1234; // Adds or updates value for "blah" to 1234.
delete myObj[myKey]; // Removes key-value pair for "blah".
Have you tried delete hash.someKey; ?
You can give your object a remove method, or use apply or call to use another object's remove method, if defined.
function myObj(members){
for(var p in members) this[p]= members[p];
}
myObj.prototype.remove= function(val){
for(var p in this){
if(this[p]=== val) delete this[p];
}
return this;
}
myObj.prototype.toString= function(){
var A= [];;
for(var p in this){
if(this.hasOwnProperty(p)){
A.push(p+':'+this[p])
}
}
return '{'+A.join(', ')+'}';
}
var O= new myObj({a: 1, b: 10, c: 100});
alert(O)
O.remove(10);
alert(O)
I'm not psychic, so I can only guess that you wanted to accomplish something like this:
var paths = [];
function getPaths() {
for(var i = 1; i < 8; ++i) {
var value = $('#path' + i).val();
if(value) paths.push(value);
}
}
function process() {
var firstPath = paths.shift();
// do stuff
}
getPaths();
if(paths.length) process();