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
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.
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()
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.
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)));
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());