Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

And that's your opinion. I find javascript quite enjoyable and easy to use, without producing errors. YMMV.


JavaScript has good parts, I write it a lot. But it is ignorant to close eyes on its warts

    1 + '2'
    1 - '2'
    Number.MAX_SAFE_INTEGER + 2
and entire WAT series, stems from "don't raise" ethos. JavaScript exposes constructor instead of prototype that messed up a lot, in Ruby terms

    Object.alias_method :__proto__, :class
    Object = Object.instance_method(:initialize)
    Class = Class.instance_method(:initialize)
    Class.__proto__.alias_method :prototype, :owner
    new = ->(constructor) { constructor.owner.new }
    
    Person = Class.prototype.new do
      def initialize
      end
    end.instance_method(:initialize)
    
    def Person.foo
      'foo'
    end
    puts Person.foo

    john = new.call Person
    
    def john.bar
      'bar'
    end
    puts john.bar
    
    def (Person.prototype).baz
      'baz'
    end
    puts john.__proto__.baz
Does anyone wants to adopt this feature in their language?


Operator overloading can lead to ambiguities in dynamic languages. Ruby, python, and any number of other languages have it much worse because they can be overloaded any way you want while JS overloads are (currently at least) set in stone by the language.

If you could only choose one number type, would it be floats or ints? Crockford would say decimal, but the rest of use using commodity hardware would choose floats every time. It's not the language implement's fault someone doesn't understand IEEE 854. This max safe integer issue exists in ALL languages that use IEEE 854. In any case, BigInt is already in browsers and will be added to the spec shortly.


Perl and Lua have separate arithmetic and concatenation operators

    1 + "2"
    #3
    1 - "2"
    #-1
    1 . "2"  | 1 ..  "2"
    #"12"
    1 . "-2" | 1 .. "-2"
    #"1-2"
Python and Ruby throw exception, use explicit type conversion and string interpolation

    1 + '2'
    Traceback (most recent call last):
    TypeError (String can't be coerced into Integer)
    1 + '2'.to_i
    #3
    "1#{'2'}"
    #"12"
Hardly any language is perfect, I have not encounter much of operator overload in ruby (nokogiri?) but I believe C++ got it bad.

One number type in Lua:

    > 0 | 0xffffffff
    4294967295
    > 0 | 0xffffffffffffffff
    -1
    > 0 | 0x7fffffffffffffff
    9223372036854775807
limited but better than JavaScript:

    0 | 0xffffffff
    //-1
BigInt is an improvement

    0n | 0xffffffffn
    //4294967295n
    0xffffffffffffffffn
    18446744073709551615n
it is strict

    1n - "2"
    1 + 1n
    Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions
works nice with string interpolation:

    `${1n}`
    "1"
Numbers is a sane example. One can argue it was for good. How about `{} + []`? I believe I can disable this part in JavaScript engine and no one would notice. And misleading `object[key]` where it calls toString, sure I have not tried that in a decade but it is stupid. UTF-16:

    ""[1] # there were emoji
    //"�"
You've said nothing about constructor oriented programming. Unique feature, I have not heard any other language adopted it yet. The post you've replied contents sketch for Ruby. Actually I've got it wrong — every JavaScript function is a closure (Ruby method is not closure) and Prototype method was a class method (not instance method), fixed but ugly:

    def function(&block)
      Class.prototype.new.tap do |c|
        c.define_method(:initialize, block)
      end.instance_method(:initialize)
    end

    def function_(object, name, &block)
      object.class_eval do
        define_method(name, &block)
      end
    end

    Person = function { |name|
      @name = name
    }
    function_(Person.prototype, :name_) {
      @name
    }

    john = new.call Person, 'john'
    puts john.__proto__ == Person.prototype
    puts john.name_

    def function__(object, name, &block)
      object.singleton_class.class_eval do
        define_method(name, &block)
      end
    end

    function__(john, :name__) {
      @name
    }
    puts john.name__
By the way, you can say "Yes, I know JavaScript has some problems". It is not a secret, everyone knows.


I completely agree that separate operators area MUST for dynamic languages.

Lua allows operator overloading with metatables as do ruby and Python with classes

http://lua-users.org/wiki/MetatableEvents

https://docs.python.org/3/reference/datamodel.html#emulating...

https://www.ruby-lang.org/en/documentation/faq/7/

> One number type in Lua:

Not quite true. Lua had only 64-bit floats like JS until version 5.3 and the blazing fast LuaJIT still only has floats. Well, to be honest, it has hidden 32-bit integers for sake of bitwise operations just like JS (well, JS uses 31-bits with a tag bit which is probably a lot faster).

> How about `{} + []`? I believe I can disable this part in JavaScript engine and no one would notice.

That's very simple. {} at the beginning of a line is an empty block rather than an object (yay C). "Disabling" that would break the entire language.

> UTF-16

UCS-2 actually. Back in those days, Unicode was barely a standard and that in name only. Java did/does use UCS-2 and JS for marketing reasons was demanded to look like Java. I don't want to go into this topic, but python, PHP, ruby, C/C++, Java, C#, and so on all have a long history not at all compatible with UTF-8.

> You've said nothing about constructor oriented programming. Unique feature, I have not heard any other language adopted it yet.

I'll give you that JS prototypal inheritance is rather complex due to them trying to pretend it's Java classes. Once again though, the deep parts of both Python and Ruby classes are probably more difficult to explain. Lua's metatables are very easy to understand on the surface, but because there's no standard inheritance baked in, every project has their own slightly different implementation with it's own footguns.

Closures are almost always preferred over classes in modern JS. Likewise, composition is preferred over inheritance and the use of prototype chains while not necessarily code smell, does bear careful consideration.

If someone insists on using deep inheritance techniques, they certainly shouldn't be using class syntax as it adds yet another set of abstractions on top. Object.create() and inheriting from `null` solves a ton of issues.

> By the way, you can say "Yes, I know JavaScript has some problems". It is not a secret, everyone knows.

I'd say if you take the top 20 languages on the tiobe index, it sits in the middle of the pack with regard to warts and weirdness. Maybe people are just attracted to weird languages.


I have no grudge against operator overloading when done consciously — complex numbers, matrix multiplication. I've tried to implement JavaScript arithmetic in Ruby, failed so far.

Sorry, I had to be clear, in Lua "one number type" means float, my bad. I meant Lua 5.3 integer still works like JavaScript Number. In the end we have to know about ToInteger, ToInt32, ToUint32, Number.MAX_SAFE_INTEGER [1]. It is not one number type but encoding of several number types, union.

Prior to 5.3 and in LuaJIT it has different limitations

    > print(string.format("%18.0f",9007199254740991 + 1))
      9007199254740992
    > print(string.format("%18.0f",9007199254740991 + 2))
      9007199254740992
they have extended original "one number type" without change of the interface. In any case both versions do not convert to BigNum like Ruby.

    0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
    => 115792089237316195423570985008687907853269984665640564039457584007913129639935
Ruby unified Fixnum, Integer and BigNum as Integer in 2.4. Can't see benefits of Number/BigInt against Float/Integer. I'd rather have 3.6f literal.

Yes, I know how WAT works. I meant ToPrimitive [2]

    [] * {}
    //NaN
I've disabled this code in Firefox, have not done extensive testing but looks like no one depends on it. We infer types with TypeScript and flow but VM already knows it, it can report such cases without external tools. I think of it as extension of Firefox Developer edition — lint in the browser.

Object.prototype.toString is not as useful as Ruby, Python

    class Foo {}
    `${new Foo}`
    //"[object Object]"

    class Foo end
    Foo.new
    #=> #<Foo:0x0000560b7a10df20>

    >>> class Foo:
    ...     pass
    >>> Foo()
    <__main__.Foo object at 0x7fb53aecf1f0>

And there is no separate inspect/__repr__

    Date.today
    #=> #<Date: 2020-10-20 ((2459143j,0s,0n),+0s,2299161j)>
    Date.today.to_s
    #=> "2020-10-20"
> UCS-2 actually

Oh, DOM UTF-16 string broken by UCS-2 JavaScript function. I understand it is not easy to fix, Ruby fixed in 1.9, Python in 3.0, new languages (Rust, Elixir) come with UTF-8. Microsoft Windows has code pages, UCS-2, UTF-16.

Maybe Python way? b"binary", u"utf-8" (but together, not python fiasco), ruby has "# Encoding: utf-8", transformation tools can mark "b" or "u" all unspecified strings.

> Once again though, the deep parts of both Python and Ruby classes are probably more difficult to explain.

No, every Ruby object contains variables and has a link to a class which defines instance methods, we call it singleton_class

    foo = Object.new
    foo.class == Object
    #=> true
    foo.singleton_class == Object
    #=> false

    def foo.bar
    end
    foo.singleton_class.instance_method(:bar)
    #=> #<UnboundMethod: #<Class:#<Object:0x000055cb33808e10>>#bar() (irb):7>
There is ancestors chain

    Object.ancestors
    #=> [Object, Kernel, BasicObject]
There is a bit of syntactic sugar

    Foo = Class.new
There are few revelations with main (method defined in Object)

    def baz
    end
    Object.instance_method(:baz)
    => #<UnboundMethod: Object#baz() (irb):19>
Nothing like audible "click" I had when understood that "function" is a "constructor"

    constructor Foo {}
    // you can call me as function too
that unlike any other language [[Prototype]] is hidden. I've red through ES5 to be sure there are no hidden traps left.

Every JavaScript programmer has to go through this list either beforehand or by experience. I do not want to undermine TC39 effort — arrow functions, string interpolation in template literals, strict BigInt, Object.create — these are great advancement. I don't feel same way for "class", underlying weirdness is still there.

Make [[Prototype]] visible

    Object = Object.prototype
    Function = Function.prototype
now it is easy to reason about

    typeof Object 
    //"object"

    Foo = class {}.prototype         // redefine with sweetjs macro
    Bar = class extends Foo.constructor {}.prototype

    new Foo.constructor              // redefine with sweetjs macro

    Object.constructor.create(Bar)   // redefine as Reflect.create
once redefined:

    Foo = class {}
    Bar = class extends Foo {}
    new Foo
    Reflect.create(Bar)
I've shown it in another comment [3].

Languages are weird, there are a lot of C++ developers, I've been there, no way to know all dark corners. Pythons ideology hurts. Java took EE way. C# was tied to Microsoft. C K&R is beautiful, hard to write safe, packs a lot in the code. PHP has its bag of problems. SQL is not composable, CTE helps. Go ideology. Ruby — performance. And JavaScript because browser, not bad when know and avoid skeletons in the shelf.

Lua metatables looked like a proxy/method_missing for me.

[1] https://www.ecma-international.org/ecma-262/5.1/#sec-9.5

[2] https://www.ecma-international.org/ecma-262/5.1/#sec-9.1

[3] https://news.ycombinator.com/item?id=24815922


> Object.prototype.toString is not as useful as Ruby, Python

I don't know that returning that info would be good or secure in JS

> Oh, DOM UTF-16 string broken by UCS-2 JavaScript function. I understand it is not easy to fix, Ruby fixed in 1.9, Python in 3.0, new languages (Rust, Elixir) come with UTF-8. Microsoft Windows has code pages, UCS-2, UTF-16.

The best and most compatible answer is moving JS to UTF-32. JS engines already save space by encoding strings internally as latin1 instead of UCS when possible (even around 90% of text from Chinese sites is still latin1). IMO they should have made backtick strings UTF-32, but that doesn't exactly transpile well.

> No, every Ruby object contains variables and has a link to a class which defines instance methods, we call it singleton_class

https://mccraigmccraig.files.wordpress.com/2008/10/ruby-eige...

https://i.stack.imgur.com/FPPdI.png

or adding all the things with a few instances, .constructor, etc

https://i.stack.imgur.com/HvzDP.png

I'll let you decide which implementation is easier to work through, but I have a definite opinion that Ruby's system is more complex (and Python layers their OOP on top of what is basically a hidden prototypal system).

> I've red through ES5 to be sure there are no hidden traps left.

You'll love newer ES versions then. The upcoming private fields are an even bigger mess.

JS needs a "use stricter" mode which really slices away the bad parts. Even better, just add a `version="es20xx"` requirement to use newer features and have browsers ignore what they don't know, so you could even compile and link to multiple compilation levels of the same script and have the browser choose.

In truth, JS would be in the best place of any top-20 language if Eich had just been allowed to make a scheme variant as he had planned.


Yes, template strings was a clean start.

Of course prototype based language is simpler than class based. Ruby system is more complex. It provides more tools — Class, Module, class and instance methods, variables (as depicted on the picture). You've asked eigenclass (singleton_class these days), that's Class:a -> A, very simple concept.

And yet Ruby inheritance is much easier, it is all around and it just works. No one does this in JavaScript, too complex. There were many attempts of building OOP people could understand on top of JavaScript in 200x. No one does this for Ruby.

> https://i.stack.imgur.com/FPPdI.png

With fix above:

http://sergeykish.com/javascript-no-constructor.png

I'll let you decide which implementation is easier to work through, but I have a definite opinion that current JavaScript system is more complex.

> You'll love newer ES versions then. The upcoming private fields are an even bigger mess.

I follow.

Netscape and Mozilla tried version approach. Module is a clean start, 'use strict' by default. It is not Visual Basic, already good.


Sure, until you parachute into a code base where several generations of contractors added features that communicate over a shared global object. This is bad per-se, but becomes worse when your language allows one to add fields on the fly and you end up with this container full of similar fields because eventually nobody knows exactly what’s in the object any more...


And that seems pretty simple to fix. "The same level of awareness that created a problem cannot be used to fix the problem" - and maybe that's why they hired you, to fix these problems. I've been that guy before. What was really fun was the codebase I had to fix that used mexican slang words as variable names, and I only speak English. So much fun. But I sucked it up, accepted the challenge, and I improved it.

It really doesn't take a super-genius to code javascript simply, efficiently, and without errors. Funny that a lot of programmers that think they're very smart are the ones that either shit on javascript, or make a lot of stupid errors with it, or both.


I've seen similar abuses with global maps in other languages (essentially the same). This is an architecture fault rather than a language fault.

As you say, that is a problem with any language and project with a revolving door of developers. Perhaps those companies should learn their lesson and hire at least one or two good, permanent senior devs to keep things on track.

Like always, the human factor outweighs almost everything else.


I'd love to have a way to take a `Date` object and set it as the value of a `datetime-local` input. Sure feels like that should be straightforward to do, without requiring any weird conversions like it does.



Wow. `zonedDateTimeISO` looks like exactly what I was hoping for. I'm kind of surprised that there isn't anything analogous to `strftime`, though.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: