Good morning
I am wanting to pass a string as a functions parameter in java script but the string will represent the name of a property that i want the function to operate on. I have seen this done before but don't quite comprehend it.
the function below shows what i'm referring to with the "field" parameter. it's passed a value as a string but operates on the property who's name matched the value of the string.
What i want to do is cycle through the array of objects and return only the values stored in the property who's name matches the string passed. The idea is to have one function which can process any objects with properties that have been added to an array and return any property without having to write a loop function for each property.
Below is an example of this type of magic:
listName.sort(sort_by('stringPropertyName', false, function(a){return a.toUpperCase()}));
var sort_by = function(field, reverse, primer){ //http://stackoverflow.com/questions/979256/how-to-sort-an-array-of-javascript-objects
var key = function(x){return primer ? primer(x[field]) : x[field]};
return function (a,b){
var A = key(a), B = key(b);
return ((A < B) ? -1 :(A > B) ? +1 : 0) * [-1,1][+!!reverse];
}
}
If you want to "cycle through the array of objects and return only the values stored in the property who's name matches the string passed", you may do this :
function getValues(array, propname) {
var values = [];
for (var i=0; i<array.length; i++) {
if (typeof array[i][propname] !== 'undefined') {
values.push(array[i][propname])
}
}
return values;
}
The "trick" is to access the property using obj[propname] instead of obj.propname when propname is a variable containing the name of the property.
For example window.location can be accessed as window["location"]
DEMONSTRATION
Related
Let´s assume I have an object property which is passed into a function. In this case 'name' is filled with 'myObject.name' (which has the value 'Tom') - so basically 'Tom' gets passed into the function as the 'name'
function(name) {
do something //non-essential for my question
}
Is it possible to get the object, where 'Tom' is the property of, just by having the information 'Tom'? Basically I´m looking to get myObject.
Thanks :)
No, that's not possible.
All that the function knows is that one of its parameters was pointed to the string "Tom", not what else points to that string somewhere else in memory.
You can store objects within an array, filter the array to match property name of object to parameter passed to function using for..of loop, Object.entries(), which returns an array of property, values of an object.
const data = Array();
const setObjectPropertyName = _name => {
data.push({[_name]:_name});
return data
}
const getObjectByPropertyName = prop => {
let res = `${prop} property not found in data`;
for (let obj of data) {
for (let [key] of Object.entries(obj)) {
if(key === prop) return obj;
}
}
return res;
}
let s = setObjectPropertyName("Tom");
let g = getObjectByPropertyName("Tom");
let not = getObjectByPropertyName("Tome");
console.log(s,"\n", g, "\n", not);
Disclaimer: you absolutely should not do this. I'm only posting this because it is in fact possible (with some caveats), just really not advisable.
Going on the assumption that this is running in the browser and it's all running in the global scope (like in a script tag), you could technically iterate over the window object, check any objects in window for a name property and determine if their name property matches the name passed to your function.
var myObject = {
name: 'Tom',
thisIs: 'so awful',
imSorry: true,
};
function doSomethingWithName(name) {
for (var obj in window) {
var tmp = window[obj];
if (Object(tmp) === tmp && tmp.name === name) {
return tmp;
}
}
}
console.log(doSomethingWithName(myObject.name));
I have a Typescript object that defines a function. The object itself defines an array of some objects. So I am trying to add a function to act more like an indexer. The function always returns the parent object where it is defined and not a specific string value.
Here's the code. The variables is defined as an Array of object having name and value as properties.
valueOf(key: string): string {
var result = '';
if (key === null || key === undefined || key.length === 0) {
return result;
}
for (var i = 0; i < this.variables.length; i++) {
if (this.variables[i].name === key) {
result = this.variables[i].value;
break;
}
}
return result;
}
UPDATE
The above function is defined on a Typescript object. This object includes a property of type Array. I want to query that array based on a string key and not number key. That's why I wrote the above function to loop over the elements of property "variables", i.e. the Array, when there is a match on "name" === "key passed in", return the "value" associated with the object inside "variables property".
for instance, I can use the above as:
var tsObj = new TsObj(...);
tsObj.valueOf('key1');
function CookieStorage(maxage, path) { // Arguments specify lifetime and scope
// Get an object that holds all cookies
var cookies = (function() { // The getCookies() function shown earlier
var cookies = {}; // The object we will return
var all = document.cookie; // Get all cookies in one big string
if (all === "") // If the property is the empty string
return cookies; // return an empty object
var list = all.split("; "); // Split into individual name=value pairs
for(var i = 0; i < list.length; i++) { // For each cookie
var cookie = list[i];
var p = cookie.indexOf("="); // Find the first = sign
var name = cookie.substring(0,p); // Get cookie name
var value = cookie.substring(p+1); // Get cookie value
value = decodeURIComponent(value); // Decode the value
cookies[name] = value; // Store name and value
}
return cookies;
}());
// Collect the cookie names in an array
var keys = [];
for(var key in cookies) keys.push(key);
// Now define the public properties and methods of the Storage API
// The number of stored cookies
**this.length = keys.length;**
// Return the name of the nth cookie, or null if n is out of range
this.key = function(n) {
if (n < 0 || n >= keys.length) return null;
return keys[n];
};
// Return the value of the named cookie, or null.
this.getItem = function(name) { return cookies[name] || null; };
**// Store a value
this.setItem = function(key, value) {
if (!(key in cookies)) { // If no existing cookie with this name
keys.push(key); // Add key to the array of keys
this.length++; // And increment the length
}**
// Store this name/value pair in the set of cookies.
cookies[key] = value;
// Now actually set the cookie.
// First encode value and create a name=encoded-value string
var cookie = key + "=" + encodeURIComponent(value);
// Add cookie attributes to that string
if (maxage) cookie += "; max-age=" + maxage;
if (path) cookie += "; path=" + path;
// Set the cookie through the magic document.cookie property
document.cookie = cookie;
};
Hello guys, I found this piece of code in a book that I'm reading, and I saw this one line that made no sense to me:
**// Store a value
this.setItem = function(key, value) {
if (!(key in cookies)) { // If no existing cookie with this name
keys.push(key); // Add key to the array of keys
this.length++; // And increment the length
}**
If the object's that we're currently in length property has already been defined by previous line of code (this.length = keys.length;)
Why do we need to increment its length by this.length++ ??
Isn't keys.push(key) enough?
EDIT:
Thanks to all who answered.
After staring at this code for a couple of minutes, i figured out that the first length declaration was relevant only for that "phase" in scripts time.
this.length = keys.length
means that this objects length is equal to the current length of key array.
Later on, when we added another element to key array, it's length increased, this why we must tell it to our object by increasing its own value this time (this.length++;)
It is enough, but if you want to use this function from outside code then you don't have access to the internal values array, so this is a convenience property to get the length.
You can replace it with a getter like this and skip updating it manually each time:
Object.defineProperty(this, "length", {
get: function() {
return keys.length;
}
});
NOTE: As #zzzzBov noted in his comment, IE8 and below don't support getters yet.
this.setItem = function(key, value) {
if (!(key in cookies)) { // If no existing cookie with this name
keys.push(key); // Add key to the array of keys
this.length++; // And increment the length
}
...
};
If you look at just this code, you'll notice that it's declaring a function. The code within this function will execute when setItem is called on the instance of CookieStorage.
The previous line is called when a CookieStorage instance is being created. The purpose of incrementing the length is to produce a public API for the length of the privately stored array.
It is my first answer. Hope it helps.
Looks like this.length does not mean the cookie array's length, isn't it?
Yes, if it uses the push() function, the array's length will definitely increment by one.
You do not have to do it manually.
Unless, this.length mean something else.
For your firtst question:
Basically It's defines the number of the parameters that the function gets only if you Asking for the function Length for example:
CookieStorage.length
function a() {}
function b(a, b) {}
function c(a,b,c) {}
console.log(a.length); //output 0
console.log(b.length); //output 2
console.log(c.length); //output 3
for the this.length question:
Well, this.length is the property that hold the keys.length.
so when you set a new item to the keys array it's update the length property with the new length. so you can use it with:
var cookies = new CookieStorage();
cookies.setItem("test","test");
cookies.length //output 1
I have a JavaScript object called data. I am using the following code to sort the keys in the object :
var index = [];
// build the index
for (var x in data) {
index.push(x);
}
// sort the index
index.sort(function (a, b) {
return a == b ? 0 : (a > b ? 1 : -1);
});
I then want to access the value for a particular index key in the following way :
for (var i=0; i<index.length; i++) {
var key = index[i];
document.getElementById(key).value = data.key;
}
However I am getting undefined for the data.key value. Can anyone suggest why ?
Change to
document.getElementById(key).value = data[key];
If the key you want to access is stored within a variable, you have to use the bracket notation. In your code, JavaScript will search for a key named "key" and thus fails.
Example:
var key = 'test';
console.log( data.key ); // yields content of data.key
console.log( data[key] ); // yields content of data.test
How about
Object.keys(data)[key] ?
Not sure it would work, without showing the structure of data.
edit: This way retrieves object key according to numerical index (0,1...,n), and not by name.
if (sorted[i].Document === 'abc' || sorted[i].Document === 'xyz') {
delete sorted[i].Document;
}
When i try to remove the particular two documents, it gets removed but the next time it throws me an error saying Document is undefined.
var sorted = DocumentListData.Documents.sort(function (a, b) {
var nameA = a.Document.toLowerCase(),
nameB = b.Document.toLowerCase();
return nameA.localeCompare(nameB);
});
I am sorting the documents, then iterating it and then trying to remove the documents which are abc and xyz.
You're trying to call toLowerCase on properties that don't exist because you just deleted them. Check if they exist before attempting to execute methods on them.
// i used empty string as the default, you can use whatever you want
var nameA = a.Document ? a.Document.toLowerCase() : '';
var nameB = b.Document ? b.Document.toLowerCase() : '';
If you are trying to remove the array elements instead of just their Document properties, you should be using splice instead of delete:
if (sorted[i].Document === 'abc' || sorted[i].Document === 'xyz') {
sorted.splice(i, 1);
}