Unable to use ternary operator within object data - javascript

I am using JavaScript and jQuery for my web application. In one case I have used the ternary operator in order to optimize the code while assigning object values.
I have manually set the d value to true for testing. But this value will vary based on customer given data in my application.
d=true;
var args = { d ? { target:"div"} : {main:"body"}, status:"enabled", updated:"yes" };
But this does not work and throws script error. Can you suggest how to update object data in optimized way.

Thats incorrect JavaScript syntax, You cant dynamicaly define properies on object this way. You can do this:
var args = {status:"enabled", updated:"yes"};
d ? (args.target = "div") : (args.main = "body");
In ES2015 you can do:
var args = {[d ? "target" : "main"]: d ? "div" : "body", status:"enabled", updated:"yes"};

You cannot use this operator in an object this way. Moreover, the data structure is incorrect. It would result in the following object :
{ { target:"whatever"} , status:"enabled", updated:"yes" };
Which is syntactically incorrect.
Consider writing something like this :
var args = {status:"enabled", updated:"yes" };
if(d){
args.target = 'div';
} else {
args.main = 'body';
}

Related

How can I reuse a variable in typescript?

I want to use my variable children for different cases:
var children = [];
if (folderPath == '/') {
var children = rootFolder;
} else {
var children = folder.childs;
}
But I get the error message:
variable 'children' must be of type 'any[]' but here has type
'Folder[]'
What does this mean?
In general, if "using a variable for different cases" involves using them for different types, then you're Doing Something Wrong.
Assuming rootFolder is of type Folder, and folder.childs is Folder[], your code looks like it could be something like
const children: Folder[] = (folderPath === '/' ? [rootFolder] : folder.childs);
and in fact you should be able to just do
const children = (folderPath === '/' ? [rootFolder] : folder.childs);
too and let inference handle things.
If you want to use if, then
let children: Folder[];
if (folderPath === '/') {
children = [rootFolder];
} else {
children = folder.childs;
}
should be fine; TypeScript will notice the variable is always definitely set after that if, even if it has no initial value.

What does the syntax x:y mean in JavaScript?

I am following a course on blockchain which has the following piece of code.
What does " index:this.chain.length+1 " mean? Is index a variable in the object newBlock? Or is it a key value pair? If it is a variable, why don't we simply use index=this.chain.length+1? Also what is the type of the object newBlock?
function Blockchain()
{
this.chain=[];
this.newTranscations=[];
}
Blockchain.prototype.createNeBlock = function(nonce,previousBlockHash,hash)
{
const newBlock ={
index:this.chain.length+1,
timestamp:Date.now(),
// all of the transactions in this block will be the transactions that waiting to be put in a block
transactions:this.newTranscations,
// nonce is hust a number giving proof of the transaction
nonce:nonce,
hash:hash,
previousBlockHash: previousBlockHash
}
// As we move all the pending transactions to the new block, we clear this array
this.newTranscations=[];
this.chain.push(newBlock);
return newBlock;
}
var Box = {
"playdoh":{"playdoh":["none", "some", "none", "none", "some"]}
};
Box of playdoh upon playdoh, you're getting into the study of Objects/Arrays/Maps.
To call the above out, it'd be
console.log(Box["playdoh"]["playdoh"][0]);
= none
console.log(Box["playdoh"]["playdoh"][4]);
= some
console.log(Box["playdoh"]["playdoh"][5]);
= null (undefined)
is the same as
console.log(Box.playdoh.playdoh[0]);
= none
console.log(Box.playdoh.playdoh[4]);
= some
console.log(Box.playdoh.playdoh[5]);
= null (undefined)
It is one of several ways to initialize an object called newBlock in javascript. Take a look at this documentation on MDN
The index property is of type number in this case, and it is set to equal chain[].length + 1

Split out props.location.search value

I'm trying to split out the values from props.location.search in React/Redux. I've successfully obtained the mixOne split however I can't seem to return the value of quantity. Here's my code:
const mixOne = props.location.search
? String(props.location.search.split("mixOne=")[1])
: "None";
const quantity = props.location.search
? Number(props.location.search.split("=")[1])
: 1;
And here's the URL that gets generated:
const addToCartHandler = () => {
props.history.push(
`/Cart/${productId}?quantity=${quantity}?mixOne=${mixOne}`
);
};
As you can see quantity returns null, when I need the value selected
props.location.search.split("=") on "?quantity=1?mixOne=Grape" would return [ '?quantity', '1?mixOne', 'Grape' ] since the next = is not until after mixOne.
There's a few different fixes here.
Your query string is invalid– a ? denotes the start of the query string. Separate parameters should be split up using & ampersand characters. It should look like this: ?quantity=1&mixOne=Grape
If you follow the standard here, you can then split it two ways: by = and then by & to get the different parameters. However, there is an easier way.
Using the new-ish URLSearchParams API, you can parse your parameters in a predictable way:
// Use the constructor with your `props.location.search`
const queryParams = new URLSearchParams(props.location.search);
// Use the getters to grab a specific value
const quantity = queryParams.get("quantity");
// Ensure it's a number for safety
const quantityNum = Number(quantity);
// ... the rest of your code here
The query is wrong. You're using double question marks. The second ? should be replaced with &.
?quantity=1&mixOne=Grape

Understanding procedures in Snowflake (javascript)

I came through lately following line of code while analyzing 3rd party data script.
CREATE OR REPLACE PROCEDURE WH.SCHEMA.PROCEDURE_NAME(DATE_OF_LOAD STRING) --input which will be binded later
RETURNS STRING
LANGUAGE javascript
AS $$
var drop_table = `drop table if exists TABLE_NAME;`;
var stmt_drop_table = snowflake.createStatement( {sqlText: drop_table} );
var incremental_data =
`CREATE TABLE AS <many arguments>
WHERE P.CZAS_MODYF_SF >= :1 --this is where biding of DATE_OF_LOAD occurs)
SELECT *, HASH(*) HASH FROM (
SELECT <arguments>
FROM CTE) q; `;
var stmt_incremental_data = snowflake.createStatement( {sqlText: incremental_data,binds: [DATE_OF_LOAD ].map(function(x){return x === undefined ? null : x}) } );
try {
stmt_drop_table.execute();
stmt_incremental_data.execute();
rtr = "Success!";
return rtr;
}
catch (err) {
return "Failed: " + err;
}
$$
;
Entire challenge I have is with:
var stmt_incremental_data = snowflake.createStatement( {sqlText: incremental_data,binds: [DATE_OF_LOAD ].map(function(x){return x === undefined ? null : x}) } ).
object.method part is clear. Same for binds. Code after binds is my issue here.
Another topic: Snowflake interpretes method's parameters as a JSON. Does it mean that bind value can be extended by assigning JS code?
I'll be greatly thankful for help and explanation.
The reason I did not post this as an answer initially is that JavaScript is not my area of expertise. I did dabble in it for a few months.
But in order to understand what is going on with:
[DATE_OF_LOAD ].map(function(x){return x === undefined ? null : x})
You need to break it down:
x === undefined ? null : x
This is called an elvis operator and is the equivalent of :
if (x === undefined)
{
return null
} else {
return x
}
Now that we know what the function does, we need to understand the map method. But in short it creates a new array with the results of calling a provided function on every element in the calling array.
So the simple answer copied from my comment is:
if DATE_OF_LOAD is undefined it will replace it with null, otherwise it will use whatever value is stored in DATE_OF_LOAD. That is because SQL does not know how to handle undefined.
But here is the reasoning for my answer.

Why is the value of a specific key for a doc getting 'undefined' [duplicate]

Is there something that I'm missing that would allow item to log as an object with a parameter, but when I try to access that parameter, it's undefined?
What I've tried so far:
console.log(item) => { title: "foo", content: "bar" } , that's fine
console.log(typeof item) => object
console.log(item.title) => "undefined"
I'll include some of the context just in case it's relevant to the problem.
var TextController = function(myCollection) {
this.myCollection = myCollection
}
TextController.prototype.list = function(req, res, next) {
this.myCollection.find({}).exec(function(err, doc) {
var set = new Set([])
doc.forEach(function(item) {
console.log(item) // Here item shows the parameter
console.log(item.title) // "undefined"
set.add(item.title)
})
res.json(set.get());
})
}
Based on suggestion I dropped debugger before this line to check what item actually is via the node repl debugger. This is what I found : http://hastebin.com/qatireweni.sm
From this I tried console.log(item._doc.title) and it works just fine.. So, this seems more like a mongoose question now than anything.
There are questions similar to this, but they seem to be related to 'this' accessing of objects or they're trying to get the object outside the scope of the function. In this case, I don't think I'm doing either of those, but inform me if I'm wrong. Thanks
Solution
You can call the toObject method in order to access the fields. For example:
var itemObject = item.toObject();
console.log(itemObject.title); // "foo"
Why
As you point out that the real fields are stored in the _doc field of the document.
But why console.log(item) => { title: "foo", content: "bar" }?
From the source code of mongoose(document.js), we can find that the toString method of Document call the toObject method. So console.log will show fields 'correctly'. The source code is shown below:
var inspect = require('util').inspect;
...
/**
* Helper for console.log
*
* #api public
*/
Document.prototype.inspect = function(options) {
var isPOJO = options &&
utils.getFunctionName(options.constructor) === 'Object';
var opts;
if (isPOJO) {
opts = options;
} else if (this.schema.options.toObject) {
opts = clone(this.schema.options.toObject);
} else {
opts = {};
}
opts.minimize = false;
opts.retainKeyOrder = true;
return this.toObject(opts);
};
/**
* Helper for console.log
*
* #api public
* #method toString
*/
Document.prototype.toString = function() {
return inspect(this.inspect());
};
Make sure that you have defined title in your schema:
var MyCollectionSchema = new mongoose.Schema({
_id: String,
title: String
});
Try performing a for in loop over item and see if you can access values.
for (var k in item) {
console.log(item[k]);
}
If it works, it would mean your keys have some non-printable characters or something like this.
From what you said in the comments, it looks like somehow item is an instance of a String primitive wrapper.
E.g.
var s = new String('test');
typeof s; //object
s instanceof String; //true
To verify this theory, try this:
eval('(' + item + ')').title;
It could also be that item is an object that has a toString method that displays what you see.
EDIT: To identify these issues quickly, you can use console.dir instead of console.log, since it display an interactive list of the object properties. You can also but a breakpoint and add a watch.
Use findOne() instead of find().
The find() method returns an array of values, even if you have only one possible result, you'll need to use item[0] to get it.
The findOne method returns one object or none, then you'll be able to access its properties with no issues.
Old question, but since I had a problem with this too, I'll answer it.
This probably happened because you're using find() instead of findOne(). So in the end, you're calling a method for an array of documents instead of a document, resulting in finding an array and not a single document. Using findOne() will let you get access the object normally.
A better way to tackle an issue like this is using doc.toObject() like this
doc.toObject({ getters: true })
other options include:
getters: apply all getters (path and virtual getters)
virtuals: apply virtual getters (can override getters option)
minimize: remove empty objects (defaults to true)
transform: a transform function to apply to the resulting document before returning
depopulate: depopulate any populated paths, replacing them with their original refs (defaults to false)
versionKey: whether to include the version key (defaults to true)
so for example you can say
Model.findOne().exec((err, doc) => {
if (!err) {
doc.toObject({ getters: true })
console.log('doc _id:', doc._id) // or title
}
})
and now it will work
You don't have whitespace or funny characters in ' title', do you? They can be defined if you've quoted identifiers into the object/map definition. For example:
var problem = {
' title': 'Foo',
'content': 'Bar'
};
That might cause console.log(item) to display similar to what you're expecting, but cause your undefined problem when you access the title property without it's preceding space.
I think using 'find' method returns an array of Documents.I tried this and I was able to print the title
for (var i = 0; i < doc.length; i++) {
console.log("iteration " + i);
console.log('ID:' + docs[i]._id);
console.log(docs[i].title);
}
If you only want to get the info without all mongoose benefits, save i.e., you can use .lean() in your query. It will get your info quicker and you'll can use it as an object directly.
https://mongoosejs.com/docs/api.html#query_Query-lean
As says in docs, this is the best to read-only scenarios.
Are you initializing your object?
function MyObject()
{
this.Title = "";
this.Content = "";
}
var myo1 = new MyObject();
If you do not initialize or have not set a title. You will get undefined.
When you make tue query, use .lean() E.g
const order = await Order.findId("84578437").lean()
find returns an array of object , so to access element use indexing, like
doc[0].title

Categories