This question already has answers here:
Declaring static constants in ES6 classes?
(19 answers)
Closed 7 years ago.
Is there a way I can define a const in the constructor of a class?
I tried this:
class Foo {
constructor () {
const bar = 42;
}
getBar = () => {
return this.bar;
}
}
But
var a = new Foo();
console.log ( a.getBar() );
returns undefined.
You use static read-only properties to declare constant values that are scoped to a class.
class Foo {
static get BAR() {
return 42;
}
}
console.log(Foo.BAR); // print 42.
Foo.BAR = 43; // triggers an error
Simply defining a constant in the constructor won't attach it to the instance, you have to set it using this. I'm guessing you want immutability, so you can use getters:
class Foo {
constructor () {
this._bar = 42;
}
get bar() {
return this._bar;
}
}
Then you can use it like you normally would:
const foo = new Foo();
console.log(foo.bar) // 42
foo.bar = 15;
console.log(foo.bar) // still 42
This will not throw an error when trying to change bar. You could raise an error in a setter if you want:
class Foo {
constructor () {
this._bar = 42;
}
get bar() {
return this._bar;
}
set bar(value) {
throw new Error('bar is immutable.');
}
}
The problem is with "bar" scoping - it scoped to constructor:
'use strict';
class Foo {
constructor () {
const bar = 42;
this.bar = bar; // scoping to the class
}
getBar () {
return this.bar;
}
}
var a = new Foo();
console.log ( a.getBar() );
Related
This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed last year.
What's the difference between a variable:
const a = console.log;
a('HELLO');
and an arrow function:
const a = (str) => console.log(str);
a('HELLO');
And why in case of using a class member it doesn't work
class MyClass {
foo;
str;
constructor(str, foo) {
this.str = str;
this.foo = foo;
}
getFoo() {
return this.foo(this.str);
}
}
const instance = new MyClass(123, console.log);
// works
const f = (str) => {
instance.getFoo(str);
}
f('Hello');
// doesn't works -> this.str is undefined
const f = instance.getFoo;
f('Hello');
variable = classInstance.function actually just returns a reference to the function in the prototype, not linked to the actual instance, the this.* looks for global variables.
If you want to be able to have another variable store the function with the context of that variable, you need to use .bind(...) or similar
You can also give it a custom context
class MyClass {
foo;
str;
constructor(str, foo) {
this.str = str;
this.foo = foo;
}
getFoo() {
return this.foo(this.str);
}
}
const instance = new MyClass(123, console.log);
// give it the context object
const f = instance.getFoo.bind(instance);
f('Hello');
const f2 = instance.getFoo.bind({ str: "abcd", foo: console.log});
f2("...");
// Equal to the prototype
console.log(instance.getFoo == MyClass.prototype.getFoo);
This question already has answers here:
ES6 arrow function and lexical scope inside a function [duplicate]
(2 answers)
Closed 2 years ago.
I am trying to understand the scope of arrow functions. I implemented a small program in Angular, but I got confused a bit. In the code below I don't really understand why this binds to the TestComponent
export class TestComponent {
a: string = "Hello World";
myArrowFunction = () => {
console.log(this.a); //
}
constructor(){
myArrowFunction(); //output: "Hello World"
}
}
Arrow functions don't have its own this, so the this binds to the parent, is that right? myArrowFunction belongs to TestComponent, so this in myArrowFunction should be undefined, but in the example above this binds to TestComponent why?
test = {
b: "Hello World",
foo: () => {
console.log(this.b);
}
}
test.foo(); //output: undefined
Where is the difference to the javascript code above? There this.b is undefined.
This is normal, because of the arrow function this refers to the upper object so your instance.
//console.log(this)
class TestComponent {
myArrowFunction = () => {// function set in instance
console.log(this); //
}
myFunction() {// function set in prototype
console.log(this); //
}
constructor() {
this.a = "Hello World";
this.myArrowFunction(); //output: "Hello World"
}
}
function A() {
this.foo = () => { console.log(this) };// A instance
this.foo()
}
A.prototype.bar = () => { console.log(this) };// global
new A();
//const a = new TestComponent();
Is it possible to combine the following into one statement:
// Combine from here
const foo = function() {
return 'hello';
}
foo.world = 'world';
// to here
console.log(foo() + foo.world) // helloworld
(foo = () => 'hello').world = 'world'
You can move the property declaration into the function.
let foo = function () {
foo.world = 'world';
return 'hello';
};
console.log(foo() + foo.world)
You have to assign statics outside of the function/class declaration. Here is an alternative ES5 version using classes.
class foo {
constructor() {
// constructor...
}
toString() {
return 'hello'
}
}
foo.world = 'world' // static member variables need to be assigned outside, no other way
console.log(new foo() + foo.world) // helloworld
As it's currently compiled via Babel + Webpack, module's exported class will create a closure: variables created inside the module will be shared between class instances.
bar.js:
let foo;
export default class Bar {
set foo(value) {
foo = value;
}
get foo() {
return foo;
}
}
app.js:
import Bar from './bar.js';
var barOne = new Bar();
var barTwo = new Bar();
barOne.foo = 'quux';
console.assert(barTwo.foo === 'quux');
I wonder if this behavour correct according to the spec.
I wonder if this behavour correct according to the spec.
Yes. JavaScript has lexical scope. That doesn't change with classes.
Keep in mind that classes are more or less just syntactic sugar for constructor function + prototype. Would you have had the same question if you wrote
let foo;
function Bar(){};
Bar.prototype = {
set foo(value) {
foo = value;
}
get foo() {
return foo;
}
};
module.exports = Bar;
instead?
If I have a function like this:
function foo(_this) {
console.log(_this);
}
function bar() {}
bar.prototype.func = function() {
foo(this);
}
var test = new bar();
test.func();
then the test instance of bar gets logged.
However, for this to work I have to pass the this in the bar.prototype.func function. I was wondering whether it is possible to obtain the same this value without passing this.
I tried using arguments.callee.caller, but this returns the prototype function itself and not the this value inside the prototype function.
Is it possible to log the test instance of bar by only calling foo() in the prototype function?
If the question is 'without passing this (by any means)' then answer is no
value can be passed by alternative methods though. For example using global var (within Bar class) or session or cookies.
function bar() {
var myThis;
function foo() {
console.log(myThis);
}
bar.prototype.func = function() {
myThis = this;
foo();
}
}
var test = new bar();
test.func();
I think calling foo within the context of bar should work:
function foo() {
console.log(this.testVal);
}
function bar() { this.testVal = 'From bar with love'; }
bar.prototype.func = function() {
foo.call(this);
}
var test = new bar();
test.func(); //=> 'From bar with love'
You can do this without changing the external function, but you must change the way you call it.
You can't get the context of the caller, but you can set the this property on a function you call with the method apply or call. See this reference for an explanation on this.
function foo()
{
console.log( this );
}
function bar()
{
bar.prototype.func = function func()
{
foo.apply( this );
};
}
var test = new bar();
test.func();
Usually if this is used, it's in an object oriented context. Trying to call a method of an object with another this might indicate poor design. Explain a bit more what you are trying to achieve for more applicable design patterns.
For an example of a javascript OOP paradigm, check my answer here.
What about this?
"use strict";
var o = {
foo : function() {
console.log(this);
}
}
function bar() {}
bar.prototype = o;
bar.prototype.constructor = bar;
bar.prototype.func = function() {
this.foo();
}
var test = new bar();
test.func();
Or this:
"use strict";
Function.prototype.extender = function( o ){
if(typeof o == 'object'){
this.prototype = o;
}else if ( typeof o == 'function' ) {
this.prototype = Object.create(o.prototype);
}else{
throw Error('Error while extending '+this.name);
}
this.prototype.constructor = this;
}
var o = {
foo : function() {
console.log(this);
}
}
function bar() {}
bar.extender(o);
bar.prototype.func = function() {
this.foo();
}
var test = new bar();
test.func();