Use gender neutral pronouns
This commit is contained in:
parent
ded121f974
commit
e4a4426ff1
24 changed files with 37 additions and 37 deletions
|
@ -247,7 +247,7 @@ const myBirthday = '18.04.1982';
|
||||||
myBirthday = '01.01.2001'; // error, can't reassign the constant!
|
myBirthday = '01.01.2001'; // error, can't reassign the constant!
|
||||||
```
|
```
|
||||||
|
|
||||||
When a programmer is sure that the variable should never change, he can use `const` to guarantee it, and also to clearly show that fact to everyone.
|
When a programmer is sure that the variable should never change, they can use `const` to guarantee it, and also to clearly show that fact to everyone.
|
||||||
|
|
||||||
|
|
||||||
### Uppercase constants
|
### Uppercase constants
|
||||||
|
|
|
@ -4,7 +4,7 @@ importance: 5
|
||||||
|
|
||||||
# Repeat until the input is correct
|
# Repeat until the input is correct
|
||||||
|
|
||||||
Write a loop which prompts for a number greater than `100`. If the visitor enters another number -- ask him to input again.
|
Write a loop which prompts for a number greater than `100`. If the visitor enters another number -- ask them to input again.
|
||||||
|
|
||||||
The loop must ask for a number until either the visitor enters a number greater than `100` or cancels the input/enters an empty line.
|
The loop must ask for a number until either the visitor enters a number greater than `100` or cancels the input/enters an empty line.
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ More in: <info:variables> and <info:types>.
|
||||||
We're using a browser as a working environment, so basic UI functions will be:
|
We're using a browser as a working environment, so basic UI functions will be:
|
||||||
|
|
||||||
[`prompt(question[, default])`](mdn:api/Window/prompt)
|
[`prompt(question[, default])`](mdn:api/Window/prompt)
|
||||||
: Ask a `question`, and return either what the visitor entered or `null` if he pressed "cancel".
|
: Ask a `question`, and return either what the visitor entered or `null` if they pressed "cancel".
|
||||||
|
|
||||||
[`confirm(question)`](mdn:api/Window/confirm)
|
[`confirm(question)`](mdn:api/Window/confirm)
|
||||||
: Ask a `question` and suggest to choose between Ok and Cancel. The choice is returned as `true/false`.
|
: Ask a `question` and suggest to choose between Ok and Cancel. The choice is returned as `true/false`.
|
||||||
|
@ -111,7 +111,7 @@ We're using a browser as a working environment, so basic UI functions will be:
|
||||||
[`alert(message)`](mdn:api/Window/alert)
|
[`alert(message)`](mdn:api/Window/alert)
|
||||||
: Output a `message`.
|
: Output a `message`.
|
||||||
|
|
||||||
All these functions are *modal*, they pause the code execution and prevent the visitor from interacting with the page until he answers.
|
All these functions are *modal*, they pause the code execution and prevent the visitor from interacting with the page until they answer.
|
||||||
|
|
||||||
For instance:
|
For instance:
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ i = i ? i < 0 ? Math.max(0, len + i) : i : 0;
|
||||||
|
|
||||||
Cool, right? If you write like that, the developer who comes across this line and tries to understand what is the value of `i` is going to have a merry time. Then come to you, seeking for an answer.
|
Cool, right? If you write like that, the developer who comes across this line and tries to understand what is the value of `i` is going to have a merry time. Then come to you, seeking for an answer.
|
||||||
|
|
||||||
Tell him that shorter is always better. Initiate him into the paths of ninja.
|
Tell them that shorter is always better. Initiate them into the paths of ninja.
|
||||||
|
|
||||||
## One-letter variables
|
## One-letter variables
|
||||||
|
|
||||||
|
@ -45,11 +45,11 @@ completed.
|
||||||
|
|
||||||
Another way to code faster is to use single-letter variable names everywhere. Like `a`, `b` or `c`.
|
Another way to code faster is to use single-letter variable names everywhere. Like `a`, `b` or `c`.
|
||||||
|
|
||||||
A short variable disappears in the code like a real ninja in the forest. No one will be able to find it using "search" of the editor. And even if someone does, he won't be able to "decipher" what the name `a` or `b` means.
|
A short variable disappears in the code like a real ninja in the forest. No one will be able to find it using "search" of the editor. And even if someone does, they won't be able to "decipher" what the name `a` or `b` means.
|
||||||
|
|
||||||
...But there's an exception. A real ninja will never use `i` as the counter in a `"for"` loop. Anywhere, but not here. Look around, there are many more exotic letters. For instance, `x` or `y`.
|
...But there's an exception. A real ninja will never use `i` as the counter in a `"for"` loop. Anywhere, but not here. Look around, there are many more exotic letters. For instance, `x` or `y`.
|
||||||
|
|
||||||
An exotic variable as a loop counter is especially cool if the loop body takes 1-2 pages (make it longer if you can). Then if someone looks deep inside the loop, he won't be able to quickly figure out that the variable named `x` is the loop counter.
|
An exotic variable as a loop counter is especially cool if the loop body takes 1-2 pages (make it longer if you can). Then if someone looks deep inside the loop, they won't be able to quickly figure out that the variable named `x` is the loop counter.
|
||||||
|
|
||||||
## Use abbreviations
|
## Use abbreviations
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ function ninjaFunction(elem) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
A fellow programmer who wants to work with `elem` in the second half of the function will be surprised... Only during the debugging, after examining the code he will find out that he's working with a clone!
|
A fellow programmer who wants to work with `elem` in the second half of the function will be surprised... Only during the debugging, after examining the code they will find out that he's working with a clone!
|
||||||
|
|
||||||
Deadly effective even against an experienced ninja. Seen in code regularly.
|
Deadly effective even against an experienced ninja. Seen in code regularly.
|
||||||
|
|
||||||
|
@ -204,7 +204,7 @@ There are functions that look like they don't change anything. Like `isReady()`,
|
||||||
|
|
||||||
**A really beautiful trick is to add a "useful" action to them, besides the main task.**
|
**A really beautiful trick is to add a "useful" action to them, besides the main task.**
|
||||||
|
|
||||||
The expression of dazed surprise on the face of your colleague when he sees a function named `is..`, `check..` or `find...` changing something -- will definitely broaden your boundaries of reason.
|
The expression of dazed surprise on the face of your colleague when they see a function named `is..`, `check..` or `find...` changing something -- will definitely broaden your boundaries of reason.
|
||||||
|
|
||||||
**Another way to surprise is to return a non-standard result.**
|
**Another way to surprise is to return a non-standard result.**
|
||||||
|
|
||||||
|
@ -228,7 +228,7 @@ Additional actions should not be obvious from the function name. A true ninja co
|
||||||
|
|
||||||
**Joining several actions into one protects your code from reuse.**
|
**Joining several actions into one protects your code from reuse.**
|
||||||
|
|
||||||
Imagine, another developer wants only to check the email, and not output any message. Your function `validateEmail(email)` that does both will not suit him. So he won't break your meditation by asking anything about it.
|
Imagine, another developer wants only to check the email, and not output any message. Your function `validateEmail(email)` that does both will not suit them. So they won't break your meditation by asking anything about it.
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ Here Babel comes to the rescue.
|
||||||
|
|
||||||
Actually, there are two parts in Babel:
|
Actually, there are two parts in Babel:
|
||||||
|
|
||||||
1. First, the transpiler program, which rewrites the code. The developer runs it on his own computer. It rewrites the code into the older standard. And then the code is delivered to the website for users. Modern project build system like [webpack](http://webpack.github.io/) or [brunch](http://brunch.io/) provide means to run transpiler automatically on every code change, so that doesn't involve any time loss from our side.
|
1. First, the transpiler program, which rewrites the code. The developer runs it on their own computer. It rewrites the code into the older standard. And then the code is delivered to the website for users. Modern project build system like [webpack](http://webpack.github.io/) or [brunch](http://brunch.io/) provide means to run transpiler automatically on every code change, so that doesn't involve any time loss from our side.
|
||||||
|
|
||||||
2. Second, the polyfill.
|
2. Second, the polyfill.
|
||||||
|
|
||||||
|
|
|
@ -201,7 +201,7 @@ Strange! What is it then if not `0.3`?
|
||||||
alert( 0.1 + 0.2 ); // 0.30000000000000004
|
alert( 0.1 + 0.2 ); // 0.30000000000000004
|
||||||
```
|
```
|
||||||
|
|
||||||
Ouch! There are more consequences than an incorrect comparison here. Imagine you're making an e-shopping site and the visitor puts `$0.10` and `$0.20` goods into his chart. The order total will be `$0.30000000000000004`. That would surprise anyone.
|
Ouch! There are more consequences than an incorrect comparison here. Imagine you're making an e-shopping site and the visitor puts `$0.10` and `$0.20` goods into their chart. The order total will be `$0.30000000000000004`. That would surprise anyone.
|
||||||
|
|
||||||
But why does this happen?
|
But why does this happen?
|
||||||
|
|
||||||
|
|
|
@ -451,7 +451,7 @@ Let's recap these methods to avoid any confusion:
|
||||||
```smart header="Which one to choose?"
|
```smart header="Which one to choose?"
|
||||||
All of them can do the job. Formally, `substr` has a minor drawback: it is described not in the core JavaScript specification, but in Annex B, which covers browser-only features that exist mainly for historical reasons. So, non-browser environments may fail to support it. But in practice it works everywhere.
|
All of them can do the job. Formally, `substr` has a minor drawback: it is described not in the core JavaScript specification, but in Annex B, which covers browser-only features that exist mainly for historical reasons. So, non-browser environments may fail to support it. But in practice it works everywhere.
|
||||||
|
|
||||||
The author finds himself using `slice` almost all the time.
|
The author finds themself using `slice` almost all the time.
|
||||||
```
|
```
|
||||||
|
|
||||||
## Comparing strings
|
## Comparing strings
|
||||||
|
|
|
@ -369,7 +369,7 @@ It's rarely used, because square brackets `[]` are shorter. Also there's a trick
|
||||||
|
|
||||||
If `new Array` is called with a single argument which is a number, then it creates an array *without items, but with the given length*.
|
If `new Array` is called with a single argument which is a number, then it creates an array *without items, but with the given length*.
|
||||||
|
|
||||||
Let's see how one can shoot himself in the foot:
|
Let's see how one can shoot themself in the foot:
|
||||||
|
|
||||||
```js run
|
```js run
|
||||||
let arr = new Array(2); // will it create an array of [2] ?
|
let arr = new Array(2); // will it create an array of [2] ?
|
||||||
|
|
|
@ -47,7 +47,7 @@ For instance:
|
||||||
```js run
|
```js run
|
||||||
let john = { name: "John" };
|
let john = { name: "John" };
|
||||||
|
|
||||||
// for every user, let's store his visits count
|
// for every user, let's store their visits count
|
||||||
let visitsCountMap = new Map();
|
let visitsCountMap = new Map();
|
||||||
|
|
||||||
// john is the key for the map
|
// john is the key for the map
|
||||||
|
@ -332,7 +332,7 @@ That's useful for situations when we have a main storage for the objects somewhe
|
||||||
|
|
||||||
Let's look at an example.
|
Let's look at an example.
|
||||||
|
|
||||||
For instance, we have code that keeps a visit count for each user. The information is stored in a map: a user is the key and the visit count is the value. When a user leaves, we don't want to store his visit count anymore.
|
For instance, we have code that keeps a visit count for each user. The information is stored in a map: a user is the key and the visit count is the value. When a user leaves, we don't want to store their visit count anymore.
|
||||||
|
|
||||||
One way would be to keep track of leaving users and clean up the storage manually:
|
One way would be to keep track of leaving users and clean up the storage manually:
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ So we'll assign `throttle(update, 100)` as the function to run on each mouse mov
|
||||||
|
|
||||||
Visually, it will look like this:
|
Visually, it will look like this:
|
||||||
|
|
||||||
1. For the first mouse movement the decorated variant passes the call to `update`. That's important, the user sees our reaction to his move immediately.
|
1. For the first mouse movement the decorated variant passes the call to `update`. That's important, the user sees our reaction to their move immediately.
|
||||||
2. Then as the mouse moves on, until `100ms` nothing happens. The decorated variant ignores calls.
|
2. Then as the mouse moves on, until `100ms` nothing happens. The decorated variant ignores calls.
|
||||||
3. At the end of `100ms` -- one more `update` happens with the last coordinates.
|
3. At the end of `100ms` -- one more `update` happens with the last coordinates.
|
||||||
4. Then, finally, the mouse stops somewhere. The decorated variant waits until `100ms` expire and then runs `update` runs with last coordinates. So, perhaps the most important, the final mouse coordinates are processed.
|
4. Then, finally, the mouse stops somewhere. The decorated variant waits until `100ms` expire and then runs `update` runs with last coordinates. So, perhaps the most important, the final mouse coordinates are processed.
|
||||||
|
|
|
@ -118,7 +118,7 @@ user.name = "Pete"; // Error: Cannot assign to read only property 'name'...
|
||||||
*/!*
|
*/!*
|
||||||
```
|
```
|
||||||
|
|
||||||
Now no one can change the name of our user, unless he applies his own `defineProperty` to override ours.
|
Now no one can change the name of our user, unless they apply their own `defineProperty` to override ours.
|
||||||
|
|
||||||
Here's the same operation, but for the case when a property doesn't exist:
|
Here's the same operation, but for the case when a property doesn't exist:
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ alert( lazy.stomach ); // <nothing>
|
||||||
|
|
||||||
Now all works fine, because `this.stomach=` does not perform a lookup of `stomach`. The value is written directly into `this` object.
|
Now all works fine, because `this.stomach=` does not perform a lookup of `stomach`. The value is written directly into `this` object.
|
||||||
|
|
||||||
Also we can totally evade the problem by making sure that each hamster has his own stomach:
|
Also we can totally evade the problem by making sure that each hamster has their own stomach:
|
||||||
|
|
||||||
```js run
|
```js run
|
||||||
let hamster = {
|
let hamster = {
|
||||||
|
|
|
@ -194,7 +194,7 @@ You can find more detailed information about JSON in the <info:json> chapter.
|
||||||
|
|
||||||
Should we be satisfied with that? Of course, not!
|
Should we be satisfied with that? Of course, not!
|
||||||
|
|
||||||
This way, if something's wrong with the data, the visitor will never know that (unless he opens developer console). And people really don't like when something "just dies" without any error message.
|
This way, if something's wrong with the data, the visitor will never know that (unless they open the developer console). And people really don't like when something "just dies" without any error message.
|
||||||
|
|
||||||
Let's use `try..catch` to handle the error:
|
Let's use `try..catch` to handle the error:
|
||||||
|
|
||||||
|
@ -575,7 +575,7 @@ The information from this section is not a part of the core JavaScript.
|
||||||
|
|
||||||
Let's imagine we've got a fatal error outside of `try..catch`, and the script died. Like a programming error or something else terrible.
|
Let's imagine we've got a fatal error outside of `try..catch`, and the script died. Like a programming error or something else terrible.
|
||||||
|
|
||||||
Is there a way to react on such occurrences? We may want to log the error, show something to the user (normally he doesn't see error messages) etc.
|
Is there a way to react on such occurrences? We may want to log the error, show something to the user (normally they don't see error messages) etc.
|
||||||
|
|
||||||
There is none in the specification, but environments usually provide it, because it's really useful. For instance, Node.JS has [process.on('uncaughtException')](https://nodejs.org/api/process.html#process_event_uncaughtexception) for that. And in the browser we can assign a function to special [window.onerror](mdn:api/GlobalEventHandlers/onerror) property. It will run in case of an uncaught error.
|
There is none in the specification, but environments usually provide it, because it's really useful. For instance, Node.JS has [process.on('uncaughtException')](https://nodejs.org/api/process.html#process_event_uncaughtexception) for that. And in the browser we can assign a function to special [window.onerror](mdn:api/GlobalEventHandlers/onerror) property. It will run in case of an uncaught error.
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ importance: 5
|
||||||
|
|
||||||
# Catch links in the element
|
# Catch links in the element
|
||||||
|
|
||||||
Make all links inside the element with `id="contents"` ask the user if he really wants to leave. And if he doesn't then don't follow.
|
Make all links inside the element with `id="contents"` ask the user if they really want to leave. And if they don't then don't follow.
|
||||||
|
|
||||||
Like this:
|
Like this:
|
||||||
|
|
||||||
|
|
|
@ -175,7 +175,7 @@ Now if you double-click on "Unselectable", it doesn't get selected. Seems to wor
|
||||||
|
|
||||||
...But there is a potential problem! The text became truly unselectable. Even if a user starts the selection from "Before" and ends with "After", the selection skips "Unselectable" part. Do we really want to make our text unselectable?
|
...But there is a potential problem! The text became truly unselectable. Even if a user starts the selection from "Before" and ends with "After", the selection skips "Unselectable" part. Do we really want to make our text unselectable?
|
||||||
|
|
||||||
Most of time, we don't. A user may have valid reasons to select the text, for copying or other needs. That may be inconvenient if we don't allow him to do it. So this solution is not that good.
|
Most of time, we don't. A user may have valid reasons to select the text, for copying or other needs. That may be inconvenient if we don't allow them to do it. So this solution is not that good.
|
||||||
|
|
||||||
What we want is to prevent the selection on double-click, that's it.
|
What we want is to prevent the selection on double-click, that's it.
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ Each event may be useful:
|
||||||
|
|
||||||
- `DOMContentLoaded` event -- DOM is ready, so the handler can lookup DOM nodes, initialize the interface.
|
- `DOMContentLoaded` event -- DOM is ready, so the handler can lookup DOM nodes, initialize the interface.
|
||||||
- `load` event -- additional resources are loaded, we can get image sizes (if not specified in HTML/CSS) etc.
|
- `load` event -- additional resources are loaded, we can get image sizes (if not specified in HTML/CSS) etc.
|
||||||
- `beforeunload/unload` event -- the user is leaving: we can check if the user saved the changes and ask him whether he really wants to leave.
|
- `beforeunload/unload` event -- the user is leaving: we can check if the user saved the changes and ask them whether they really want to leave.
|
||||||
|
|
||||||
Let's explore the details of these events.
|
Let's explore the details of these events.
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ importance: 5
|
||||||
|
|
||||||
Write a function that shows a tooltip over an element only if the visitor moves the mouse *over it*, but not *through it*.
|
Write a function that shows a tooltip over an element only if the visitor moves the mouse *over it*, but not *through it*.
|
||||||
|
|
||||||
In other words, if the visitor moves the mouse on the element and stopped -- show the tooltip. And if he just moved the mouse through fast, then no need, who wants extra blinking?
|
In other words, if the visitor moves the mouse on the element and stopped -- show the tooltip. And if they just moved the mouse through fast, then no need, who wants extra blinking?
|
||||||
|
|
||||||
Technically, we can measure the mouse speed over the element, and if it's slow then we assume that it comes "over the element" and show the tooltip, if it's fast -- then we ignore it.
|
Technically, we can measure the mouse speed over the element, and if it's slow then we assume that it comes "over the element" and show the tooltip, if it's fast -- then we ignore it.
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
// JavaScript does not get the "keyup" event
|
// JavaScript does not get the "keyup" event
|
||||||
// and pressed set will keep assuming that the key is pressed
|
// and pressed set will keep assuming that the key is pressed
|
||||||
// so, to evade "sticky" keys, we reset the status
|
// so, to evade "sticky" keys, we reset the status
|
||||||
// if the user wants to run the hotkey again - let him press all keys again
|
// if the user wants to run the hotkey again - let them press all keys again
|
||||||
pressed.clear();
|
pressed.clear();
|
||||||
|
|
||||||
func();
|
func();
|
||||||
|
|
|
@ -4,7 +4,7 @@ importance: 4
|
||||||
|
|
||||||
# Load visible images
|
# Load visible images
|
||||||
|
|
||||||
Let's say we have a slow-speed client and want to save his mobile traffic.
|
Let's say we have a slow-speed client and want to save their mobile traffic.
|
||||||
|
|
||||||
For that purpose we decide not to show images immediately, but rather replace them with placeholders, like this:
|
For that purpose we decide not to show images immediately, but rather replace them with placeholders, like this:
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ importance: 5
|
||||||
|
|
||||||
Create a function `showPrompt(html, callback)` that shows a form with the message `html`, an input field and buttons `OK/CANCEL`.
|
Create a function `showPrompt(html, callback)` that shows a form with the message `html`, an input field and buttons `OK/CANCEL`.
|
||||||
|
|
||||||
- A user should type something into a text field and press `key:Enter` or the OK button, then `callback(value)` is called with the value he entered.
|
- A user should type something into a text field and press `key:Enter` or the OK button, then `callback(value)` is called with the value they entered.
|
||||||
- Otherwise if the user presses `key:Esc` or CANCEL, then `callback(null)` is called.
|
- Otherwise if the user presses `key:Esc` or CANCEL, then `callback(null)` is called.
|
||||||
|
|
||||||
In both cases that ends the input process and removes the form.
|
In both cases that ends the input process and removes the form.
|
||||||
|
|
|
@ -176,7 +176,7 @@ Still, there are some things that can be done.
|
||||||
For instance:
|
For instance:
|
||||||
|
|
||||||
- When we open a popup, it's might be a good idea to run a `newWindow.focus()` on it. Just in case, for some OS/browser combinations it ensures that the user is in the new window now.
|
- When we open a popup, it's might be a good idea to run a `newWindow.focus()` on it. Just in case, for some OS/browser combinations it ensures that the user is in the new window now.
|
||||||
- If we want to track when a visitor actually uses our web-app, we can track `window.onfocus/onblur`. That allows us to suspend/resume in-page activities, animations etc. But please note that the `blur` event means that the visitor switched out from the window, but he still may observe it. The window is in the background, but still may be visible.
|
- If we want to track when a visitor actually uses our web-app, we can track `window.onfocus/onblur`. That allows us to suspend/resume in-page activities, animations etc. But please note that the `blur` event means that the visitor switched out from the window, but they still may observe it. The window is in the background, but still may be visible.
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ All we need to attack -- is to position the `<iframe>` on the evil page in such
|
||||||
```smart header="Clickjacking is for clicks, not for keyboard"
|
```smart header="Clickjacking is for clicks, not for keyboard"
|
||||||
The attack only affects mouse actions.
|
The attack only affects mouse actions.
|
||||||
|
|
||||||
Technically, if we have a text field to hack, then we can position an iframe in such a way that text fields overlap each other. So when a visitor tries to focus on the input he sees on the page, he actually focuses on the input inside the iframe.
|
Technically, if we have a text field to hack, then we can position an iframe in such a way that text fields overlap each other. So when a visitor tries to focus on the input they see on the page, they actually focus on the input inside the iframe.
|
||||||
|
|
||||||
But then there's a problem. Everything that the visitor types will be hidden, because the iframe is not visible.
|
But then there's a problem. Everything that the visitor types will be hidden, because the iframe is not visible.
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ This not a reliable defence, because there are many ways to hack around it. Let'
|
||||||
|
|
||||||
We can block the transition caused by changing `top.location` in the [beforeunload](info:onload-ondomcontentloaded#window.onbeforeunload) event.
|
We can block the transition caused by changing `top.location` in the [beforeunload](info:onload-ondomcontentloaded#window.onbeforeunload) event.
|
||||||
|
|
||||||
The top page (belonging to the hacker) sets a handler to it, and when the `iframe` tries to change `top.location` the visitor gets a message asking him whether he wants to leave.
|
The top page (belonging to the hacker) sets a handler to it, and when the `iframe` tries to change `top.location` the visitor gets a message asking them whether they want to leave.
|
||||||
|
|
||||||
Like this:
|
Like this:
|
||||||
```js
|
```js
|
||||||
|
@ -99,7 +99,7 @@ window.onbeforeunload = function() {
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
In most cases the visitor would answer negatively, because he doesn't know about the iframe, all he can see is the top page, leading him to think there is no reason to leave. So `top.location` won't change!
|
In most cases the visitor would answer negatively because they don't know about the iframe - all they can see is the top page, leading them to think there is no reason to leave. So `top.location` won't change!
|
||||||
|
|
||||||
In action:
|
In action:
|
||||||
|
|
||||||
|
@ -188,9 +188,9 @@ The demo:
|
||||||
|
|
||||||
Clickjacking is a way to "trick" users into clicking on a malicious site without even knowing what's happening. That's dangerous if there are important click-activated actions.
|
Clickjacking is a way to "trick" users into clicking on a malicious site without even knowing what's happening. That's dangerous if there are important click-activated actions.
|
||||||
|
|
||||||
A hacker can post a link to his evil page in a message, or lure visitors to his page by some other means. There are many variations.
|
A hacker can post a link to their evil page in a message, or lure visitors to their page by some other means. There are many variations.
|
||||||
|
|
||||||
From one perspective -- the attack is "not deep": all a hacker is doing is intercepting a single click. But from another perspective, if the hacker knows that after the click another control will appear, then he may use cunning messages to coerce the user into clicking on them as well.
|
From one perspective -- the attack is "not deep": all a hacker is doing is intercepting a single click. But from another perspective, if the hacker knows that after the click another control will appear, then they may use cunning messages to coerce the user into clicking on them as well.
|
||||||
|
|
||||||
The attack is quite dangerous, because when we engineer the UI we usually don't anticipate that a hacker may click on behalf of the visitor. So vulnerabilities can be found in totally unexpected places.
|
The attack is quite dangerous, because when we engineer the UI we usually don't anticipate that a hacker may click on behalf of the visitor. So vulnerabilities can be found in totally unexpected places.
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,9 @@
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<p>After a click on the button the visitor gets a "strange" question about whether he wants to leave.</p>
|
<p>After a click on the button the visitor gets a "strange" question about whether they want to leave.</p>
|
||||||
|
|
||||||
<p>Probably he would respond "No", and the iframe protection is hacked.</p>
|
<p>Probably they would respond "No", and the iframe protection is hacked.</p>
|
||||||
|
|
||||||
<button onclick="attack()">Add a "protected" iframe</button>
|
<button onclick="attack()">Add a "protected" iframe</button>
|
||||||
|
|
||||||
|
|
|
@ -234,7 +234,7 @@ Using a function gives us the ultimate replacement power, because it gets all th
|
||||||
|
|
||||||
Let's move on to the methods of `RegExp` class, that are callable on regexps themselves.
|
Let's move on to the methods of `RegExp` class, that are callable on regexps themselves.
|
||||||
|
|
||||||
The `test` method looks for any match and returns `true/false` whether he found it.
|
The `test` method looks for any match and returns `true/false` whether they found it.
|
||||||
|
|
||||||
So it's basically the same as `str.search(reg) != -1`, for instance:
|
So it's basically the same as `str.search(reg) != -1`, for instance:
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue