Skip to content

Commit

Permalink
feat: translation of Methods of primitives (#60)
Browse files Browse the repository at this point in the history
  • Loading branch information
lenchen1112 authored Oct 13, 2019
1 parent afacdfd commit 3f1e747
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 64 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

Try running it:
試著跑看看:

```js run
let str = "Hello";
Expand All @@ -9,16 +8,17 @@ str.test = 5; // (*)
alert(str.test);
```

Depending on whether you have `use strict` or not, the result may be:
1. `undefined` (no strict mode)
2. An error (strict mode).
根據你是否有使用 `use strict`,結果可能會是:
1. `undefined`(沒用嚴格模式)
2. 錯誤(嚴格模式)

為什麼?來重播一下 `(*)` 這行發生什麼事:

Why? Let's replay what's happening at line `(*)`:
1.`str` 的屬性被存取時,"包裝物件" 被建立了。
2. 在嚴格模式下,寫入它會造成錯誤。
3. 否則,該屬性操作會被執行,該物件得到 `test` 的屬性,但在那之後 "包裝物件" 消失了,所以最後一行的 `str` 沒有該屬性的蹤跡。

1. When a property of `str` is accessed, a "wrapper object" is created.
2. In strict mode, writing into it is an error.
3. Otherwise, the operation with the property is carried on, the object gets the `test` property, but after that the "wrapper object" disappears, so in the last line `str` has no trace of the property.
**這個例子清楚顯示原生類型並非物件。**

**This example clearly shows that primitives are not objects.**
它們不能儲存額外的資料。

They can't store additional data.
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ importance: 5

---

# Can I add a string property?
# 我可以為字串加入屬性嗎?


Consider the following code:
考慮以下程式碼:

```js
let str = "Hello";
Expand All @@ -15,4 +14,5 @@ str.test = 5;
alert(str.test);
```

How do you think, will it work? What will be shown?
你覺得如何,這樣行嗎?會顯示什麼?

99 changes: 50 additions & 49 deletions 1-js/05-data-types/01-primitives-methods/article.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
# Methods of primitives
# 原生類型的方法

JavaScript allows us to work with primitives (strings, numbers, etc.) as if they were objects. They also provide methods to call as such. We will study those soon, but first we'll see how it works because, of course, primitives are not objects (and here we will make it even clearer).
JavaScript 允許我們像物件一樣來使用原生類型(字串、數值等等),它們也提供類似的呼叫方法。我們很快會學到,但首先要來看看它是怎麼運作的,沒錯,因為原生類型並不真的是物件(且在此我們要來把它弄得更清楚點)。

Let's look at the key distinctions between primitives and objects.
來看看原生類型與物件之間的關鍵區別吧。

A primitive
原生值

- Is a value of a primitive type.
- There are 6 primitive types: `string`, `number`, `boolean`, `symbol`, `null` and `undefined`.
- 是個原生類型的值。
- 有六種原生類型:`字串(string``數值(number``布林(boolean``符號(symbol``null` `undefined`

An object
物件

- Is capable of storing multiple values as properties.
- Can be created with `{}`, for instance: `{name: "John", age: 30}`. There are other kinds of objects in JavaScript: functions, for example, are objects.
- 能夠儲存多個值作為屬性。
- 可以經由 `{}` 建立,例如:`{name: "John", age: 30}`。在 JavaScript 中還有其它種類的物件:例如函式就是物件。

One of the best things about objects is that we can store a function as one of its properties.
物件最棒的事情之一就是我們可以存放函式作為它的屬性。

```js run
let john = {
Expand All @@ -27,102 +27,103 @@ let john = {
john.sayHi(); // Hi buddy!
```

So here we've made an object `john` with the method `sayHi`.
在這我們已經建立一個有著 `sayHi` 方法的物件 `john` 了。

Many built-in objects already exist, such as those that work with dates, errors, HTML elements, etc. They have different properties and methods.
已存在許多內建物件,像是用來處理日期、錯誤、HTML 元素等等的,它們有著不一樣的屬性與方法。

But, these features come with a cost!
但是,這些功能是有代價的!

Objects are "heavier" than primitives. They require additional resources to support the internal machinery.
物件比原生類型 "更笨重",它們需要額外資源來支援內部機制。

## A primitive as an object
## 作為物件的原生類型

Here's the paradox faced by the creator of JavaScript:
JavaScript 的建立者們面臨了這樣的一個矛盾:

- There are many things one would want to do with a primitive like a string or a number. It would be great to access them as methods.
- Primitives must be as fast and lightweight as possible.
- 人們想對字串或數值這樣的原生類型做許多事,若能透過其方法來存取就太棒了。
- 原生類型應該要盡可能的快速和輕量化。

The solution looks a little bit awkward, but here it is:
解法看起來有點笨,但就是這樣:

1. Primitives are still primitive. A single value, as desired.
2. The language allows access to methods and properties of strings, numbers, booleans and symbols.
3. In order for that to work, a special "object wrapper" that provides the extra functionality is created, and then is destroyed.
1. 原生類型依然是原生的,與預期相同,一個簡單的值。
2. 語言允許存取字串、數值、布林與符號的方法與屬性。
3. 為了要讓其可以運作,建立一個特殊的 "物件包裝" 並提供額外的功能,然後運作後再銷毀。

The "object wrappers" are different for each primitive type and are called: `String`, `Number`, `Boolean` and `Symbol`. Thus, they provide different sets of methods.
"物件包裝" 對於每種原生類型都不同,名為:`String``Number``Boolean` `Symbol`。因此,它們提供不同的方法集合。

For instance, there exists a string method [str.toUpperCase()](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase) that returns a capitalized `str`.
舉個例,有個字串方法 [str.toUpperCase()](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase) 回傳被大寫的 `str`

Here's how it works:
這邊是它的用法:

```js run
let str = "Hello";

alert( str.toUpperCase() ); // HELLO
```

Simple, right? Here's what actually happens in `str.toUpperCase()`:
簡單,對吧?這邊是實際上在 `str.toUpperCase()` 內到底發生了什麼事:

1. The string `str` is a primitive. So in the moment of accessing its property, a special object is created that knows the value of the string, and has useful methods, like `toUpperCase()`.
2. That method runs and returns a new string (shown by `alert`).
3. The special object is destroyed, leaving the primitive `str` alone.
1. 字串 `str` 是個原生數值,所以在存取它屬性的當下,建立一個知道字串值的特殊物件,並包含有用的方法,像是 `toUpperCase()`
2. 該方法被執行且回傳一個新字串(被 `alert` 顯示)。
3. 該特殊物件被銷毀,獨自留下原生類型 `str`

So primitives can provide methods, but they still remain lightweight.
因此原生類型可以提供方法,但它們依然維持輕量化。

The JavaScript engine highly optimizes this process. It may even skip the creation of the extra object at all. But it must still adhere to the specification and behave as if it creates one.
JavaScript 引擎高度優化這個過程,它甚至會完全跳過建立額外的物件,但仍必須堅守規格且表現的像是它有建立一樣。

A number has methods of its own, for instance, [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) rounds the number to the given precision:
數值有著自己的方法,例如,[toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) 四捨五入至給予的精度:

```js run
let n = 1.23456;

alert( n.toFixed(2) ); // 1.23
```

We'll see more specific methods in chapters <info:number> and <info:string>.
我們將會在章節 <info:number> <info:string> 看到更多特定的方法。

````warn header="建構子 `String/Number/Boolean` 僅供內部使用"
有些像是 Java 的語言允許我們使用像是 `new Number(1)``new Boolean(false)` 的語法,來對原生類型明確建立 "包裝物件"

````warn header="Constructors `String/Number/Boolean` are for internal use only"
Some languages like Java allow us to explicitly create "wrapper objects" for primitives using a syntax like `new Number(1)` or `new Boolean(false)`.
在 JavaScript,因為歷史因素的關係也可以這麼做,但極度 **不建議**,這樣做的話在很多地方的東西可能會變得讓人抓狂。

In JavaScript, that's also possible for historical reasons, but highly **unrecommended**. Things will go crazy in several places.

For instance:
舉個例:

```js run
alert( typeof 0 ); // "number"

alert( typeof new Number(0) ); // "object"!
```

Objects are always truthy in `if`, so here the alert will show up:
物件在 `if` 中永遠是真值,所以這邊的 alert 將會被顯示:

```js run
let zero = new Number(0);

if (zero) { // zero is true, because it's an object
if (zero) { // zero true,因為它是物件
alert( "zero is truthy!?!" );
}
```

On the other hand, using the same functions `String/Number/Boolean` without `new` is a totally sane and useful thing. They convert a value to the corresponding type: to a string, a number, or a boolean (primitive).
另一方面,不透過 `new` 而使用同樣的函式 `String/Number/Boolean` 是明智且有用的用法,它們將值轉換為對應的類型:字串、數值或布林(原生類型)。

例如,這樣完全有效:

For example, this is entirely valid:
```js
let num = Number("123"); // convert a string to number
let num = Number("123"); // 轉換字串為數值
```
````
````warn header="null/undefined have no methods"
The special primitives `null` and `undefined` are exceptions. They have no corresponding "wrapper objects" and provide no methods. In a sense, they are "the most primitive".
````warn header="null/undefined 沒有任何方法"
特殊的原生類型 `null` `undefined` 是例外。它們沒有對應的 "包裝物件" 且沒有提供任何方法。在否種意義上,它們 "最原生"。
An attempt to access a property of such value would give the error:
試圖存取這種值的屬性將會給予錯誤:
```js run
alert(null.test); // error
````

## Summary
## 總結

- 除了 `null``undefined` 以外的原生類型提供許多有幫助的方法,我們會在接下來的章節學習它們。
- 正確地說,這些方法經由臨時物件來運作,但 JavaScript 引擎已經對此做了良好的調整來內部優化。所以它們呼叫起來資源消耗不高。

- Primitives except `null` and `undefined` provide many helpful methods. We will study those in the upcoming chapters.
- Formally, these methods work via temporary objects, but JavaScript engines are well tuned to optimize that internally, so they are not expensive to call.

0 comments on commit 3f1e747

Please sign in to comment.