Weird behavior when declaring class property with semicolon - javascript

class SomeClass {
x: 5;
y = 10;
}
const c = new SomeClass();
alert(c.x + ' : ' + c.y);
Why is the code compilable but the value of c.x is undefined?
What is the effect of declaring a class property with :?

Regarding the x: 5 part, although this is a valid javascript code, there is no much use for it.
This is a javascript label and it used (if any) mostly within loops context.
So to answer your questions:
Why is the code compilable
Because technically this is a valid javascript code (yet not a valid class field).
but the value of c.x is undefined
Because the x is a label and not a class field.
What is the effect of declaring a class property with :
You get a label instead of a class field.
Addendum
Another common mistake, is this code of block:
class SomeClass {
z = () => {
x: 5;
};
}
You would think that z() will return an object with an x key:
`{x:5}`
But actually you have a function with a label of x that just run an expression of 5.
Just for completeness sake, the fix will be either to add an explicit return and another set of curly braces
() => {return {x: 5}}
Or just wrap the whole thing with parentheses
() => ({x: 5})
Edit
As a followup to the comments below:
Just to be clear, your code compiles on several environments that i tested as well as stack-snippets as can be seen below:
class SomeClass {
x: 5;
y = 10;
}
const c = new SomeClass();
console.log(c.x + ' : ' + c.y);

The code is not valid ES6.
You seem to be "compiling" with babel, and have inadvertently enabled the flow syntax extension (and also class properties for the second line). In flow, x: 5 is a class field type annotation. Of course, 5 as a type doesn't make sense, but apparently they allow pretty arbitrary expressions.

Related

Do derived classes enable property lookup Inline Cache in V8? [duplicate]

How I understand inline caches, there is no check for "or further down in the hidden class tree" (would be costly to do without having some trick). Even though an instance property from a base class would always be at the same offset, an access of a base class property encountering many different subclass instances would mean its inline cache gets overwhelmed (or does it? Perhaps I am wrong here already, strongly typed languages usually do cover this case, perhaps there is a trick being used?). This also would apply to objects in general.
This left me wondering: instead of subclasses, wouldn't it sometimes be better, to have two objects, one with the base properties, one with the subclass properties, both having a reference to the other?
Class extension version:
class A {
x = 0;
}
class B1 extends A {
y = 0;
}
class B2 extends A {
z = 0;
}
const b1 = new B1();
const b2 = new B2();
const f = (p: A) => { p.x; };
// Different hidden classes.
f(b1);
f(b2);
Linked objects version:
class A<T> {
x = 0;
extension: T;
constructor(extension: T) { this.extension = extension; }
}
class B1 {
a: A<B1>;
y = 0;
constructor() { this.a = new A(this); }
}
class B2 {
a: A<B2>;
z = 0;
constructor() { this.a = new A(this); }
}
const b1 = new B1();
const b2 = new B2();
const a1 = b1.a;
const a2 = b2.a;
const f = <T,>(p: A<T>) => { p.x; };
// Same hidden class.
f(a1);
f(a2);
Does this have any tangible performance impact? I guess the answer is always "don't care until you measured it's your bottleneck", but I am left wondering.
In short: Yes.
Subclassing can lead to excessive polymorphism when an engine uses hidden classes and equality comparisons on these hidden classes (like V8 does). (And for the record, that doesn't imply that hidden classes are a bad idea -- they just happen to have both benefits and limitations, like any engineering technique.)
Modifying your object layout can be a good way to avoid that. How exactly to do that depends a lot on your requirements. You may or may not need the bidirectional links; e.g. a variant that might be good enough to address some common usage scenarios is:
class A {
x = 0;
extension;
constructor(extension) { this.extension = extension; }
}
function MakeB1() {
return new A({y: 0});
}
function MakeB2() {
return new A({z: 0});
}
// And then the rest is very similar to your first example, just
// with "MakeB1" instead of "new B1":
const b1 = MakeB1();
...
f(b1);
You may want to include a type property in class A, then you can do things like
if (a.type == B1) ProcessB1(a) else if (a.type == B2) ProcessB2(a);.
Does this have any tangible performance impact?
It might, sometimes...
I guess the answer is always "don't care until you measured it's your bottleneck"
...absolutely. Many/most apps don't need to care, but for certain performance-sensitive code, optimizations like these might help quite a bit. Only profiling can tell you which parts of your app might be worth optimizing.

Uncaught TypeError: quotesData[currentQuote] is undefined

i try to build a simple javasciprt random quote app but in the very first test of my code i saw this in console : Uncaught TypeError: quotesData[currentQuote] is undefined
showquote http://127.0.0.1:5500/js/main.js:31
http://127.0.0.1:5500/js/main.js:37
this is js code source :
quotesData = [{
quote: `There are only two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a miracle.`,
name: 'Albert Einstein '
},
{
quote: `Good friends, good books, and a sleepy conscience: this is the ideal life.`,
name: 'Mark Twain'
},
{
quote: `Life is what happens to us while we are making other plans.`,
name: 'Allen Saunders '
},
{
quote: `It's not the load that breaks you down, it's the way you carry it.`,
name: 'Lou Holt'
},
{
quote: `Try not to become a man of success. Rather become a man of value.`,
name: 'Albert Einstein '
},
]
/* important variables */
const currentQuote = quotesData[0];
const quoteText = document.getElementById('quote');
const quotebtn = document.getElementById('q-btn');
const quotepan = document.getElementById('q-span');
/* this function is for show the quote and author name */
function showquote() {
quoteText.innerText = quotesData[currentQuote].quote;
quotespan.innerText = quotesData[currentQuote].name;
currentQuote++;
};
/* this function is for change the quote and author name with evrey click */
quotebtn.addEventListener('click', showquote())
currentQuote isn't an array index, it's an element of the array.
You need to set it to 0, and it can't be const if you want to increment it.
let currentQuote = 0;
Also, the second argument to addEventListener should be a reference to a function. You're calling the function immediately instead of saving it as a listener.
quotebtn.addEventListener('click', showquote);
After you increment currentQuote, you need to check if you've reached the end of the array and wrap around. You can do this using the modulus operator.
function showquote() {
quoteText.innerText = quotesData[currentQuote].quote;
quotespan.innerText = quotesData[currentQuote].name;
currentQuote = (currentQuote + 1) % quotesData.length;
};
A couple problems with your code -
Replace quotebtn.addEventListener('click', showquote()) with quotebtn.addEventListener('click', showquote) because otherwise you are passing the return value of showquote to the function.
currentQuote is an object which cannot be passed as an index. You need to set currentQuote to 0 so you can increment it.
This is still not random quotes, but it solves your problems.
currentQuote is a constant variable - which means you can't increment it because ++ is actually just syntactic sugar for += 1 which in itself is syntactic sugar for currentQuote = currentQuote + 1. Change it to let.
TIP:
Do not mix ES5 and ES6. Old functions should only be used when access to the this keyword is needed. Otherwise, stick to one version for semantic purposes.

How does the equal sign relate to the arrow function?

I recently started with ES6, and I understood the use of arrow functions, such as:
const divisibleByThrreeES6 = array.filter(v => v % 3 === 0);
However, I found this library where the following line is written:
<div ref={div => this.chart = div}/>
I am wondering about the part in curly braces. I assume that the function is:
function(div) {
return this.chart;
}
Is that correct? What does the equal sign = div have to do with it? I could not find documentation explaining that last part.
I assume that the function is
It isn't.
It is:
function(div) {
return this.chart = div;
}.bind(this)
It assigns the value of div to this.chart and then returns that value from the function.
Odds are that the return value is never used, and it is only being returned as a side effect of using the single expression arrow function syntax.

Phaser: Instantiate class by string reference

I am working on a "manager" for selecting what crop shall be placed on a certain plot. Every crop has a completely different design and therefor their own class/object. However instead of writting >40 different lines that will instantiate that class I would like 1 line that simply contains the string that matches the exact name of a class and then run it. That way my code will stay clean. I have tried some stuff but never managed to get it done. Usually resulting in an the following error:
TypeError: this.crop is not a constructor
The code I am attempting to run
export default class CropManager extends Phaser.Group {
constructor (game, className, plotId) {
super(game)
this.x = 0
this.y = 0
this.plotId = plotId
this.className = className
this.cropHandler(this.className)
}
// Defines which class to call
cropHandler (className) {
const ActualClass = 'plot' + className
this.cropclasses = { ActualClass: ActualClass}
this.crop = this.cropclasses[ActualClass]
this.classRun = new this.crop(this.game, this.x, this.y, this.plotId)
this.add(this.classRun)
}
}
Note every crop their classname = crop+cropname (cropCarrots, cropCows, etc)
Rethink the way you're storing key-value pairs in this.cropclasses. The way it's done now, it's going to have 'ActualClass' as the key and 'plotNameOfTheClass' (or whatever 'plot' + className produces) as the value, thus, when accessing it later as an array, this.crop comes out undefined since there isn't a 'plotNameOfTheClass' key in the map.

Prototype's Enumerable#pluck in F#?

In JavaScript, using the Prototype library, the following functional construction is possible:
var words = ["aqueous", "strength", "hated", "sesquicentennial", "area"];
words.pluck('length');
//-> [7, 8, 5, 16, 4]
Note that this example code is equivalent to
words.map( function(word) { return word.length; } );
I wondered if something similar is possible in F#:
let words = ["aqueous"; "strength"; "hated";"sesquicentennial"; "area"]
//val words: string list
List.pluck 'Length' words
//int list = [7; 8; 5; 16; 4]
without having to write:
List.map (fun (s:string) -> s.Length) words
This would seem quite useful to me because then you don't have to write functions for every property to access them.
I saw your request on the F# mailing list. Hope I can help.
You could use type extension and reflection to allow this. We simple extend the generic list type with the pluck function. Then we can use pluck() on any list. An unknown property will return a list with the error string as its only contents.
type Microsoft.FSharp.Collections.List<'a> with
member list.pluck property =
try
let prop = typeof<'a>.GetProperty property
[for elm in list -> prop.GetValue(elm, [| |])]
with e->
[box <| "Error: Property '" + property + "'" +
" not found on type '" + typeof<'a>.Name + "'"]
let a = ["aqueous"; "strength"; "hated"; "sesquicentennial"; "area"]
a.pluck "Length"
a.pluck "Unknown"
which produces the follow result in the interactive window:
> a.pluck "Length" ;;
val it : obj list = [7; 8; 5; 16; 4]
> a.pluck "Unknown";;
val it : obj list = ["Error: Property 'Unknown' not found on type 'String'"]
warm regards,
DannyAsher
>
>
>
>
>
NOTE: When using <pre> the angle brackets around <'a> didn't show though in the preview window it looked fine. The backtick didn't work for me. Had to resort you the colorized version which is all wrong. I don't think I'll post here again until FSharp syntax is fully supported.
Prototype's pluck takes advantage of that in Javascript object.method() is the same as object[method].
Unfortunately you can't call String.Length either because it's not a static method. You can however use:
#r "FSharp.PowerPack.dll"
open Microsoft.FSharp.Compatibility
words |> List.map String.length
http://research.microsoft.com/fsharp/manual/FSharp.PowerPack/Microsoft.FSharp.Compatibility.String.html
However, using Compatibility will probably make things more confusing to people looking at your code.

Categories

Resources