njs icon indicating copy to clipboard operation
njs copied to clipboard

classes support.

Open xeioex opened this issue 6 years ago • 6 comments

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
  // Getter
  get area() {
    return this.calcArea();
  }
  // Method
  calcArea() {
    return this.height * this.width;
  }

 static distance(a, b) {
    const dx = a.x - b.x;
    const dy = a.y - b.y;

    return Math.hypot(dx, dy);
  }
}

@drsm can you confirm that it simply can be transformed to

 function Rectangle(height, width) {
    this.height = height;
    this.width = width;
  }

Object.defineProperty(Rectangle.prototype, 'area', {get: ()=> this.calcArea()})
Rectangle.prototype.calcArea = ()=> {this.height * this.width};

Rectangle.distance = (a, b) {
    const dx = a.x - b.x;
    const dy = a.y - b.y;

    return Math.hypot(dx, dy);
}

?

xeioex avatar Nov 28 '19 13:11 xeioex

@xeioex

Fixed version (arrows cannot be used, because of lexical this):

function Rectangle(height, width) {
    this.height = height;
    this.width = width;
}

Object.defineProperty(Rectangle.prototype, 'area', { 
                        get: function() { return this.calcArea(); },
                        configurable: true });


Rectangle.prototype.calcArea = function() { return this.height * this.width; };


Rectangle.distance = function(a, b) {
    const dx = a.x - b.x;
    const dy = a.y - b.y;

    return Math.hypot(dx, dy);
};

with some exceptions:

> new Rectangle.distance()
Thrown:
TypeError: Rectangle.distance is not a constructor
> new (new Rectangle(111,222)).calcArea
Thrown:
TypeError: (intermediate value).calcArea is not a constructor
> new Object.getOwnPropertyDescriptors(Rectangle.prototype).area.get
Thrown:
TypeError: Object.getOwnPropertyDescriptors is not a constructor

drsm avatar Nov 28 '19 14:11 drsm

Also, we need a

> class X { constructor() { console.log('test'); } }
undefined
> X()
Thrown:
TypeError: Class constructor X cannot be invoked without 'new'
> new X()
test
X {}

drsm avatar Dec 03 '19 14:12 drsm

@xeioex @drsm The following code passed in chrome and quickjs.

class A {
    i = 2; // runs before constructor
    constructor(name) {
        print(this.i);
        this.name = name;
    }
    test() {
        print(this.name);
    }
    ;
}

var a = new A("a");
a.test();

It seems assignment statement is allowed. But I can't find the spec in ecma262.

BTW, this feature is good to introduce, it simplify the way of OO that we don't need to use Class.prototype.prop = .... (I'm curious if js developers like it?) We can implement the simple version first that does not include extend, super, even static.

hongzhidao avatar Jun 23 '20 08:06 hongzhidao

@xeioex @lexborisov @drsm Take a look at the example of closure. Just a reminder.

foo.js

var a = 1;
function b() {
    a = 2;
}
export {a, b}

test.js

import {a, b} from 'foo.js';
print(a);
b();
print(a);

It seems imported variables a and b are reference. In njs, closure variables are processed as normal variables, they're stored in different scope. In qjs, closure variables are processed as reference. The variable reference is also applied in module imported/exported names like the example.

hongzhidao avatar Jun 23 '20 09:06 hongzhidao

@hongzhidao

Hi!

It seems assignment statement is allowed. But I can't find the spec in ecma262.

It's an instance field: Stage 3 Draft

drsm avatar Jun 23 '20 13:06 drsm

@hongzhidao

It seems imported variables a and b are reference.

Yes. Imports are not variables at all, they are just named references to the other module memory substituted at compile time. So, there is no way to do import {a, b} from 'foo.js' in REPL, in general.

drsm avatar Jun 23 '20 13:06 drsm