Deep JavaScript
exploringjs.com
exploringjs.com
His "Exloring ES6" saved me when I was lost as knowing only about good old ES5 (or maybe ES3? I don't even remember.)
"JavaScript for impatient programmers" [2] also looks promising. Just purchased one. The PDF looks great although the cover is meh :-)
[1] https://exploringjs.com/es6.html [2] https://exploringjs.com/impatient-js/
Same for https://exploringjs.com/deep-js/ch_copying-objects-and-array..., the idea is there, but the text isn't great (is it only for objects and arrays? if I'm new to JS but someone taught me about Set and Map, can I assume those always deep copy?).
It's a great start, but it can definitely do with a few QA (rather than editorial) passes.
Don’t forget that this book is for people who already know JavaScript well. It doesn’t try to explain the basics. This book does, though: https://exploringjs.com/impatient-js/
But I never understood prototypes and prototype inheritance, and how does that "map" to "classic" inheritance, from Java or C++. And I worked in FE for about 10 years...
It seems you can model "classic" inheritance using prototypes, but... there is something more there that I don't understand. I started using ES6 "class" as quickly as I could, but I still wish I understood what .prototype and .__proto__ is and how to use it. I feel like I "miss" a lot of JS when misunderstanding prototypes.
But none of my colleagues know either, so I guess I at least know what I don't know.
A class is like a blueprint used by the language compiler and runtime to build (allocate) objects. In languages like Python, Ruby, Smalltalk, or Common Lisp these classes are present in some form at runtime controlling the memory allocation of objects, the initialization of member fields, the dispatching of generic or virtual functions and so forth. Since the classes are present in some shadowy form at runtime, they themselves have behaviors controlled by meta-classes which in some languages can be manipulated at runtime (e.g. monkey-patching).
Prototype based object systems don't use classes to accomplish this sharing of behavior and structure. Such systems have a conceptually simpler set of primitives to accomplish the sharing and classes aren't needed. In prototype based systems one can clone an existing object, even an empty object. After cloning an object one can add fields to the object.
Structural sharing is easy with prototypes. If a program would like to make use of objects representing screen coordinates, first construct a prototype:
Coordinate2D = clone(empty_object)
Coordinate2D.add_field(x).add_field(y)
Like fields, methods can be added to the prototype: Coordinate2D.add_method(clear)
Coordinate2D.clear = {self.x = 0; self.y = 0}
Next to create an object of type coordinate just clone the prototype: location = clone(Coordinate2D)
location.x = 10
location.y = 16
Prototype based systems are appealing because of the underlying language semantics and runtime implementation are very simple.Smalltalk, CLU, Common Lisp's CLOS (The Art of the Meta-Object Protocol), and Self all inspired design decisions that went into the Tivoli Systems distributed programming framework.
Diagrams help me understand how this works. At the following link, you can see the source code of a simple class and a diagram (section 29.2.2) that shows how all involved objects are connected: https://exploringjs.com/impatient-js/ch_proto-chains-classes...
I'd recommend doing it in two steps.
First, you need to get from the Java/C++ perspective of "classes are compile-time templates" to a perspective of "everything is an object". Python is a good example of the latter, as is Smalltalk (the latter is more 'extreme', but also less widely used):
$ python3
Python 3.8.9 (default, May 27 2021, 03:09:34)
[Clang 7.1.0 (tags/RELEASE_710/final)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> class A:
... pass
...
>>> myA = A()
>>> myA
<__main__.A object at 0x10670c490>
>>> A
<class '__main__.A'>
>>> myA.__class__
<class '__main__.A'>
>>> class B(A):
... x = 123
...
>>> myA.__class__ = B
>>> myA.x
123
>>>
Once you're comfortable with that, you can take the second step: from a Python/Smalltalk perspective of "everything is an object; when a slot isn't found in the instance, we fall back to looking in its class", to reach the Javascript/Self perspective of "everything is an object; when a slot isn't found in an object, it can tell us to look in another object". That 'other object' is the prototype.All we're doing in the second step is removing a distinction: Python/Smalltalk have a built-in notion of "class", where some objects are classes and others aren't. Javascript/Self just have objects: we can use any object as a prototype for any other.
If something doesn't exist on your object, JS will check if it has a prototype and look there transparently.
Now, if you got a prototype chain, JS will move through it in the hope to find what you wanted to access on the original object.
try to access obj.a
not there?
try to access obj.prototype.a
not there?
try to access obj.prototype.prototype.a
etc.
The nice thing is "this" will usually (if you call a function as method and not pass a reference of it around for callbacks and such) refer to the object and not the prototype. Also, writes happen on the object.
https://exploringjs.com/deep-js/ch_copying-objects-and-array...
The reason the article you linked is so long (instead of just being the standard OOP shallow- vs deep-copy disclaimer) seems to be because JS objects and classes are just dictionaries (in the Python sense of the word) with certain magic fields to control dispatch, inheritance, etc. The docs need to take care to explain how certain operations interact with those magic fields. So, still convoluted, but IMO better than if it were convoluted because everything was a built-in special case under the hood.
At least that's my impression as someone who doesn't write a lot of JS. Happy to be corrected.
(more offtopic, but we'll be using TypeScript, so I'm going to need to find some good guides for that too - any suggestions?)
I'd start with a "Re-introduction" tutorial on MDN [1] followed by another Axel's book - "JavaScript for impatient programmers" [2]. Don't read the whole book at first, focus on specific chapters: parts on Modularity, Collections and Asynchronicity.
As for TypeScript, the official Handbook [3] is great. Don't dwell much on intricacies of TS type system. Use it here and there to aid your editor or IDE in highlighting mistakes in your code, and get deeper into it once you get a good grip with JavaScript in general.
[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re... [2] https://exploringjs.com/impatient-js/toc.html [3] https://www.typescriptlang.org/docs/handbook/intro.html
It's going to be a shock going from declarative DSLs like Puppet and Terraform to a real coding language! Most of my coding experience has been in shell scripting and some Perl/Ruby from ages ago.
resources: [`arn:aws:${cdk.Aws.AccountNubmer}`]
(I know I got the arn format wrong and probably messed up the account number, but you get the gist I hope)
The reason is if you follow those rules strictly enough, you can still deploy that template in most accounts (dev, test, prod and so on), which has always been one of the core strengths of CF (and others) when done properly.
And I prefer to NOT use If statements in typescript if it can be done in Cloudformation with conditions or other items. For instance, if you only want to deploy a secondary rds slave in prod, use a CF condition and not a typescript 'if (accountNumber === myProdAccount)' because that means your typescript needs to know which account it's synthing for, which by default it does not.
IOW, try to use typescript to build DSL that's still in the spirit of DSL and you'll avoid a lot of traps that novices get themselves into.
Being able to throw in some loops here and there is quite a simplification on its own.
I believe language evolution like ES6 are more than welcome. However, I have the impression that the path taken by the committee and the new proposals do not bring great gains (whether in UX, code reading, performance, etc.) but bringing unnecessary complexity.
On the other hand, other serious problems such as the mathematical and numerical part of the language are being left aside.
– BigInts (arbitrary precision integers) were a recent addition: https://exploringjs.com/impatient-js/ch_bigints.html
– A proposal for `Decimal` (base 10 floating point numbers with arbitrary precision) is currently at stage 1: https://github.com/tc39/proposal-decimal
Not having 64 bit integers is a large annoyance. There’s workarounds but none of them are especially ergonomic.
The expression n | 0 is a signed 32 bit int. The expression n >>> 0 is an unsigned 32 bit int.
I deep dived JavaScript many years ago so I could move away from C#. It was only useful in interviews so I could answer all the esoteric trivia. On the job it was using JS frameworks and libraries like Lodash. And then TypeScript came along and eclipsed it all together.
You're better off learning just enough JavaScript and then deep diving TypeScript and Angular, React, or another framework.
People look at Crockford's "JS: The Good Parts" and comment on how it's obvious. It wasn't obvious then and that's why the book was so well received. Languages have radically copied the good parts JS since then while JS has lost most of the worst parts which means that when you move to JS, it's a much less radical shift.
First-class functions and closures with all their implications (IIFE, module pattern, callback/continuation, lambdas, .map() and it's ilk, currying, etc) have all caught on as a result.
Immutable data or more precisely, treating data as immutable and letting the GC sort it out was a huge boon for UI development.
Promises/futures seem ubiquitous these days, but that's strictly because of JS libraries introducing them in 2005 (twisted library introduced them in Python in 2001, but Python wasn't super popular then and twisted has never been popular at all).
I'd also say that the push for pattern matching has also been fueled by ES6.
In truth, StandardML (SML) and Scheme had been doing most of this (and much more) since the 70s, but for whatever reason, they have been rejected by mainstream developers. Hopefully, one day we will recognize this and switch development away from languages with these features tacked on to ones where they are baked in and cohesive.
Invest in the basics, and you'll never lose. SQL, HTML, JS. No need to keep learning or relearning frameworks or libraries.
The whole thing reads (visually) as a bit of an indiscriminate jumble.
The following changes help (me). I'd also look at colouring some other sections to clarify the visual flow of document,
```
pre { background-color: #EEE; font-size: 1.2em; line-height: 1.4; margin-left: 1em; padding: 1em; }
body { font-family: sans-serif; font-size: 1.2em; }
#page-content { margin: 2em auto 2em auto; max-width: 40em; font-size: 1.1em; line-height: 1.7; }
```
But I found it odd that there is no copyright information, date of publication, etc.
Unless there is something time/space-specific about it, invoking "algorithm" feels to me an abuse of terminology. Of course will love to be enlightened otherwise.
"Most of the books are free to read online! You can also buy offline versions."