Javascript Cannot read property 'x' of undefined - javascript

I don't understand the error in the code below. I tried calling another class's function from another class. But I gives the error error: Uncaught TypeError: Cannot read property '_name' of undefined
class Person {
constructor() {
this._name = "Name-Person";
}
getName() {
return this._name;
}
}
class Test1 {
constructor() {
let p = new Person();
new Test2(p.getName);
}
}
class Test2 {
constructor(getName) {
console.log(getName());
}
}
new Test1()
How can I fix the error?

When passing the function to Test2 you need to bind p to the function
new Test2(p.getName.bind(p));
class Person {
constructor() {
this._name = "Name-Person";
}
getName() {
return this._name;
}
}
class Test1 {
constructor() {
let p = new Person();
new Test2(p.getName.bind(p));
}
}
class Test2 {
constructor(getName) {
console.log(getName());
}
}
new Test1()

you can use public class field:
class Person {
constructor() {
this._name = "Name-Person";
}
getName = () => {
return this._name;
}
}
class Test1 {
constructor() {
let p = new Person();
new Test2(p.getName);
}
}
class Test2 {
constructor(getName) {
console.log(getName());
}
}
new Test1()

Because you are passing the function and not the entire class or its value, _name does not exist in the context of the Test2 constructor.
A couple of simple solutions is to either pass in the result of getName() to the constructor, or the entire class of Person.
new Test2(p); // And in Test2 use p.getName()
// or
new Test2(p.getName()); // And in Test2 use the result

Related

Javascript arrow func in subclass cannot be found by super class

What I would like to achieve:
Essentially, I would like my subclass to have a lexically-bound this function. However, I would like the super class to check that the subclass has an instantiation of this lexically-bound function.
This is how I would prefer to write the code, but it doesn't work:
class Animal {
constructor(type) {
this.animalType = type;
if (!(this.bark instanceof Function)) {
throw new Error('Found no bark');
}
}
}
class Dog extends Animal {
bark = () => {
console.log('woof');
}
}
let max = new Dog('dog')
max.bark();
Yet this works:
class Animal {
constructor(type) {
this.animalType = type;
if (!(this.bark instanceof Function)) {
throw new Error('Found no bark');
}
}
}
class Dog extends Animal {}
Dog.prototype.bark = () => {
console.log('woof');
}
let max = new Dog('dog')
max.bark();
and this works:
class Animal {
constructor(type) {
this.animalType = type;
if (!(this.bark instanceof Function)) {
throw new Error('Found no bark');
}
}
bark = () => {
console.log('woof');
}
}
class Dog extends Animal {}
let max = new Dog('dog')
max.bark();
Could someone please explain why my first example is failing. It seems to me that bark() isn't in the prototype chain somehow but I'm not sure why.

How to call class this in object?

I have a class testClass and in testClass there is a getter called testGetter and a public object called testObject. In testObject I have a function nestedFunction which attempts to call testGetter but cannot as the scope for this is in the testObject. How could I call the getter (or any function) from the object?
class testClass {
get testGetter() {
return "test"
}
testObject = {
nestedFunction : function(){
console.log(this)
return this.testGetter
}
}
constructor()
{
console.log(this.testObject.nestedFunction())
}
}
new testClass()
Output:
{ nestedFunction: [Function: nestedFunction] }
undefined
Classic use case of arrow functions.
class testClass {
get testGetter() {
return "test"
}
testObject = {
nestedFunction: () => {
console.log(this)
return this.testGetter
}
}
constructor() {
console.log(this.testObject.nestedFunction())
}
}
new testClass()

Field initialization in a sub-class happens after constructor finishes in the parent class, in javascript. Is this by design?

It is easier to show than to describe it. Here is the code
let ns = {};
ns.A = class {
constructor() {
this.Virtual();
}
Virtual() {
}
};
ns.B = class extends ns.A {
constructor() {
super();
alert(this.Field);
}
Field = 0;
Virtual() {
this.Field = 123;
}
}
The alert() says that this.Field equals 0. That is, field initialization in the B class is performed after the A constructor finishes. Is this "by design" in Javascript?
If I put the Field in the prototype of the B class, then everything works OK, just like in any other language. For example
let ns = {};
ns.A = class {
constructor() {
this.Virtual();
}
Virtual() {
}
};
ns.B = class extends ns.A {
constructor() {
super();
alert(this.Field);
}
//Field = 0;
Virtual() {
this.Field = 123;
}
}
ns.B.prototype.Field;
Sorry to bother you here with this, but I don't know where is the right place to report this issue.
From https://github.com/tc39/proposal-class-fields#execution-of-initializer-expressions:
When field initializers are evaluated...
Base class: At the beginning of the constructor execution...
Derived class: Right after super() returns...
Illustration:
class A {
constructor() {
console.log('A constructor start');
this.Virtual();
console.log('A constructor end');
}
Field = (() => { console.log('A field init'); return 1})()
Virtual() {
}
};
class B extends A {
constructor() {
console.log('B constructor start')
super();
console.log('B constructor end')
}
Field = (() => { console.log('B field init'); return 2})()
Virtual() {
console.log('B virtual')
this.Field = 123;
}
};
console.log(new B())
That is, in your code, Field = 0 happens after this.Field = 123, thus overwriting it. The order of declarations doesn't matter.
If you have issues with this behaviour and wish to discuss it, https://github.com/tc39/proposal-class-fields/issues would be the right place.

Can we get the attributes of a javascript class?

I have this javascript class :
class UserDTO {
constructor(props) {
this.username = props.username;
this.birthday = props.birthday;
}
}
and I have a class Utils that convert an Entity to DTO:
class Utils {
convertEntityToDTO (entityObj, DTOClass) {
// entityObj is an instance of a Entity,
// DTOClass is a class not an instance
let objDTO = new DTOClass();
Object.getOwnPropertyNames(entityObj)
.filter(prop => DTOClass.hasOwnProperty(prop))
.forEach(prop => {
objDTO[prop] = entityObj[prop];
});
}
}
this doesn't work a class ; hasOwnProperty just work with object; is a way to verify if a property is an attribute of a class or not ? or I have to create an instance to test ?
You can use hasOwnProperty on the instance and getOwnPropertyNames :
class A {
constructor() {
this.ex = 'TEST';
}
}
var a = new A();
console.log(a.hasOwnProperty('ex'));
console.log(Object.getOwnPropertyNames(a));
If instead you want the methods, you need to get the prototype:
class B {
constructor() {}
exMethod() {
console.log('test');
}
}
var b = new B();
console.log(Object.getPrototypeOf(b).hasOwnProperty('exMethod'));
console.log(Object.getOwnPropertyNames(Object.getPrototypeOf(b)));

es6 class pass this to a static class functions

i have this class
import { ObjectUtilities } from '~/utils/';
class Object{
constructor(object) {
Object.assign(this, { ...object });
}
utils = ObjectUtilities;
}
and this class with the statis method also (class contains many static methods)
class ObjectUtilities {
static getKey(object){
return object.key;
}
}
and i want to know if its possible to share the "this" from the Object class
to the static method "getKey(object)"
want to do it as:
let x = new Object(object);
x.utils.getkey(this);
(ObjectUtilities as many static funcs i dont want to do it for each of them)
thanks for helping me out...
You can add a constructor to the ObjectUtilities class where you bind the given context to the getKey function:
class ObjectUtilities {
constructor(_this) {
this.getKey = this.getKey.bind(_this);
}
getKey() {
return this.key;
}
}
class MyObject {
constructor(object) {
Object.assign(this, { ...object });
this.utils = new ObjectUtilities(this);
}
}
const objectFoo = { key: 'foo' };
const objectBar = { key: 'bar' };
let x = new MyObject(objectFoo);
let y = new MyObject(objectBar);
console.log(x.utils.getKey(), y.utils.getKey());

Categories

Resources