Accessing properties of "this" during bind - javascript

Learning partial functions and got stuck with this query -
In the code snippet below, I create an admin object that re-uses a generic sendMail function by customizing it with a bind (partial function). However when this runs the from parameter to sendMail is always received as undefined.
If I replace sendMail: sendMail.bind(this, this.role) with sendMail: sendMail.bind(this, 'admin') it works fine.
How do I get the sendMail binding inside the admin object to pass variables defined inside the admin object?
function sendMail(from, to, content) {
console.log(`Sending email from ${from} to ${to} with message as ${content}`);
}
let admin = {
role: `admin`,
sendMail: sendMail.bind(this, this.role),
}
admin.sendMail(`all`, `Reboot in 15 mins`);

To do what you want, you'll have to separate out the assignment to the "sendMail" property:
let admin = {
role: `admin`,
};
admin.sendMail = sendMail.bind(admin, admin.role);
There's no way to reference the "under construction" object in the property value expressions in an object initializer. While that's being evaluated, there is no object yet (at least conceptually).

Related

Function's parameter used inside a previously defined variable (String) returns undefined

trying to declare a variable for an API call (There are different website versions for API calls so want to have it dynamically interchangeable while having clean code).
It goes like this:
const getAbi = async (addy) => {
const url = `https://api.arbiscan.io/api?module=contract&action=getabi&address=${addy}&apikey=${arbiscanKey}`;
const abi = await axios.get(url);
console.log(abi);
return abi;
};
Now, its supposed to take the function parameter (Named "addy") and input it inside the API call link. For some reason, it does not do that. It gives me error:
const arbiscanGetAbi = `https://api.arbiscan.io/api?module=contract&action=getabi&address=${addy}&apikey=${arbiscanKey}`;
^
ReferenceError: addy is not defined
Not sure how to get it to realise i am referring to "addy" from the function parameter, thanks!

Why can't I access my custom string prototype from an object method?

I have a custom string prototype that does some actions to a string;
String.prototype.norm_to_ascii=function(){return unescape(encodeURIComponent(this))};
In my example, the string that I want to apply the prototype to is a global object property that lives outside of the SampleObject object. In my actual code it would be referenced like this;
var userObject = {
name: "SomeName",
id: "SomeID"
}
It works everywhere in my project (other js files) except for within a particular Object method;
var SampleObject = { //This is in it's own js file called sampleobject.js
test: 0,
doStringThings {
let something = userObject.id.norm_to_ascii() //RETURNS userObject.id.norm_to_ascii is not a function
}
}
So in the SampleObject, I need to use the id, for example, but I need to do some basic decoding of the id value that is in the userObject which is what the string prototype does.
I can use this string prototype elsewhere. This is in a chrome extension so I have defined the prototype in the service worker and it can be used in the popup and content pages as well as the service worker so it must have to do with the object method but I can't figure out why?
Can anyone offer any suggestions to expose that prototype to the object method without having to redefine it?
EDIT
I should have been more clear in my explanation. I updated my example above.
You forget about this
this.otherTestValue.norm_to_ascii()
After seeing the updated question my conclusion is that you are defining the norm_to_ascii function after you run it.
Changing the order of the imports should fix the problem. Can you show us the structure of the project and where are you importing the file with that prototype?

Typescript - how to pass MyClass.new as method reference?

I have an array of objects, where each object looks like this:
{ id: 'string', name: 'string' }
Given this class:
class User {
constructor(obj: Record<string, string>) {
Object.assign(this, obj);
}
id: string;
name: string;
}
I want to use Array.map() to create an array of User:
const users = userObjects.map(o => new User(o));
The above works, but feels wrong: is there a way to pass a reference to the User's new and avoid the arrow function?
I'm not really sure if the answer is different between Javascript and Typescript (I suspect it isn't), but FWIW I'm coding in Typescript.
No, there isn't (other than a utility function you might write to do that arrow function for you, but that's just an abstraction on what you already have). The issue is that there is no new method (like Java's User::new), there is only the User function itself, and whether it creates a User instance or throws an error (in modern environments) depends on how you call it. If you call it via new (or a similar mechanism like Reflect.construct), it creates a User instance. If you call it directly, it throws an error (in ES2015+; if you're compiling down to ES5, it won't, but it won't work properly either).
What you have (the wrapper arrow function) is a perfectly good way to do it (and probably what I'd do).
If you need to do this in several places, you could put a static method on User:
class User {
// ...
static create(...args) {
return new User(...args);
}
}
// ...
const users = userObjects.map(User.create);
(Note that create won't work properly in User subclasses [depending on your definition of "properly"], it always creates a User instance, even if called as UserSubclass.create(/*...*/). Normally you could use this instead of User [new this(...args)], which while it looks odd works provided the call sets this correctly [as User.create(/*...*/) or UserSubclass.create(/*...*/) would], but map won't set this correctly so that wouldn't work unless you bind create or remember to pass the second argument to map [.map(User.create, User)], which takes us back to: a wrapper arrow function probably makes more sense.)

Typescript "Cannot find name <fieldname>"

I am pretty new to TypeScript.
I have created a class with some private fields. When I attempt to assign a value to one of the fields in an anonymous callback function within a class method I get the error ...
(TS) Cannot Find the name '_tokens'
I suspect that there is a scoping issue but from my understanding of JavaScript this should not be a problem. I am not sure how to fix it. Any ideas?
See .. "populateTokens()" method for error.
class SingleSignOn {
private _appTokensURL: string = "/api/IFSessionCache/Auth/";
private _tokens: string[];
/**
* Initialize an instance of the SingleSignOn class to manage the permissions for the
* application associated with the application.
*/
constructor() {
this.populateTokens();
};
/**
* Gets a list of permissions tokens associated with the currently logged on user for
* the application.
*/
private getApplicationTokens(): Q.IPromise<{}> {
return Unique.AJAX.Get(this._appTokensURL, null, ENUMS.AjaxContentTypes.JSON);
};
private populateTokens () {
this.getApplicationTokens().then(
function (data) {
_tokens = <string[]>data; // (TS) Cannot find name "_tokens"
});
};
};
You are using the wrong syntax:
this.getApplicationTokens().then(
(data) => {
this._tokens = <string[]>data; // note: turned into an arrow function and added the `this` keyword
});
note if you kept using function() ... syntax the this keyword will not point to the class instance but to the callee
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
greetings
Properties of a class do not have a scope, they live as long as the object they belong to live and everything that can access the object can access all its properties too. However properties always have to be accessed on their object, e.g. something._tokens or this._tokens inside methods. Also you have to make sure that this is what you think it is, in your case you have to use an arrow function to access the correct this inside a callback:
this.getApplicationTokens().then( (data) => {
this._tokens = data as string[];
});
I think you're just missing the this keyword from _tokens:
this._tokens = <string[]>data;

JavaScript Revealing Module pattern private variable state

I have recently started working on a JavaScript project and coming from Java world things seem, not surprisingly, weird at times.
I was implementing a simple module (Using revealing module pattern, afaik) which would provide config based on initialisation but notice that after a "local" variable domain is assigned in init() function its value differs depending whether it is accessed via a "getter" function getDomain() or directly via domain variable as exposed via modules "public" API.
See the following stripped down code which demonstrates the issue.
var ConfigManager = (function() {
var privateDomain = 'default';
function init(dom) {
privateDomain = dom;
}
function getDomain() {
return privateDomain;
}
return {
init: init,
domain: privateDomain,
getDomain: getDomain
};
})();
console.log(ConfigManager.domain); // Prints 'default'
console.log(ConfigManager.getDomain()); // Prints 'default'
ConfigManager.init('new domain');
console.log(ConfigManager.domain); // Prints 'default' <-- What??
console.log(ConfigManager.getDomain()); // Prints 'new domain'
At this point I am very confused how a variable returned from a getter function can have a different value when it is accessed directly?
Than you in advance!
Since privateDomain is a String, you're not copying / returning the reference, but the value.
Therefore when you're changing the domain using the init function, it just updates privateDomain, since domain has no link to it other than being a copy.
Hope it helps! :)
It's because when domain is returned, it's value is still "default". It's how Javascript works, more info here: Javascript by reference vs. by value
But when you use the function "getDomain" you will get the updated value.
Also have a look at the get/set syntax: Getter

Categories

Resources