How destructure an object starting from a constant? - javascript

I have a utils/constant.js file with:
// Key of total elements in remote collection
export const TOTAL_ELEMENTS = "totalElements";
I need to access to totalElements via the constant.
import { TOTAL_ELEMENTS } from "./constants.js";
[...]
let data = {
content: "foo",
totalElements: 54
};
if(TOTAL_ELEMENTS in data) {
// pseudocode, of course it doesn't work.
// of course in my case need to return 54
const { TOTAL_ELEMENTS } = data;
return TOTAL_ELEMENTS;
}

Edit:
As #pilchard mentioned, using Object.prototype.hasOwnProperty is a better way of doing this in case the value is falsy:
if (data.hasOwnProperty(TOTAL_ELEMENTS)) {
return data[TOTAL_ELEMENTS]
}
Original answer:
While the answer #jsN00b provided works and is closer to OP's #sineverba code, there's an issue here since the in operator checks for the specified property in both the specified object AND its prototype chain.
This means that, for example, if datas prototype is Object.prototype, something like 'toString' in data would work as well.
For that reason, you could use something like the following to only check for the 'totalElements' key in the object itself, and avoid destructuring:
if (data[TOTAL_ELEMENTS]) {
return data[TOTAL_ELEMENTS]
}

The desired objective is:
use the constant TOTAL_ELEMENTS (& not directly the prop-name)
check if data has the corresponding prop
if found, then return the value of the prop
The below code-sample may be one solution to achieve the desired objective:
if (TOTAL_ELEMENTS in data) return data[TOTAL_ELEMENTS];
NOTE
The above does not de-structure the data. It access the corresponding prop directly without the need to destructure.

Related

How do I access a parent object's name in node.js?

I am trying to write a universal function that can log some useful data in several different objects, but I don't want to have to pass a parameter that is unique to each object. Ideally, the initial name of the object, like LaunchRequestHandler would be a perfectly sufficient bit of data to use. How can I access this object's name?
const LaunchRequestHandler = {
canHandle(handlerInput) {
//I want to be able to know the name of the outer parent here.
//In this case, I would expect to retrieve 'LaunchRequestHandler'
logCanHandle(handlerInput);
return handlerInput.requestEnvelope.request.type === 'LaunchRequest';
}
I don't really understand what are you trying to do but maybe you can do something with ES6 classes, like so:
class LaunchRequestHandler {
canHandle() {
console.log(this.constructor.name);
}
};
const x = new LaunchRequestHandler();
x.canHandle(); // outputs 'LaunchRequestHandler'

Storing an ES6 Javascript class's getter/setter when inheritance is involed

Edit: The reason I am doing the below process is so I can store the reference to the getter/setter in a dictionary. This allows me to have the key of my dictionary be an ID of an HTML element. Thus, if a property is changed in the HTML, I can do something like:
var propData = allMyGetterSetters[e.originalTarget.id];
propData.getSet.set(propData.obj, e.originalTarget.value);
This also allows me to do a loop and update all the HTML, should my logic change it.
I need to store a reference to the getter/setters of a few properties of one of classes. I've managed to do this with the following code:
Object.getOwnPropertyDescriptor(Object.getPrototypeOf(myClassObj.position), "x");
For simplicity, since I have to do this several times, I have the following method:
_makeGetSetObj(object, property){
return {
getSet: Object.getOwnPropertyDescriptor(Object.getPrototypeOf(object), property),
obj: object
};
}
And subsequent code would look something like this:
var xPos = this._makeGetSetObj(myClassObj.position, "x");
// ...
xPos.getSet.get(xPos.obj);
All of this works perfectly.
However, I now need to store a reference to a getter/setter of my myclassObj object. However, the following does not work
this._makeGetSetObj(myClassObj, "name");
This actually gives me an error that name does not exist on the object. I've managed to figure out that the problem is my inheritance, which looks something like this
|-- BaseClass
|-- MyClass
|-- DerivedClass
The problem seems to be that myClassObj is actually an object of type DerivedClass, which doesn't have the property name on it.
So, if I do this:
this._makeGetSetObj(myClassObj.__proto__, "name");
It works to get the prototype, but when I try to use it as shown above (with my xPos example), it fails because it seems to still be storing an reference in obj as a DerivedClass object.
If I pull outside of my method, and try things manually, this works:
var name = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(myClassObj.__proto__), "name");
name.get(myClassObj);
This obviously breaks my method though, as one part requires the __proto__ while the other part does not.
So, my question is: Is there a way to keep my current logic, or will I have to create a special method for the places with the described problem?
Thanks.
Hardcoded prototype doesn't smell good. Prototype chains should always be iterated:
let proto = obj;
let descriptor;
do {
descriptor = Object.getOwnPropertyDescriptor(proto, prop);
} while (!descriptor && proto = Object.getPrototypeOf(proto))
...
This functionality has been already implemented by Reflect. Instead of parsing descriptors manually, it may be
const getSet = {
get: () => Reflect.get(obj, prop),
set: (val) => { Reflect.set(obj, prop, val) }
};
Or... just
const getSet = {
get: () => obj[prop],
set: (val) => { obj[prop] = val }
};
Because this is what happens when accessors are called directly.

How to modify object property values while enumerating

An API call I'm making returns empty objects in lieu of null. Tedious doesn't like this, so before I save the API response I'm cleaning the data with the following function:
var object_to_return = input_object;
_.forOwn(object_to_return, function(key_value) {
if (_.isEmpty(key_value)) {
object_to_return[key_value] = null;
}
});
return object_to_return;
This isn't quite correct and I'm curious if anyone knows why and how I can fix it. I'm especially interested in the why and if I should bother with even returning a copy of the object (is it being passed in by reference, or...?)
_.forOwn exposes the key in the callback function; therefore, this worked:
module.exports.convertEmptyObjectsToNull = function(target_object) {
_.forOwn(target_object, function(property, key) {
if (_.isEmpty(property)) {
target_object[key] = null;
}
});
}
Also, as #apsillers mentioned, I wasn't doing much with my assignments, so this method just mutates the input object and doesn't attempt to clone it and return a copy.

Hashing JavaScript objects

I have a function that receives a list of JS objects as an argument. I need to store information about those objects in a private variable for future reference. I do not want to stuff a property into the objects themselves, I just want to keep it out of band in a dictionary. I need to be able to lookup metadata for an object in sub-linear time.
For this I need a hash function such that, for any two objects o1 and o2,
hash(o1) !== hash(o2) whenever o1 !== o2.
A perfect example of such a hash function would be the memory address of the object, but I don't think JS exposes that. Is there a way?
Each object reference is different. Why not push the object onto an array? Traversing the array looking for an object reference might still perform better than inspecting each object in a recursive manor to generate a hash key.
function Dictionary() {
var values = [];
function contains(x) {
var i = values.length;
while(i--) {
if (values[i] === x) {
return true;
}
}
return false;
}
function count() {
return values.length;
}
function get(i) {
return (i >= 0 && i < values.length) ? values[i] : null;
}
function set(o) {
if (contains(o)) {
throw new Error("Object already exists in the Dictionary");
}
else {
return values.push(o) - 1;
}
}
function forEach(callback, context) {
for (var i = 0, length = values.length; i < length; i++) {
if (callback.call(context, values[i], i, values) === false) {
break;
}
}
}
return {
get: get,
set: set,
contains: contains,
forEach: forEach,
count: count
};
}
And to use it:
var objects = Dictionary();
var key = objects.set({});
var o = objects.get(key);
objects.contains(key); // returns true
objects.forEach(function(obj, key, values) {
// do stuff
}, this);
objects.count(); // returns 1
objects.set(o); // throws an error
To store metadata about objects, you can use an WeakMap:
WeakMaps are key/value maps in which keys are objects.
Note that this API is still experimental and thus not widely supported yet (see support table). There is a polyfill implementation which makes use of defineProperty to set GUIDs (see details here).
Javascript does not provide direct access to memory (or to the file system for that matter).
You'd probably just want to create your properties/variables within the analysis (hash) function, and then return them to where the function was called from to be stored/persisted for later reference.
Thanks everyone who chipped in to reply. You all have convinced me that what I want to do is currently not possible in JavaScript.
There seem to be two basic compromises that someone with this use case can chose between:
Linear search using ===
=== appears to be the only built-in way to distinguish between two identically-valued objects that have different references. (If you had two objects, o1 and o2, and did a deep comparison and discovered that they were value-identical, you might still want to know if they're reference-identical. Besides === you could do something weird like add a property to o1 and see if showed up in o2).
Add a property to the object.
I didn't like this approach because there's no good reason why I should have to expose this information to the outside world. However, a colleague tipped me off to a feature that I didn't know about: Object.defineProperty. With this, I can alleviate my main concerns: first, that my id would show up, unwanted, during object enumeration, and second, that someone could inadvertently alter my id if there were to be a namespace collision.
So, in case anyone comes here wanting the same thing I wanted, I'm putting it up there for the record that I'm going to add a unique id using Object.defineProperty.

Does Javascript have get/set keywords like C#?

I'm working with XULRunner and came across the following pattern in a code sample:
var StrangeSample = {
backingStore : "",
get foo() { return this.backingStore + " "; },
set foo(val) { this.backingStore = val; },
func: function(someParam) { return this.foo + someParam; }
};
StrangeSample.foo = "rabbit";
alert(StrangeSample.func("bear"));
This results in "rabbit bear" being alerted.
I've never seen this get/set pattern used in Javascript before. It works, but I can't find any documentation/reference for it. Is this something peculiar to XUL, a recent language feature, or just something I missed? I'm puzzled because I was specifically looking for something like this a few months ago and couldn't find anything.
For reference, removing "get" or "set" results in a syntax error. Renaming them to anything else is a syntax error. They really do seem to be keywords.
Can anyone shed some light on this for me, or point me towards a reference?
As suggested by Martinho, here are some links explaining the getter/setters in JS 1.5:
http://ejohn.org/blog/javascript-getters-and-setters/
http://ajaxian.com/archives/getters-and-setters-in-javascript
Be aware though, they don't seem to be supported in IE, and some developers have (legitimate) concerns about the idea of variable assignment having side-effects.
get/set are not reserved keywords as Daniel points out. I had no problem creating a top-level functions called "get" and "set" and using the alongside the code-sample posted above. So I assume that the parser is smart enough to allow this. In fact, even the following seems to be legitimate (if confusing):
var Sample = {
bs : "",
get get() { return this.bs; },
set get(val) { this.bs = val; }
}
According to Mozilla, they are not in ECMAScript.
JavaScript Setters And Getters:
Usually the setter and getter methods follow the following syntax in JavaScript objects. An object is created with multiple properties. The setter method has one argument, while the getter method has no arguments. Both are functions.
For a given property that is already created within the object, the set method is typically an if/else statement that validates the input for any time that property is directly accessed and assigned later on via code, a.k.a. "set". This is often done by using an if (typeof [arg] === 'certain type of value, such as: number, string, or boolean') statement, then the code block usually assigns the this.(specific)property-name to the argument. (Occasionally with a message logging to the console.) But it doesn't need to return anything; it simply is setting the this.specific-property to evaluate to the argument. The else statement, however, almost always has a (error) message log to the console that prompts the user to enter a different value for the property's key-value that meets the if condition.
The getter method is the opposite, basically. It sets up a function, without any arguments, to "get", i.e. return a(nother) value/property when you call the specific-property that you just set. It "gets" you something different than what you would normally get in response to calling that object property.
The value of setters and getters can be easily seen for property key-values that you don't want to be able to be directly modified, unless certain conditions are met. For properties of this type, use the underscore to proceed the property name, and use a getter to allow you to be able to call the property without the underscore. Then use a setter to define the conditions by which the property's key-value can be accessed and assigned, a.k.a. "set". For example, I will include two basic setters and getters for this object's properties. Note: I use a constant variable because objects remain mutable (after creation).
const person = {
_name: 'Sean';
_age: 27;
set age(ageIn) {
if (typeof ageIn === 'number') {
this._age = ageIn;
}
else {
console.log(`${ageIn} is invalid for the age's key-value. Change ${ageIn} to/into a Number.`);
return 'Invalid Input.';
}
},
get age() {
return this._age;
},
set name(nameIn) {
if (typeof nameIn === 'string') {
this._name = nameIn;
} else {
console.log(`Change ${nameIn} to/into a(ny) String for the name's
key-value.`);
return 'Invalid Input.';
}
},
get name() {
return this._name;
}
};
Where it gets interesting is when you try to set/assign a new key-value for the _age property, because it has to meet the if conditional in order to be successfully assigned, meaning not all assignments are valid, etc.
person.age = 'twenty-eight'; /* output: twenty-eight is invalid for the
age's key-value. Change twenty-eight to/into a Number. */
console.log(person.age); // output: 27 (twenty-eight was never assigned)
person.age = 28; // output: none
console.log(person.age); // output: 28
Note how I was able to access the person._age property via the person.age property thanks to the getter method. Also, similar to how input for age was restricted to numbers, input for the name property is now restricted/set to strings only.
Hope this helps clear things up!
Additionally, some links for more:
https://johnresig.com/blog/javascript-getters-and-setters/
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get
https://www.infragistics.com/community/blogs/infragistics/archive/2017/09/19/easy-javascript-part-8-what-are-getters-and-setters.aspx

Categories