# Lesson 1: Syntax

這堂課不講基礎只講差異，有需要[請看基礎](https://www.udacity.com/course/intro-to-javascript--ud803)。

{% hint style="warning" %}
Javascript的版本很多，這邊討論SE6。
{% endhint %}

## Let and Const <a href="#header-title" id="header-title"></a>

There are now two new ways to declare variables in JavaScript: **let** and **const**.

Up until now, the only way to declare a variable in JavaScript was to use the keyword `var`. To understand why `let` and `const` were added, it’s probably best to look at an example of when using `var` can get us into trouble.

## Template Literals

**Template literals** are essentially string literals that include embedded expressions.

Denoted with backticks (\` \`) instead of single quotes ( `''` ) or double quotes ( `""` ), template literals can contain placeholders which are represented using `${expression}`. This makes it *much easier* to build strings.

```javascript
/*
 * Programming Quiz: Build an HTML Fragment (1-2)
 */

const cheetah = {
    name: 'Cheetah',
    scientificName: 'Acinonyx jubatus',
    lifespan: '10-12 years',
    speed: '68-75 mph',
    diet: 'carnivore',
    summary: 'Fastest mammal on land, the cheetah can reach speeds of 60 or perhaps even 70 miles (97 or 113 kilometers) an hour over short distances. It usually chases its prey at only about half that speed, however. After a chase, a cheetah needs half an hour to catch its breath before it can eat.',
    fact: 'Cheetahs have “tear marks” that run from the inside corners of their eyes down to the outside edges of their mouth.'
};

// creates an animal trading card
function createAnimalTradingCardHTML(animal) {
    const cardHTML = `<div class="card">
        <h3 class="name"> ${animal.name} </h3>
        <img src="${animal.name}.jpg" alt="${animal.name}" class="picture">
        <div class="description">
            <p class="fact"> ${animal.fact} </p>
            <ul class="details">
                <li><span class="bold">Scientific Name</span>: ${animal.scientificName} </li>
                <li><span class="bold">Average Lifespan</span>: ${animal.lifespan} </li>
                <li><span class="bold">Average Speed</span>: ${animal.speed}</li>
                <li><span class="bold">Diet</span>: ${animal.diet} </li>
            </ul>
            <p class="brief"> ${animal.summary} </p> 
        </div> 
    </div>`;

    return cardHTML;
}

console.log(createAnimalTradingCardHTML(cheetah));

```

## Destructuring <a href="#header-title" id="header-title"></a>

**Destructuring** borrows inspiration from languages like [Perl](https://en.wikipedia.org/wiki/Perl) and [Python](https://en.wikipedia.org/wiki/Python_\(programming_language\)) by allowing you to specify the elements you want to extract from an array or object *on the left side of an assignment*. It sounds a little weird, but you can actually achieve the same result as before, but with much less code; and it's still easy to understand.

Let’s take a look at both examples rewritten using destructuring.

### Destructuring values from an array

```javascript
const point = [10, 25, -34];

const [x, y, z] = point;

console.log(x, y, z);
```

```javascript
/*
 * Programming Quiz: Destructuring Arrays (1-3)
 *
 * Use destructuring to initialize the variables `one`, `two`, and `three`
 * with the colors from the `things` array.
 */

const things = ['red', 'basketball', 'paperclip', 'green', 'computer', 'earth', 'udacity', 'blue', 'dogs'];

const [one,,,two,,,,three,] = things;

const colors = `List of Colors
1. ${one}
2. ${two}
3. ${three}`;

console.log(colors);

```

注意逗點間的空白變數省略變數的用法。

### Destructuring values from an object

```javascript
const gemstone = {
  type: 'quartz',
  color: 'rose',
  carat: 21.29
};

const {type, color, carat} = gemstone;

console.log(type, color, carat);
```

## Object Literal Shorthand <a href="#header-title" id="header-title"></a>

New *shorthand* ways for initializing objects and adding methods to objects.

以前要這樣指定object:

```javascript
let type = 'quartz';
let color = 'rose';
let carat = 21.29;

const gemstone = {
  type: type,
  color: color,
  carat: carat
};

console.log(gemstone);

Output:
Prints: Object {type: "quartz", color: "rose", carat: 21.29}
```

Do you see the repetition? Doesn't `type: type`, `color: color`, and `carat:carat` seem redundant?

可以看到type被重複寫三次。

新版：

新版可以在object中加入function

```javascript
let type = 'quartz';
let color = 'rose';
let carat = 21.29;

const gemstone = {
  type,
  color,
  carat,
  calculateWorth: function() {
    // will calculate worth of gemstone based on type, color, and carat
  }
};
```

function可省略

```javascript
let gemstone = {
  type,
  color,
  carat,
  calculateWorth() { ... }
};
```

## Family of For Loops <a href="#header-title" id="header-title"></a>

### 1. The most common type

```javascript
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (let i = 0; i < digits.length; i++) {
  console.log(digits[i]);
}
```

### 2. The for...in loop

```javascript
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (const index in digits) {
  console.log(digits[index]);
}
```

Also, the for...in loop can get you into big trouble when you need to add an extra method to an array (or another object). Because for...in loops loop over all enumerable properties, this means if you add any additional properties to the array's prototype, then those properties will also appear in the loop.

```javascript
Array.prototype.decimalfy = function() {
  for (let i = 0; i < this.length; i++) {
    this[i] = this[i].toFixed(2);
  }
};

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (const index in digits) {
  console.log(digits[index]);
}
```

輸出會連function定義也print出來！

```javascript
Prints:
0
1
2
3
4
5
6
7
8
9
function() {
 for (let i = 0; i < this.length; i++) {
  this[i] = this[i].toFixed(2);
 }
}
```

{% hint style="warning" %}
**NOTE:** The **forEach loop** is another type of for loop in JavaScript. However, `forEach()` is actually an array method, so it can only be used exclusively with arrays. **There is also no way to stop or break a forEach loop**. If you need that type of behavior in your loop, you’ll have to use a basic for loop.
{% endhint %}

### 3. For...of loop to the rescue

就跟Java的 for(int n : nums) { ... } 很像，冒號改成of：

```javascript
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (const digit of digits) {
  console.log(digit);
}
```

並且這個方法修正了print function definition 這個問題：

And you don’t have to worry about adding new properties to objects. The for...of loop will only loop over the values in the object.

```javascript
Array.prototype.decimalfy = function() {
  for (i = 0; i < this.length; i++) {
    this[i] = this[i].toFixed(2);
  }
};

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (const digit of digits) {
  console.log(digit);
}
```

輸出：

```javascript
Prints:
0
1
2
3
4
5
6
7
8
9
```

## Spread... Operator <a href="#header-title" id="header-title"></a>

新概念，把

The **spread operator**, written with three consecutive dots ( `...` ), is new in ES6 and gives you the ability to expand, or *spread*, [iterable objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators#Iterators) into multiple elements.

```javascript
const books = ["Don Quixote", "The Hobbit", "Alice in Wonderland", "Tale of Two Cities"];
console.log(...books);

Prints: Don Quixote The Hobbit Alice in Wonderland Tale of Two Cities
```

```javascript
const primes = new Set([2, 3, 5, 7, 11, 13, 17, 19, 23, 29]);
console.log(...primes);

Prints: 2 3 5 7 11 13 17 19 23 29
```

好用在哪？

### Combining arrays with concat

```javascript
const fruits = ["apples", "bananas", "pears"];
const vegetables = ["corn", "potatoes", "carrots"];
const produce = fruits.concat(vegetables);
console.log(produce);

Prints: ["apples", "bananas", "pears", "corn", "potatoes", "carrots"]
```

### 利用spread operator

```javascript
const fruits = ["apples", "bananas", "pears"];
const vegetables = ["corn", "potatoes", "carrots"];

const produce = [...fruits, ...vegetables];

console.log(produce);

Prints: [ 'apples', 'bananas', 'pears', 'corn', 'potatoes', 'carrots' ]
```

## ...Rest Parameter <a href="#header-title" id="header-title"></a>

就是spread operator的反面

If you can use the spread operator to *spread* an array into multiple elements, then certainly there should be a way to bundle multiple elements back into an array, right?

In fact, there is! It’s called the *rest parameter*, and it’s another new addition in ES6.

### 1. Rest parameter <a href="#rest-parameter" id="rest-parameter"></a>

The **rest parameter**, also written with three consecutive dots ( `...` ), allows you to represent an indefinite number of elements as an array. This can be helpful in a couple of different situations.

One situation is when assigning the values of an array to variables. For example,

注意items的部分：

```javascript
const order = [20.17, 18.67, 1.50, "cheese", "eggs", "milk", "bread"];
const [total, subtotal, tax, ...items] = order;
console.log(total, subtotal, tax, items);

Prints: 20.17 18.67 1.5 ["cheese", "eggs", "milk", "bread"]
```

This code takes the values of the `order` array and assigns them to individual variables using destructuring (as you saw in the **Destructuring** section earlier in this lesson). `total`, `subtotal`, and `tax` are assigned the first three values in the array, however, `items` is where you want to pay the most attention.

By using the rest parameter, `items` is assigned the *rest* of the values in the array (as an array).

### 2. Variadic functions <a href="#variadic-functions" id="variadic-functions"></a>

問題：

Another use case for the rest parameter is when you’re working with variadic functions. **Variadic functions** are functions that take an indefinite number of arguments.

For example, let’s say we have a function called `sum()` which calculates the sum of an indefinite amount of numbers. How might the `sum()` function be called during execution?

```javascript
sum(1, 2);
sum(10, 36, 7, 84, 90, 110);
sum(-23, 3000, 575000);
```

There’s literally an endless number of ways the `sum()` function could be called. Regardless of the amount of numbers passed to the function, it should always return the total sum of the numbers.

#### 方法一：Using the arguments object

In previous versions of JavaScript, this type of function would be handled using the [arguments object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments). The **arguments object** is an array-like object that is available as a local variable inside all functions. It contains a value for each argument being passed to the function starting at 0 for the first argument, 1 for the second argument, and so on.

If we look at the implementation of our `sum()` function, then you’ll see how the arguments object could be used to handle the variable amount of numbers being passed to it.

```javascript
function sum() {
  let total = 0;  
  for(const argument of arguments) {
    total += argument;
  }
  return total;
}
```

Now this works fine, but it does have its issues:

1. If you look at the definition for the `sum()` function, it doesn’t have any parameters.
   * This is misleading because we know the `sum()` function can handle an indefinite amount of arguments.
2. It can be hard to understand.
   * If you’ve never used the arguments object before, then you would most likely look at this code and wonder where the arguments object is even coming from. Did it appear out of thin air? It certainly looks that way.

#### 方法二：Using the rest parameter

Fortunately, with the addition of the rest parameter, you can rewrite the `sum()` function to read more clearly.

```javascript
function sum(...nums) {
  let total = 0;  
  for(const num of nums) {
    total += num;
  }
  return total;
}
```

This version of the `sum()` function is both **more concise** and is **easier to read**. Remember, we use the [`for...of loop`](https://classroom.udacity.com/nanodegrees/nd016/parts/11a45d59-bb81-44a9-be76-042c99e5f051/modules/cbf6deb8-d2cc-4757-b3a9-a1c58a4acd82/lessons/42383e89-ac6a-491a-b7d0-198851287bbe/concepts/f1955923-744a-4906-8f64-1ddcb34c6da2) to loop over any type of data that is iterable. So we'll use `for...of` here rather than `for...in`.
