JavaScript - Object property inconsistency - javascript

i am having a problem that i am finding difficult to find information about as i am unaware of the underlying issue.
I am trying to set a property inside an object, and when i console.log the property it gives the anticipated result but when i console.log the entire object, the property inside is different.
defaults:{
uid:undefined,
createSphere:function(uid,coordinates)
{
this.uid = uid;
console.log(this.uid);
console.log(uid);
console.log(this);
console.log(this.uid);
I run the createSphere function in a simple for loop. Here you can see how i assign the uid for the function.
for(i = 0;i<n;i++)
{
coordinates = {x:0,y:5,z:0}
coordinates.x = 0+ (40*Math.sin(Math.PI*(i/2)))
coordinates.z = 0+ (40*Math.cos(Math.PI*(i/2)))
spheres.defaults.createSphere((i+1),coordinates);
}
Here you can see the resulting log when creating the first sphere with the code from the first block. The console.logs are executed directly after eachother, so nothing is able to change the value between the logging. I wanted to upload it in an image for better clarity but i unfortunately cannot.
1
1
Object
action: function (order,impulseVector){
createSphere: function (uid,coordinates)
uid: 2
__proto__: Object
1
So the problem is; when taking the value directly from the property it differs from when using the entire object.

When you call:
spheres.defaults.createSphere((i+1),coordinates);
It isn't creating a new sphere object. Instead it is only updating "spheres.defaults.uid".
Perhaps this is closer to what you are looking for:
var Sphere = function(uid, coordinates){
this.uid = uid;
this.coordinates = coordinates;
}
var spheres = [];
spheres.push(new Sphere(1, null));
spheres.push(new Sphere(2, null));
spheres.push(new Sphere(3, null));
spheres.push(new Sphere(4, null));
console.log(spheres);

Related

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

How do I call a method to an object?

How would I call my method to my other objects?
Been having lots of trouble with everything I've tried.
I'm not that confident with this stuff, just looking on how to tell if the object is safe to drive or not.
//Create a constructor function called `Track`. It will accept two parameters - the name of the track and the maximum capacity of the track.
let track = function(name, capacity){
this.trackName=name
this.personnel=0;
this.cars=[];
this.cap=capacity;
}
//We'll need a value for the average weight of a person but this value will be the same for all tracks.
//Add a property `personWeight` on the `Track` prototype so that all instances share the same value.
track.prototype.personWeight = 200
//Create three methods on the prototype that will calculate track weight, person weight, and if its safe to drive
function personWeight(){
personnelWeight = this.personWeight * this.personnel
return personnelWeight
}
function trackWeight(){
let carsTotal = function myFunc(total, num) {
return total - num;
}
let weightTotal = (this.personnel * this.personWeight) + (this.carsTotal)
return weightTotal
}
function safeToDrive(){
if(this.trackWeight<this.capacity){
return true
}
}
//Create two track objects
let trackOne = new track ("Daytona", 25000);
trackOne.cars = [1800, 2400, 2700, 3200, 3600, 3800, 4200]
trackOne.personnel = 10
let trackTwo = new track ("Indiana",15000);
trackTwo.cars = [2000, 2300, 2800, 3000, 3500, 3700, 4000]
trackTwo.personnel = 8
//Call the `safeToDrive` method for truck objects.
With the code as it is now, you would use safeToDrive.call(trackOne). However, this is not the straight-forward way you would do it normally.
I guess what you really want is assigning these methods to the prototype:
track.prototype.safeToDrive = function () {
if(this.trackWeight<this.capacity){
return true
}
}
Then you'd call them using trackOne.safeToDrive().
The same goes for personWeight and trackWeight.
A few other observations:
Your check for this.capacity won't work because the property is actually called cap and not capacity according to what you set in your constructor.
safeToDrive currently returns true or nothing, i.e. undefined, and not true or false as you would expect.
You could fix that by either adding an else with return false or simply using return this.trackWeight < this.capacity instead of the whole if condition.
Oh, also, your personnelWeight variable is accidentally made global. Add a let before it. To avoid this in the first place, add 'use strict' at the top of your file to get warned about this issue next time.
I'm not sure what you are doing with carsTotal there though, I guess that should be a member function as well (otherwise you couldn't even call it using this.carsTotal as you do now). Plus, your indention is wrong there. (Put your file through a beautifier to see what I mean.)
Do you mean truck instead of track maybe...?

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

Array.slice() parameter is not a function

Im encountering an odd problem when going through freeCodeCamp beta.
The "purpose" of this is not modifying the original array and using functional programming techniques to modify arrays.
However I keep getting complaints about the "array" parameter is the remove function not being a valid function:
// the global variable
var bookList = [
"The Hound of the Baskervilles",
"On The Electrodynamics of Moving Bodies",
"PhilosophiƦ Naturalis Principia Mathematica",
"Disquisitiones Arithmeticae"];
/* This function should add a book to the list and return the list */
// New parameters should come before the bookName one
// Add your code below this line
function add (bookListTemp, bookName) {
let newBookArr = bookListTemp;
return newBookArr.push(bookName);
// Add your code above this line
}
/* This function should remove a book from the list and return the list */
// New parameters should come before the bookName one
// Add your code below this line
function remove (bookList,bookName) {
let newArr = bookList.slice();
if (newArr.indexOf(bookName) >= 0) {
return newArr.slice(0, 1, bookName);
// Add your code above this line
}
}
var newBookList = add(bookList, 'A Brief History of Time');
var newerBookList = remove(bookList, 'On The Electrodynamics of Moving Bodies');
var newestBookList = remove(add(bookList, 'A Brief History of Time'),
'On The Electrodynamics of Moving Bodies');
console.log(bookList);
In the remove function i've tried taking the parameter and doing array.slice() method as well as array.concat() method. Since doing let newArr = bookList doesn't actually make a new array correct? it just makes a new copy that references the original array correct?
The exact error I get is TypeError: bookList.slice is not a function
What's even weirder is Array.isArray(bookList) returns true (in the function remove. So I don't understand why it's complaining about array methods?
Your problem is Array.push
return The new length property of the object upon which the method was
called.
You should return array instead
function add (bookListTemp, bookName) {
let newBookArr = bookListTemp;
newBookArr.push(bookName);
// Add your code above this line
return newBookArr;
}
OR
Let's try Array.concat instead
function add (bookListTemp, bookName) {
let newBookArr = bookListTemp;
return newBookArr.concat(bookName);
// Add your code above this line
}
There are two ways to copy the array without mutating it. You will not be able to use the .slice() method on the bookList, because it is an argument in the function and therefore not an array. The work around is var newBookArr = Array.prototype.slice.call(bookListTemp); or [].slice.call(bookListTemp);
This allows you to perform the slice on the bookList when it is an argument. The other way I discovered, when playing around with it - var newBookArr = [].concat(bookListTemp);
When trying var newBookArr = [].push(bookListTemp); we find the original bookList pushed inside the new array. So it is a copy, but as an array within an array. the .concat() method merges the old array into the new.

Javascript ERROR, undefined, not an object

I am new in JavaScript, And I am trying to map my controller's buttons and leds for mixxx application. Is that an object, an array? var is missing.
BehringerCMDMM1.leds = [
// Master
{ "shiftButton" : 0x12 },
// Deck 1
{ "sync" : 0x30 },
// Deck 2
{ "sync" : 0x33 }
];
I have an error here,
BehringerCMDMM1.shiftButton = function (channel, control, value, status, group) {
// Note that there is no 'if (value)' here so this executes both when the shift button is pressed and when it is released.
// Therefore, BehringerCMDMM1.shift will only be true while the shift button is held down
var deck = BehringerCMDMM1.groupToDeck(group);
BehringerCMDMM1.shift = !BehringerCMDMM1.shift // '!' inverts the value of a boolean (true/false) variable
BehringerCMDMM1.setLED(BehringerCMDMM1.leds[deck]["shiftButton"], BehringerCMDMM1.shift);
}
about "shiftButton" as undefined.
also I have this function
BehringerCMDMM1.setLED = function(value, status) {
status = status ? 0x7F : 0x00;
midi.sendShortMsg(0x94, value, status);
}
This is from a javascript file I found on the internet created for a different controller. So, I am trying things to understand how can I configure mine.
BehringerCMDMM1.leds is an array of objects. Within that array, the element at index 0 is an object that has a shiftButton property. Thus, the only way to get the 0x12 value in your example is to do this:
BehringerCMDMM1.leds[0]['shiftButton']
So when this code executes...
var deck = BehringerCMDMM1.groupToDeck(group);
...the value of deck is probably something other than 0, and you're accessing one of the sync objects in the BehringerCMDMM1.leds array. For example, if the value of deck was 1, then this...
BehringerCMDMM1.leds[deck]['shiftButton']
...will be undefined because you're effectively doing this:
BehringerCMDMM1.leds[1]['shiftButton']
Ok,
I am new in JavaScript, And I am trying to map my controller's buttons and leds for mixxx application. Is that an object, an array?
You have a array of objects.
var is missing.
You should test what is inside yout deck variable. Try this:
console.log(deck);
if (deck in BehringerCMDMM1.leds) {
BehringerCMDMM1.setLED(BehringerCMDMM1.leds[deck]["shiftButton"], BehringerCMDMM1.shift);
} else {
console.log("Index: "+deck+" doesn't exist");
}

Categories