Skip to content

Commit

Permalink
feat: rewrite and add new sections
Browse files Browse the repository at this point in the history
  • Loading branch information
Kikobeats committed Apr 4, 2022
1 parent 07e87db commit e86b527
Show file tree
Hide file tree
Showing 20 changed files with 258 additions and 156 deletions.
28 changes: 0 additions & 28 deletions .travis.yml

This file was deleted.

File renamed without changes.
20 changes: 13 additions & 7 deletions docs/_sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,28 @@

* Function
* [new agnostic](function/new.md)
* [bind is slower](function/bind.md)
* [.bind is slower](function/bind.md)

* RegExp
* [Use the correct method](regexp/correct-methods.md)
* [Focus on failing faster](regexp/fail-faster.md)
* [Mandatory Fields](regexp/flags.md)
* [Dot all flag](regexp/dot-all-flag.md)
* [Global flag](regexp/global-flag.md)
* [Unicode flag](regexp/unicode-flag.md)

* Object
* [Empty prototype](object/empty-prototype.md)

* V8
* [Hidden Class](v8-tips/hidden-class.md)
* [Sparse Arrays](v8-tips/sparse-arrays.md)
* [Properties Names](v8-tips/properties-names.md)
* [Float Number](v8-tips/float-number.md)
* [Freeing memory](v8-tips/freeing-memory.md)
* [Hidden classes](v8-tips/hidden-classes.md)
* [Inline initialization](v8-tips/inline-initialization.md)
* [Monomorphic](v8-tips/monomorphic.md)
* [Properties Names](v8-tips/properties-names.md)
* [Sparse Arrays](v8-tips/sparse-arrays.md)
* [Use strict](v8-tips/use-strict.md)
* [Freeing memory](v8-tips/freeing-memory.md)
* [Spread Syntax](v8-tips/spread-syntax.md)

* Workflow
* [Deferring by a tick](workflow/defer.md)
Expand All @@ -42,4 +48,4 @@
* [Scope](workflow/scope.md)
* [Variable access](workflow/variable-access.md)
* [How to clone](workflow/how-to-clone.md)
* [null and undefined](workflow/null-and-undefined.md)
* [null or undefined](workflow/null-or-undefined.md)
2 changes: 1 addition & 1 deletion docs/array/pop-or-shift.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# pop over shift
# .pop over .shift

The `.shift` method removes the first element from an array and returns it.

Expand Down
8 changes: 6 additions & 2 deletions docs/array/preallocation.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Preallocation

## Initialize value
Preallocation is when you reserve memory space before using it.

This is specially useful when you know much much space you need, or you want to avoid expanding repeatedly the size of a collection over time.

## Initializing the values

If you want to preallocate an array with a initial value, you can use [`Array.from()`](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Array/from):

Expand All @@ -11,7 +15,7 @@ const n = 5
[...Array(n).keys()] // [ 0, 1, 2, 3, 4 ]

// more powerful
Array.from({length: n}, (value, index) => index) // [ 0, 1, 2, 3, 4 ]
Array.from({ length: n }, (value, index) => index) // [ 0, 1, 2, 3, 4 ]
```

## Reusing instances
Expand Down
1 change: 0 additions & 1 deletion docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
<script src="//unpkg.com/docsify@latest/lib/plugins/external-script.min.js"></script>
<script src="//unpkg.com/docsify@latest/lib/plugins/ga.min.js"></script>
<script src="//unpkg.com/docsify-pagination/dist/docsify-pagination.min.js"></script>
<script async src="//cdn.headwayapp.co/widget.js"></script>
<script src="//cdn.jsdelivr.net/npm/codecopy/umd/codecopy.min.js"></script>

</html>
2 changes: 1 addition & 1 deletion docs/main.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions docs/object/empty-prototype.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Empty prototype

All objects in JavaSCript are instance of `Object` and they inherit properties and methods, such as `.toString`.

There are situations in which you just want to use an `Object` instance as a container of values.

For thoese cases, an `Object` maybe be deliberately created with an empty prototype, meaning it inherits nothing.

```js
const cache = Object.create(null)
```

In this way, the object has a smaller memory footprint.

Since it doesn't inherit from other object, you can't typechecking using `instanceof`:

```js
Object.create(null) instanceof Object // false
```
46 changes: 8 additions & 38 deletions docs/regexp/flags.md → docs/regexp/dot-all-flag.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,4 @@
# Always use flags

## Unicode flag

The unicode (`u`) flag is mandatory when working with Unicode strings, in particular when you might need to handle characters in astral planes, the ones that are not included in the first 1600 Unicode characters.

Like Emojis, for example, but not just those.

If you don’t add that flag, this simple regex that should match one character will not work, because for JavaScript that emoji is represented internally by 2 characters (see [Unicode in JavaScript](https://flaviocopes.com/javascript-unicode/)):

```js
/^.$/.test('a') //
/^.$/.test('🐶') //
/^.$/u.test('🐶') //
```

So, always use the `u` flag.

Keep in mind that Unicode, just normal characters, handle ranges:

```js
/[a-z]/.test('a') //
/[1-9]/.test('1') //

/[🐶-🦊]/u.test('🐺') //
/[🐶-🦊]/u.test('🐛') //
```

JavaScript checks the internal code representation, so `🐶 < 🐺 < 🦊` because `\u1F436 < \u1F43A < \u1F98A`. Check [emoji-regex](https://github.com/mathiasbynens/emoji-regex) for exploring more about that.

## Dot all flag
# Dot all flag (s)

By default, `.` matches any character except for line terminators.

Expand All @@ -38,25 +8,25 @@ Line terminators are specially remarkable when you are working with [Templates S
const input = `
Lorem ipsum dolor sit amet, consectetur adispiscing hello
world elit. Nam sit amet elit id risus aliquam porta.
`
`;

/hello.world/u.test(input)
// → false 🤔
```

As you can see, it doesn't match because a line break is present between `hello` and `world` words.

The problem, is that the dot, in fact, doest not math all characters. It only matches characters that JavaScript does not consider to be line terminators.
The "dot" doesn't match all characters. It only matches characters that JavaScript doesn't consider to be line terminators.

Sometimes you really do want to match any character, including new lines. This problem is so common that developers have started to use workarounds like this:

```js
const input = `
Lorem ipsum dolor sit amet, consectetur adispiscing hello
world elit. Nam sit amet elit id risus aliquam porta.
`
`;

/hello[\s\S]world/u.test(input);
/hello[\s\S]world/u.test(input)
// → true 😕
```

Expand All @@ -68,9 +38,9 @@ Another workaround is to use a negated empty character class:
const input = `
Lorem ipsum dolor sit amet, consectetur adispiscing hello
world elit. Nam sit amet elit id risus aliquam porta.
`
`;

/hello[^]world/u.test(input);
/hello[^]world/u.test(input)
// → true 🤷‍♂️
```

Expand All @@ -84,7 +54,7 @@ The new regular expression flag called dotAll mode (`s`) makes the dot truly mat
const input = `
Lorem ipsum dolor sit amet, consectetur adispiscing hello
world elit. Nam sit amet elit id risus aliquam porta.
`
`;

/hello.world/us.test(input)
// → true 🎉
Expand Down
53 changes: 53 additions & 0 deletions docs/regexp/global-flag.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Global flag (g)

The global flag indicates the regular expression should be tested against all possible matches in a string.

```js
const regex = new RegExp('o', 'g')

const greetings = 'Hello, how are you?'
const results = greetings.match(regex)

console.log(results.length) // => 3
```

If you just want to know if a string matches a regular expression, you use [RegExp.test()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test) for it.

```js
const regex = new RegExp('o', 'g')
const greetings = 'Hello, how are you?'

regex.test(greetings) // => true
```

When `.test` is invoked, the regex keeps internally the state of the search at [lastIndex](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastIndex) property.

This will be cause inconsistent results if you call test method several times:

```js
const regex = new RegExp('o', 'g')
const greetings = 'Hello, how are you?'

regex.lastIndex // => 0
regex.test(greetings) // => true
regex.lastIndex // => 5
regex.test(greetings) // => true
regex.lastIndex // => 9
regex.test(greetings) // => true
regex.lastIndex // => 17
regex.test(greetings) // => false
regex.lastIndex // => 0
```

As you can see, `lastIndex` will continue from the last matched result.

That can be easily avoided just wrapping into a function that will be executed from the beginning every time:

```js
const regex = new RegExp('o', 'g')
const greetings = 'Hello, how are you?'

const test = (regex, str) => regex.test(str)

test(regex, greetings) // => true
```
27 changes: 27 additions & 0 deletions docs/regexp/unicode-flag.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Unicode flag (u)

The unicode (`u`) flag is mandatory when working with Unicode strings, in particular when you might need to handle characters in astral planes, the ones that are not included in the first 1600 Unicode characters.

Like Emojis, for example, but not just those.

If you don’t add that flag, this simple regex that should match one character will not work, because for JavaScript that emoji is represented internally by 2 characters (see [Unicode in JavaScript](https://flaviocopes.com/javascript-unicode/)):

```js
/^.$/.test('a') //
/^.$/.test('🐶') //
/^.$/u.test('🐶') //
```

So, always use the `u` flag.

Keep in mind that Unicode, just normal characters, handle ranges:

```js
/[a-z]/.test('a') //
/[1-9]/.test('1') //

/[🐶-🦊]/u.test('🐺') //
/[🐶-🦊]/u.test('🐛') //
```

JavaScript checks the internal code representation, so `🐶 < 🐺 < 🦊` because `\u1F436 < \u1F43A < \u1F98A`. Check [emoji-regex](https://github.com/mathiasbynens/emoji-regex) for exploring more about that.
6 changes: 3 additions & 3 deletions docs/v8-tips/freeing-memory.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# Freeing memory

If you want to remove a property from an `Object`, probably you are considering use `delete`:
If you want to remove a property from an `Object`, probably you are considering use `delete`:

```js
var foo = { bar: 'hello world' }
const foo = { bar: 'hello world' }
delete foo.bar // Inefficient way (bad)
```

But this action have serious performance degradation. A most common technique with the same effect is assign `undefined`:

```js
var foo = { bar: 'hello world' }
const foo = { bar: 'hello world' }
foo.bar = undefined // Efficient way (good)
```

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Hidden class
# Hidden classes

JavaScript has limited compile-time type information: types can be changed at
runtime. This is why it is expensive to reason about JS types at compile time.
Expand All @@ -9,8 +9,8 @@ function Point (x, y) {
this.y = y
}

var p1 = new Point(11, 22) // => hidden Point class created
var p2 = new Point(33, 44) // => hidden Point class shared with p1
const p1 = new Point(11, 22) // => hidden Point class created
const p2 = new Point(33, 44) // => hidden Point class shared with p1
// At this point, p1 and p2 have a shared hidden class

p2.z = 55 // => another hidden class (Point) created, p1 !== p2
Expand Down
34 changes: 4 additions & 30 deletions docs/v8-tips/inline-initialization.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Inline Initialization

When you need to create a new `Object` (including `Array`s, because `Array`s in JavaScript are just `Object` with a magical [`.length`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length) property), you can do that following two approaches.
When you need to create a new `Object` (including and `Array`, because an `Array` in JavaScript are just `Object` with a magical [`.length`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length) property), you can do that following two approaches.

The first approach is to declare the new `Object` and later attach the information that we want to associate to the `Object`:

```js
var array = []
const array = []
array[0] = 77 // Allocates
array[1] = 88 // Allocates
array[2] = 0.5 // Allocates, converts
Expand All @@ -14,36 +14,10 @@ array[3] = true // Allocates, converts

In this example, the individual assignments are performed one after the other, and the assignment of `a[2]` causes the `Array` to be converted to an `Array` of unboxed doubles, but then the assignment of `a[3]` causes it to be re-converted back to an `Array` that can contain any values (`Number` or `Object`).

<br>

A more immediate solution is to attach all the information in one call:

```js
var array = [77, 88, 0.5, true]
const array = [77, 88, 0.5, true]
```

Now, the compiler knows the types of all of the elements in the literal, and the **hidden class** can be determined up front.

<br>

Imagine that you want to have an `Array` of elements but you can't build it in one call. You need to build it dynamically. How do you do it?

An immediate solution would be:

```js
var array = []
for (var i = 0; i < 10; i++) array[i] |= 0 // Oh no!
```

This piece of code is accessing an element that doesn't exist in the array, and in this case the specs says that it wants to return `undefined` that later is converted into `0`, so you need to do this extra effort simply to compare with `0`.


The array is being re-converted all time, but knowing how **hidden classes** act, a better solution in terms of performance would be:

```js
var array = []
array[0] = 0
for (var i = 0; i < 10; i++) array[i] |= i // Much better! 2x faster.
```

This second piece of code is simply better in terms of perfomance because we initialize a value out of the array with the same type as the element on the loops, so we avoid transforming the type of the array all the time.
In the above code, the compiler knows the types of all of the elements in the literal, and the [hidden classes](/v8-tips/hidden-classes) can be determined up front.
Loading

1 comment on commit e86b527

@vercel
Copy link

@vercel vercel bot commented on e86b527 Apr 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.