I have these 3 files:
bar.js
class Bar {
test(p) {
console.log(p);
}
}
module.exports = Bar;
baz.js
const Bar = require('./bar');
class Baz extends Bar {
test2(p) {
this.test(p);
}
}
module.exports = Baz;
foo.js
const Baz = require('./baz');
const { test2 } = new Baz();
test2('test');
When I passed 'test' to new Baz.test2(), I expected it to pass it to it's superclass (this.test(p)) where it should log 'test'. However, it threw the error:
this.test(p);
^
TypeError: Cannot read property 'test' of undefined
What am I doing wrong? Why is this undefined, I thought it should reference the class itself?
test2 is used apart from it's original context (Bar instance) and should be bound to proper this.
It's impossible to say from the name if it's expected to be a callback by design. In case it is, it can be bound in constructor:
class Bar {
constructor () {
this.test = this.test.bind(this);
}
...
}
Otherwise it can be bound in-place:
const test2 = new Baz().test2.bind(this);
test2('test');
Or just not be used separately from the context:
const baz = new Baz()
baz.test2('test');
Related
I have this:
export class QueueEntity<T> implements HasInternalQueue<T> {
opts: { // <--- inline type here
foo: boolean
}
constructor(v: typeof this.opts) { // this doesn't quite work
this.opts = v
}
}
is there a way to reference the inline type or is this not possible?
Since there is no way to define a type inside the class directly (An open issue in the TS repo). I think you can use the class name to reference this:
export class QueueEntity<T> {
opts: { // <--- inline type here
foo: boolean
}
constructor(v: QueueEntity<T>['opts']) { // <-- should work now
this.opts = v
}
}
const obj = new QueueEntity({ foo : false });
const obj2 = new QueueEntity({ foo2 : false });
const obj3 = new QueueEntity();
Playground
I am using node 12 in my project. Back to 2 years ago, I remember I need to bind method for class instance method like below:
class Logger {
constructor () {
this.printName = this.printName.bind(this);
}
printName (name = 'there') {
this.print(`Hello ${name}`);
}
print (text) {
console.log(text);
}
}
But recently I found I don't need to call bind in the constructor. Does the latest node version support auto-bind already?
The behavior hasn't changed. The situation in which you need to .bind is when the instance's printName method would otherwise get called without a calling context. For example:
class Logger {
printName (name = 'there') {
this.print(`Hello ${name}`);
}
print (text) {
console.log(text);
}
}
const l = new Logger();
const fn = l.printName;
fn();
or with, instead of fn:
setTimeout(l.printName)
or with:
button.addEventListener('click', l.printName)`
In all of these situations, an error will be thrown if you don't use .bind, because the method gets called without a calling context - but the calling context of the Logger instance is needed for this to refer to the instance, so that this.print refers to the print method of the instance.
This sort of thing has always been true in Javascript. Nothing's changed in the past few years, except that it's now a bit easier to bind - you can use new class field syntax instead of having a constructor:
class Logger {
printName = (name = 'there') => {
this.print(`Hello ${name}`);
}
print (text) {
console.log(text);
}
}
const l = new Logger();
const fn = l.printName;
fn();
Suppose I have a class A with the following method:
foo(x, options) {
const limit = options && options.limit ? options.limit : undefined;
const select = options && options.select ? options.select : {};
const paginate = options && options.paginate ? options.paginate : {};
const sort = options && options.sort ? options.sort : {};
const count = options && options.count;
const args = deepMerge({ x }, paginate);
return count ? this.model.find(args).count()
: this.model.find(args).limit(limit).select(select).sort(sort);
}
Then I create a class B that extends A. There I have a method bar that is almost identical to method foo.
Is it possible to extend method bar to have limit,select,paginate,sort and count? I don't want to override foo method in B class, so I need it to have a distinct name
You can use the this.foo() if you haven't overwritten the foo() method on B, else, you can use the super keyword which refers to the parent class instance super.foo() and it works in both cases (overwritten or not).
class B extends A {
bar(){
super.foo();
}
}
Disclaimer: I'm assuming that: by class, you mean ES6 classes not ES5 prior prototypes.
Working example:
class A {
foo() {
return 'value of A';
}
}
class B extends A {
// case you override the method
// super.foo() still points to the
// original A.foo() but you don't
// have to do this, it's just an
// example
foo() {
return 'value of B';
}
bar() {
const valueOfA = super.foo();
return valueOfA;
}
}
const b = new B();
console.log(b.bar())
I am trying to call a method inside another and I am getting a MissingMethodException. My code looks something like this:
class Foo {
static def bar {
//do stuff
return something
}
static def baz { myVar=false ->
def something = bar()
//do stuff w/something
}
}
Foo.baz()
and this is the error I get: Caught: groovy.lang.MissingMethodException: No signature of method: Foo$__clinit__closure6.bar() is applicable for argument types: () values: []
I found that I can fix this error if I define baz like this instead:
static def baz { myVar=false ->
def something = this.bar()
//do stuff w/something
}
but if I do that, my IDE tells me that this is an Unnecessary qualified reference.
What's going on here?
That syntax in your snippet is wrong. Either you wanted static def bar = {} or static def bar() {}.
If you wanted bar to be a method, then there is no error:
class Foo {
static bar() { 'something' }
static baz = { myVar=false ->
def something = bar()
return something + "!"
}
}
assert Foo.baz() == "something!"
If you want bar to be a closure (i.e. bar = {}) then to invoke bar from baz you need to put the class name first:
class Foo {
static bar = { 'something' }
static baz = { myVar=false ->
def something = Foo.bar()
return something + "!"
}
}
assert Foo.baz() == "something!"
This question already has answers here:
ES6 arrow function lexical this in V8
(2 answers)
Closed 7 years ago.
I'm surprised this doesn't work. (I'm running iojs 2.3.0 with the --harmony_arrow_functions flag.)
class Foo {
constructor() { this.foo = "foo"; }
sayHi() { return (() => this.foo)(); }
}
f = new Foo();
f.sayHi // Cannot read property 'foo' of undefined.
I would have expected the arrow function to pick up the right value for this. Am I missing something?
I don't know the problem, but my version works fine for me:
class Foo {
constructor() {
this.foo = "foo";
}
sayHi() {
return (() => console.log(this.foo))();
}
}
const f = new Foo();
f.sayHi();
BTW: I am using babel
Your IIFE is creating a new scope. this is then referring to the scope of the IIFE where this.foo is undefined.
The way you'd get around this is by binding your IIFE.
class Foo {
constructor() {
this.foo = 'foo';
}
sayHi() {
return (() => {
return this.foo;
}.bind(this))();
}
}
let f = new Foo();
console.log(f.sayHi()); //foo