How to get list of class methods in JavaScript? - javascript

I have the following class in JavaScript.
class User {
get(id) {
return {id};
}
}
I'm trying to figure out how to get a list of the methods from an instance.
const user = new User();
Basically this means, I'm trying to find code where the input is user and the output is ["get"].
I have tried the following, but they all print [] (which is not what I expect).
console.log(Object.keys(user)); // []
console.log(Object.keys(Object.getPrototypeOf(user))); // []
console.log(Object.getOwnPropertyNames(user)); // []
I know user.get exists because the following line works and prints [Function: get]:
console.log(user.get); // [Function: get]
Obviously this works for properties, and prototype functions. But I'm trying to figure out how to get this to work with class methods. So that means that any solution can not change the User class.
How can I achieve this?

You need to get the prototype of the instance first:
console.log(Object.getOwnPropertyNames(Object.getPrototypeOf(u)));
prints
["constructor", "get"]

Related

Which file called a class

I want to know which file called the class:
database.ts
class Database {
constructor() {
console.log(`This class was called by ${super()}`);
}
}
server.ts
import Database from 'database.ts';
new Database(); // The constructor would print "This class was called by server.ts"
Of course the way I presented by using "super()" doesn't work, but which way does ? I could not find an answer for this question. Is it possible to do such thing ?
Log the superclass name
You can log the name of the superclass like this:
Object.getPrototypeOf(Object.getPrototypeOf(foo)).constructor.name;
see https://stackoverflow.com/a/44251889/675721
Logging the superclass name will not show you which file called instantiated your class, however.
Log the calling file
To do this you should create an log an error.
class Database {
constructor() {
const a = new Error();
console.log(a);
}
}
This will give you a stack trace with all of the file names.
Error
at REPL39:1:23
at Script.runInThisContext (vm.js:132:18)
at REPLServer.defaultEval (repl.js:479:29)
at bound (domain.js:430:14)
at REPLServer.runBound [as eval] (domain.js:443:12)
at REPLServer.onLine (repl.js:809:10)
at REPLServer.emit (events.js:326:22)
at REPLServer.EventEmitter.emit (domain.js:486:12)
at REPLServer.Interface._onLine (readline.js:337:10)
at REPLServer.Interface._line (readline.js:666:8)
Debugger
Neither of these is really the best approach - you should use a debugger to set a breakpoint when the class is instantiated or when the database isn't working and look around to see what is different.
It isn't strictly a typescript question. There is no simple way to do this but you can hack around with the stack trace I believe. On that way you can find out where your class has been instantiated even if your application is packaged and the file name information is lost. The stack trace can be obtained by processing the callee property of the constructor's arguments. E.g. see this question for a possible solution. I.e.
function stacktrace() {
function st2(f) {
return !f ? [] :
st2(f.caller).concat([f.toString().split('(')[0].substring(9) + '(' + f.arguments.join(',') + ')']);
}
return st2(arguments.callee.caller);
}
But you can make your own version of this function what returns the stack as an array. I assume from the comments on the question you would like to store the caller in the class and log it in case of error so storing the trace as an object might suit your needs better.
Then just call this function from the Database class constructor.
Of course I could add a parameter to the constructor. But is there another way ?
class Database() {
constructor(fileLocation: string) {
console.log(`This file was called by ${fileLocation}`);
}
}

Property of class exists but undefined

I have a function to collect data when I click on the row, I keep the data in the object. When I log the object, it returns object type. But when I try to log its property, it is undefined.
branchToDivision: BranchDto;
onSelect(record: BranchDto) {
this.branchToDivision = record;
console.log(this.branchToDivision);
console.log(this.branchToDivision.brancH_CODE);
}
console screen
GetBranchForView {branch: BranchDto}
undefined
I don't know what problem is.
Here is Object definition
Console display
Does this work for you?
console.log(this.branchToDivision.branch.brancH_CODE);
I find the answer. Each line on the datatable is represented by a class called GetBranchForView. So when I try to catch the event I have to pass a param with type GetBranchForView. This works for me.
onSelect(record: GetBranchForView) {
this.item = record;
this.branchToDivision = record.branch;
}

Chrome Debugger: What's a "PropertyBag" object?

Using the Chrome Debugger in the following way:
console.dir(element);
On the console the data-type is called a "PropertyBag". I would have expected "Object".
What special kind of object is a "PropertyBag"?
I have never read that term in JavaScript before ...
As you said in the above comments, you are using some code written by somebody else (or a custom framework) and element is just an instance of a custom class. For example, the PropertyBag class exists in cesiumjs.
If the object is an instance of a class (not a simple object, really a class with a constructor), if you use console.log on that item, you'll get the class name in the console (at least in Chrome) and a little arrow to expand it. You can copy/paste the following code in the console to test the behavior.
class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
let user = new User("John");
console.log(user);
Cheers!

ReactJS: Can't ready property xxx of undefined

I'm aware that there are a lot of questions asking the same thing but none of those answers seem to work for my specific case and I have been at this for hours and still can't figure it out. I'm following a ReactJs tutorial for a WeatherApp.I get back an object from an API call that looks like this:
{
current: {}
forecast:
forecastday:[ //
0: {...}
1: {...}
2: {...}
3: {...}
4: {...}
] //Array of five objects
location: {}
} //this object is part of a bigger response object
When I console.log(objectName.forecast.forecastday) I get back the array, which means it's actually there.
But when I try
var forecastData = props.forecast.data;
var days = forecastData.forecast.forecastday.map(function (day) {
//do something
});
it gives me back the error Uncaught TypeError: Cannot read property 'forecast' of undefined. I have also tried logging forecastData and it comes back just fine. forecast is clearly there so unless I'm missing something extremely obvious, I don't know what's going on.
Thanks.
You are most likely not taking into account the initial state, where props.forecast.data may be undefined at the initial mount of the component since your API call is happening asynchronously.
You can do something like this:
var days = forecastData
? forecastData.forecast.forecastday.map(function (day) {
//do something
})
: null;
This will first check to see if forecastData exists, and if it does exist, it will map over the forecastData.forecast.forecastday array.
If forecastData does not exist, then that variable will render null.

Avoid declaring large object in getDefaultProps prior to an event

The title might not be the best way to describe the problem, but I was wondering if there was a better practice to declaring an object in getDefaultProps?
In my render method I call several keys from from a prop/state that get updated on a click event i.e. this.props.player.name. The problem is that on page load this.props.player is blank and calling .name errors out. I know I can do something like ...
getDefaultProps: function() {
return {
player: {
name: null,
team: null
position: null
}
};
}
but it doesn't feel right. I was hoping there might be something similar to how Ruby does .try() where it won't try to call a method on a undefined prop.
The problem is specifically that this.props.player is undefined, if you define an empty object it will prevent the error from occurring. It's not bad practice to stub out the keys you're anticipating, but setting the default value to {} will be enough to prevent it from throwing.
You can create your data from ImmutableJS. Then you can get any part of your data like this:
this.state.getIn(['player', 'name', ...])
or
this.state.get('player')
This will not throw error even player is not defined or other, it will return undefined (or null) I don't remember
The update and updateIn work the same
see the doc here
I'd like to add this vanilla JS solution too - var x = (user || {}).name;
Source

Categories

Resources