Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion package-lock.json

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

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"how-to-keep-learning",
"introduction-functional-programming",
"how-to-tech-writing",
"howto-use-react-keys"
"howto-use-react-keys",
"what-is-throw"
],
"devDependencies": {
"@slidev/cli": "^0.47.5",
Expand Down
5 changes: 5 additions & 0 deletions reuse/styles/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,11 @@ deepl-inline-trigger {
font-weight: 600;
}

#app code[class*="language-"],
#app pre[class*="language-"] {
background-color: revert;
}

/* strong */
#app strong {
font-size: 1.25em;
Expand Down
46 changes: 46 additions & 0 deletions what-is-throw/components/Tips.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<script lang="ts" setup>
import { ref } from "vue";
const props = defineProps<{
title: string;
level?: 2 | 3 | 4 | 5 | 6;
}>();

const heading = `h${props.level ?? 2}`;
</script>

<template>
<div class="container">
<component :is="heading" class="heading">{{ props.title }}</component>
<p class="content"><slot></slot></p>
</div>
</template>

<style scoped>
#app {
.container {
position: relative;
background-color: var(--c-main);
border-radius: 10px;
}
.heading {
display: flex;
margin: 0;
padding: 0 8px;
width: 100%;
font-size: 1rem;
color: var(--c-main);
font-weight: 900;
background-color: var(--c-base);
border-radius: 8px 8px 0 0;
}
.heading::before {
all: revert;
content: "🤔";
padding: 0 4px;
}
.content {
margin: 0;
padding: 8px 16px;
}
}
</style>
15 changes: 15 additions & 0 deletions what-is-throw/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "@slide/what-is-throw",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "slidev build",
"export": "slidev export",
"dev": "slidev"
},
"keywords": [],
"author": "ken7253 <ken7253@gmail.com>",
"license": "MIT"
}
158 changes: 158 additions & 0 deletions what-is-throw/slides.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
---
theme: default
titleTemplate: '%s - ken7253'
colorSchema: 'dark'
fonts:
sans: 'M PLUS 2'
mono: 'M PLUS 1 Code'
---

# 「throw」とはなにか

---
src: "../reuse/me.md"
---

---

## よくある使い方

想定していない値を受け取った場合などに例外を投げるために利用される。

```ts
/** 引数をすべて足し合わせる関数 */
export const sum = (...args: number[]) => {
if (args.some(num => (isFinite(num)))) {
// NaNやInfinityが引数に含まれていたら例外を投げる
throw new Error('加算できない数値が含まれています');
}

// 加算できる数値であることを確認してからすべての数値を足し合わせる
return args.reduce((acc, val) => acc + val, 0);
}
```

---

## よくある使い方

想定していない値を受け取った場合などに例外を投げるために利用される。

```ts{4-5}
/** 引数をすべて足し合わせる関数 */
export const sum = (...args: number[]) => {
if (args.some(num => (isFinite(num)))) {
// NaNやInfinityが引数に含まれていたら例外を投げる
throw new Error('加算できない数値が含まれています');
}

// 加算できる数値であることを確認してからすべての数値を足し合わせる
return args.reduce((acc, val) => acc + val, 0);
}
```

---

## 関数を利用する側

関数の呼び出し側では`try...catch`を使うことで例外を受け取って安全に処理ができる。

```ts
import { sum } from "./util/math";
import { userInput } from "./ui/input";

userInput.onChange((inputList: number[]) => {
// ユーザーの入力がある度に履歴を含めた配列を受け取る
try {
const result = sum(inputList);
console.log(result);
} catch (err) {
console.log(err);
}
});
```

---

## 関数を利用する側

関数の呼び出し側では`try...catch`を使うことで例外を受け取って安全に処理ができる。

```ts{9-11}
import { sum } from "./util/math";
import { userInput } from "./ui/input";

userInput.onChange((inputList: number[]) => {
// ユーザーの入力がある度に履歴を含めた配列を受け取る
try {
const result = sum(inputList);
console.log(result);
} catch (err) {
console.log(err);
}
});
```

---
layout: center
---

## 今回はそんな`throw`の話

---

## throwとはなにか

MDNで調べてみるとこのような説明がある。

> `throw`文は、ユーザー定義の例外を発生させます。現在の関数の実行を停止し(`throw`の後の文は実行されません)、コールスタック内の最初の`catch`ブロックに制御を移します。呼び出し元の関数に`catch`ブロックが存在しない場合は、プログラムが終了します。

[throw - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/throw)より引用

おそらくこれを読んで分かるのはもともと例外を知っている人だと思う。

なので一度意味を整理してみる。

---

## つまりどういうことか

`throw`とは例外を発生させるための構文

### 例外とはなにか

- 関数の実行を停止する
- `catch`されるまでコールスタックをたどる
- 任意の値を`catch`節に渡す

---

## 関数の実行を停止する

基本的には`return`と同じ性質だと思えばいい

```ts
/** 引数をすべて足し合わせる関数 */
export const sum = (...args: number[]) => {
if (args.some(num => (isFinite(num)))) {
// NaNやInfinityが引数に含まれていたら例外を投げる
throw new Error('加算できない数値が含まれています');
}

// 加算できる数値であることを確認してからすべての数値を足し合わせる
return args.reduce((acc, val) => acc + val, 0);
}
```

この関数の中で`throw`に到達した場合はそれ以降の処理は実行されない。

つまりこの関数の場合、値を返すことはなく例外を投げる。

---

## catch されるまでコールスタックをたどる

<Tips title="コールスタック" level="3">
コールスタック ≒ 関数の呼び出し順の記録<br>
関数<code>a()</code>が関数<code>b()</code>を呼んでその中でさらに関数<code>c()</code>を呼んで…
</Tips>
2 changes: 2 additions & 0 deletions what-is-throw/styles/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import "./mod.css"
import "@slide/reuse/styles";
Empty file added what-is-throw/styles/mod.css
Empty file.