Javascript: previous property is undefined - javascript

Why is it saying that "lbp is undefined" on the line of "creditText"? How do I refer to previous properties in a config file such as this?
var lbp = {
// Pertinant page properties, such as Author, Keywords, URL or Title
page: {
theURL: window.location.toString(),
},
// Configurable user defaults
defaults: {
creditText: lbp.page.theURL
}
}
Thanks in advance for your help

You don't. lbp won't exist in the current scope's symbol table until the object is closed out.
var lbp = {
// Pertinant page properties, such as Author, Keywords, URL or Title
page: {
theURL: window.location.toString(),
}
}; // NOW you can reference lbp by name
lbp.defaults = {
creditText: lbp.page.theURL
};

You just can't, your lbp variable is not defined since the last parenthesis of the declaration is closed.

I would guess that the contents of the object you are defining are being interpreted before the value is assigned to the lbp variable. I don't think there's any way to do what you want without assigning the values in a separate instruction.
var lbp = {};
// Pertinant page properties, such as Author, Keywords, URL or Title
lbp.page = { theURL: window.location.toString() };
// Configurable user defaults
lbp.defaults = { creditText: lbp.page.theURL };

Related

Function parameter value isn't working in object-destructuring in JS

Let's assume that I've the following object:
let filters = {
brands: { ... },
price: { ... },
sizes: { ... },
...
}
The properties of the filters object will be set by the users. Which means sometimes the filters object may contain just brands, sometimes it may contain brands & price and so on.
I've written the following function to extract a specific property from the filters object:
let extractProperty = (propertyName) => {
({ propertyName, ...rest } = filters); // <-- propertyName isn't working here
console.log(propertyName);
}
extractProperty("brands");
If I invoke the above function, the console displays undefined.
Can anyone please point me out what I'm missing here?
CodePen Link
Note:
I've already resolved this issue using lodash.omit method. But I'm still curious to know why function parameter value isn't working in object-destructuring.
Not Duplicate:
This question is about passing default value
That code is looking for a property called propertyName, literally. To use the value in propertyName as the property name, you need to use computed notation, and you'll need to specify where to put the property's value. For instance, to put it in an existing example variable:
let extractProperty = (propertyName) => {
({ [propertyName]: example, ...rest } = filters);
// ^−−−−−−−−−−−−^^^^^^^^^^
console.log(example);
};
extractProperty("brands");
Your code is written assuming that rest already exists, but I suspect you really want to declare it locally, along with the variable to receive the property value:
let extractProperty = (propertyName) => {
const { [propertyName]: example, ...rest } = filters;
console.log(example);
};
extractProperty("brands");
Without const, let (or var, but var is deprecated), unless you have rest declared in an enclosing scope, that code will either fail with a ReferenceError (in strict mode) or fall prey to what I call The Horror of Implicit Globals (in loose mode), automatically creating a global variable.
why use destructuring here when you just want to get a property?
let filters = {
brands: { value:'b' },
price: { value:'p' },
sizes: { value:'s' },
}
let extractProperty = propertyName =>
console.log(filters[propertyName])
extractProperty("brands");

Angular - Create property in new property of object

Currently, I have a select element in my html which has a ngModel to the object details:
[ngModel]="details?.publicInformation?.firstname"
However, publicInformation may not exist in that object, or if it does, maybe firstname does not exist. No matter the case, in the end, I want to create the following:
[ngModel]="details?.publicInformation?.firstname" (ngModelChange)="details['publicInformation']['firstname'] = $event"
Basically, if the select is triggered, even if neither of publicInformation nor firstname exist, I would like to create them inside details and store the value from the select.
The issue is that I am getting
Cannot set property 'firstname' of undefined
Can someone explain what I am doing wrong here and how can I achieve the result I desire?
You need to initialize details and publicInformation to empty object
public details = {publicInformation : {}};
You should do that when you load the form data.
For example, you might have something like this:
ngOnInit() {
this._someService.loadForm().then((formData: FormData) => {
this.details = formData;
});
}
Then, you could modify that to fill in the missing empty properties you need:
ngOnInit() {
this._someService.loadForm().then((formData: FormData) => {
this.details = formData || {};
if (!this.details.publicInformation) {
this.details.publicInformation = { firstname: '' };
} else if (!this.details.publicInformation.firstname) {
this.details.publicInformation.firstname = '';
}
});
}
However, it would be better to place this logic in the services, so that they are responsible for adding all the necessary empty properties to the data they load, or if you are using Redux, then it should go into the reducers.

Not able to access the value in one method in other

I would like to insert the value here as to send the JSON to backend but unable to get it.
var generateSearchObject = function() {
var searchObj = {
"fileName": change, // Here the fileName should be "Change Data"
"tabType": text.toUpperCase(),
"offset": offValue,
};
return searchObj;
};
var renderCrumbs = function(breadCrumbs, state, node) {
var change = "Change Data";
}
Please help!
First of all renderCrumbs: function(breadCrumbs, state, node) { ... } makes no sense, because you're using Object property notation with no Object to be found. If it is contained within an Object which is not visible in the code snippet then all is fine, but keep in mind that you must reference the object to call the function in the following code snippet, e.g. obj.renderCrumbs().
Secondly, and problematically, you may be tempted to use change as a global. Don't do this, globals are bad. Read more here. Further information is available elsewhere with a little googling.
The best solution that I can see is to change the functionality of renderCrumbs to
function renderCrumbs(breadCrumbs, state, node) {
return 'Change Data';
}
and then you can do
var generateSearchObject = function() {
var searchObj = {
"fileName": renderCrumbs(),
"tabType": text.toUpperCase(),
"offset": offValue,
};
return searchObj;
};

changing prototype Elements set scopes

I am wanting to attach into an Elements default property such as innerHTML as a backup under an object that way it does not pollute the Elements properties. so to help give an idea of what I am trying to achieve and what currently works:
Element.prototype._backupPropertyDescriptors = {};
Element.prototype._backupProperties = {};
Element.prototype._backupPropertyDescriptors._innerHTML = Object.getOwnPropertyDescriptor(Element.prototype,'innerHTML');
//This is what I want to do but loses Elements scope:
Object.defineProperty(Element.prototype._backupProperties,'_innerHTML',Element.prototype._backupPropertyDescriptors._innerHTML);
//the scope has changed from element to _backupProperties so this property fails.
//The working version:
Object.defineProperty(Element.prototype,'_innerHTML',Element.prototype._backupPropertyDescriptors._innerHTML);
//the reason for this is I want to be able to manipulate the get and set such as:
Object.defineProperty(Element.prototype._backupProperties,'_innerHTML',{configurable:true,enumerable:true,get:function(){console.log('getting',this.innerHTML);return this.innerHTML},set:function(val){console.log('doing something here before setting');this.innerHTML = val;}});
The problem with this is once it is inside of backup the this statement no longer holds the element...
I know one way to do this would be to use a bind or call but that still poses the how do I get the elements scope... as this during define property is the window..
So for anyone looking to try and do this, here is the solution I found :) might be something better out there, but this does work. requires only 3 properties in the prototype and then all others get put inside a single one.
Element.prototype._backupPropertyDescriptors = {};
Element.prototype._backupProperties = {};
Object.defineProperty(Element.prototype,'_backupProvider',
{
writeable:false,
enumerable:true,
configurable:true,
get:function()
{
var _backupProperties = this._backupProperties;
_backupProperties._Element = this;
return {_Element:this,_backupPropertyDescriptors:this._backupPropertyDescriptors,_backupProperties:_backupProperties};
}
});
//These first ones set up the main provider and property and descriptor holders.
//then just copy a descriptor:
Element.prototype._backupPropertyDescriptors._innerHTML = Object.getOwnPropertyDescriptor(Element.prototype,'innerHTML');
//and assign it to a new property inside the backupProperties:
Object.defineProperty(Element.prototype._backupProvider._backupProperties,'_innerHTML',
{
enumerable:true,
configurable:true,
get:function()
{
return this._Element._backupProvider._backupPropertyDescriptors._innerHTML.get.call(this._Element);
},
set:function(val)
{
console.log('setting html to: ',val);
this._Element._backupProvider._backupPropertyDescriptors._innerHTML.set.call(this._Element,val);
}
});
//and if you wanted to do something really crazy.... like overwrite the original..
Object.defineProperty(Element.prototype,'innerHTML',
{
enumerable:true,
configurable:true,
get:function()
{
return this._backupProvider._backupProperties._innerHTML;
},
set:function(val)
{
console.log('setting html to: ',val);
//do some crazy two way template binding here or something else crazy
this._backupProvider._backupProperties._innerHTML = val;
}
});
that is all.. thanks for the help #Bergi

Something is wrong in JavaScript object declaration

This code:
var doc = {
foldPrompt: function(folded) {
return folded ? "Click to unfold" : "Click to fold"
},
createFoldButtons: function() {
var prompt = foldPrompt(true); //The error is here
$("#ComparisonTable td.secrow").each(function(index, td){
$(td).prepend($('<img src="minus.gif" class="foldbtn" alt="'+prompt+'" title="'+prompt+'">'));
});
}
}
gives me an error: Undefined variable: foldPrompt
What am I doing wrong?
foldPrompt is not a variable; it's a property of doc, and you need an object reference to access properties of that object.
If someone calls doc.createFoldButtons(), then the this context variable will point at the same object that the doc variable does. So, replace foldPrompt(true) with this.foldPrompt(true).

Categories