Njs: classes support.

Created on 28 Nov 2019  路  6Comments  路  Source: nginx/njs

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);
}

?

ES6 feature help wanted

All 6 comments

@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

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 {}

@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.

@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

Hi!

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

It's an instance field: Stage 3 Draft

@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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

yvmarques picture yvmarques  路  3Comments

axipo picture axipo  路  3Comments

drsm picture drsm  路  4Comments

reyou picture reyou  路  5Comments

an0ma1ia picture an0ma1ia  路  4Comments