#### More on JavaScript

Spring 2019 。 Ric Huang
(A thorough JS guide can be found at [mdn](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide))
---
### Recall on Variables
* 弱型別
* "var" can be used to declare both local and global variables, depending on the execution context.
* Variable hoist
* "let" and "const" can be used to declare a block-scope local variable.
* No variable hoist
----
### Recall on Variables
* All numbers are double (floating numbers)
* Shift (<<, >>) operator: 將數字轉成最多 32-bit 的 signed int 來進行操作
* undefined
* NaN
* null // 0 in numeric and false in Boolean
----
### Numeric values or string?
```javascript=
"30" + 8 ==> "308"
"30" - 8 ==> 22
"30" * 8 ==> 240
"30" / 8 = 3.75
"30" << 8 ==> 7680
"30" >> 8 ==> 0
```
----
### Converting strings to numbers
parseInt(string, base) // base = [2,36]
```javascript
parseInt("15") = 15 // default is decimal
parseInt(0xF) = parseInt("0xF") = parseInt("0xF", 16) = 15
parseInt(017) = parseInt("015") = 15 = parseInt("017", 8) = 15
parseInt(017, 8) = parseInt("015", 8) = 13
parseInt("15*3", 10) ==> parseInt("15", 10) ==> 15
parseInt("321", 2) ==> NaN
```
See also: parseFloat("string");
----

---
#### Recall: Prototype-Based object construction
* object: collection of properties
* property: key(or name)-value pair
* value can be a function ==> method
```javascript
var Student = function (name, id) { ... }
var a = new Student("Ric", 101);
var b = new Student("Mary", 301);
a.score = 100; // property 'score' only belongs to 'a'
```
----
#### Don't put " " in property name declaration
* Even though these are the same:
```javascript
var a = { i: 10, "jj": 20 }
```
```javascript
var a = { i: 10, jj: 20 }
```
* But this is an error
```javascript
console.log(a."jj"); // ERROR!!
console.log(a.jj); // OK!
```
----
### Access the property value
1. By '.'
* Property name must be a valid JS identifier
* "s.createdAt" is OK, but "s.created\ at" is not OK
2. By []
* Property name can be any valid JS string
* s['created at'] = '2019.03.06 下午';
* s[''] = "nothing"; // even empty string
----
### Access the property value
```javascript
ric.name; // “Ric”
ric."name"; // ERROR!!
ric[name]; // undefined, if var name is undefined
ric["name"]; // “Ric”
ric[0]; // undefined, if ric is not an array
```
----
* 使用 [] 來存取 object 的 property 有一個好處是可以 “動態的設定” property name
```javascript
var a;
if (someExpression) { a = "A"; }
else { a = "B"; }
// assume someExpression is false
ric[a] = 70;
console.log(ric.A); // undefined
console.log(ric.B); // 70
```
----
* Property name can almost be anything…
```javascript
var car = {
manyCars: { a: "Saab", "b": "Jeep"},
7: "Mazda",
"": "An empty string",
"!": "Bang!"
};
car.manyCars.a; // "Saab" car.manyCars."a"; // ERROR!!
car.manyCars.b; // "Jeep" car.manyCars."b"; // ERROR!!
car.manyCars[a]; // undefined car.manyCars["a"]; // "Saab"
car.manyCars[b]; // undefined car.manyCars["b"]; // "Jeep"
car."7"; // ERROR!! car.7; // ERROR!!
car["7"]; // "Mazda"; car[7]; // "Mazda"
car.""; // ERROR!! car[""]; // "An empty string"
car."!"; // ERROR!! car.!; // ERROR!!
car["!"]; // "Bang!"
```
----
#### Recall: Object can be created in many ways
* Using object initializers
```javascript
var obj = { property_1: value_1, ... }
```
* Using constructor function
```javascript
function Car(make, model, year) { this.make = ... }
// is the same as
var Car = function(make, model, year) { this.make = ... }
// Then you can use "new" to create objects
var car1 = new Car("Toyota", "Wish", 2015);
```
* Using **Object.create** method
```javascript
// Using an existing object as prototype
var obj = { value: 0 }
var newObj = Obejct.create(obj);
console.log(newObj.value); // 0
newObj.value = 10; // assign a new value
```
---
### Closer Look at Constructor Function
* Tell the differences...
```javascript
// #1 Function call
function Car(make) { this.make = make; }
var car = Car("BMW");
console.log(car); // undefined
console.log(car.make); // ERROR
```
```javascript
// #2 Constructor call
function Car(make) { this.make = make; }
var car = new Car("BMW");
console.log(car); // { make: "BMW" }
console.log(car.make); // "BMW"
```
----
* Tell the differences...
```javascript
// #3 Function call to a ref to an anonymous function
var Car = function(make) { this.make = make; }
var car = Car("BMW");
console.log(car); // undefined
console.log(car.make); // ERROR
```
```javascript
// #4 Constructor call to a ref to an anonymous function
var Car = function(make) { this.make = make; }
var car = new Car("BMW");
console.log(car); // { make: "BMW" }
console.log(car.make); // "BMW"
```
----
* Tell the differences...
```javascript
// #5 Ref to a ref to an anonymous function
var Car = function(make) { this.make = make; }
var car = Car;
console.log(car); // is a function
console.log(car.make); // undefined
```
```javascript
// #6 Constructor call to a ref to an anonymous function
var Car = function(make) { this.make = make; }
var car = new Car; // missing parameter
console.log(car); // is a object
console.log(car.make); // undefined
```
----
* Tell the differences...
```javascript
// #7 Create an object from another object as a prototype
var Car = function(make) { this.make = make; }
var car = new Car("BMW");
console.log(car); // { make: "BMW" }
console.log(car.make); // "BMW"
var myCar = Object.create(car);
console.log(myCar); // { } <-- no own property
console.log(myCar.make); // "BMW" <-- inherited property
```
---
### Object Inheritance
* All objects in JavaScript inherit from at least one other **object**.
* The object being inherited from is known as the **prototype**, and the inherited properties can be found in the prototype object of the constructor.
* Don't get confused with the "inheritance" in class-based language(e.g. C++).
* "class" in JS is just a syntatical sugar (supported in ES6, covered later). JavaScript remains prototype-based.
----
### Prototype Chain
* All objects in JavaScript inherit from at least one other **object**.
* Each object has a **private property** which holds a link to another object called its **prototype**.
* That prototype object has a prototype of its own, and so on until an object is reached with **null** as its prototype. By definition, null has no prototype, and acts as the final link in this **prototype chain**.
* Nearly all objects in JavaScript are instances of **Object** which sits on the top of a prototype chain.
----
### **"\_\_proto__"** in Prototype Chain
```javascript
var Car = function(make) { this.make = make; }
var car = new Car("BMW");
var myCar = Object.create(car);
myCar.year = 2018;
console.log(myCar);
// You should see
{
year: 2018,
__proto__: Car { // Note: not "car"
make: "BMW",
__proto__: {
constructor: f (make),
__proto__: Object
}
}
}
```
----
### **"\_\_proto__"** in Prototype Chain
```javascript
var Car = function(make) { this.make = make; }
var car = new Car("BMW");
var myCar = Object.create(car);
myCar.year = 2018;
```

----
### Inheriting Properties
* An object inherits all the properties from the objects along the prototype chain
```javascript
var Car = function(make, model) {
this.make = make; this.model = model; }
var car = new Car("BMW", "X5");
var myCar = Object.create(car);
myCar.model = "X3"; // over-write
myCar.year = 2018; // own property
console.log(myCar.driver); // undefined
```
----
### Object.keys(obj) vs. for (var i in obj)
* "Object.keys(obj)" returns an array with all the **own** (not in the prototype chain) enumerable properties' names ("keys") of the object obj.
```javascript
Object.keys(myCar); // ["year"]
```
* "for (var i in obj)" traverses **all** enumerable properties of an object and its prototype chain.
```javascript
for (var i in myCar)
console.log(i); // [ "year", "make", "model"]
```
----
### List of the enumerable properties
```javascript
var Obj = function() { this.a = 10; this.b = 20; }
var obj1 = new Obj();
Object.keys(obj1); // [ "a", "b" ]
var obj2 = Object.create(obj1);
obj2.c = 30;
console.log(obj2); // { c: 30, __proto__: Obj }
Object.keys(obj2); // [ "c" ]
console.log(obj2.a); // 10
obj2.a = 40; // overwrite and make it own property
console.log(obj2); // { c: 30, a: 40, __proto__: Obj }
Object.keys(obj2); // [ "c", "a" ]
```
---
### **"prototype"** property in the function
* All functions have a special prop named **prototype**
```javascript
var Car = function(make) { this.make = make; }
var car = new Car("BMW");
var myCar = Object.create(car);
myCar.year = 2018;
console.log(Car.prototype); // You should see
{
constructor: f (make),
__proto__: Object
}
console.log(car.prototype); // undefined
console.log(myCar.prototype); // undefined
```
----
### **"prototype"** property in the function
* You can add a property through **prototype**
```javascript
var Car = function(make) { this.make = make; }
var car = new Car("BMW");
var myCar = Object.create(car);
myCar.year = 2018;
Car.prototype.model = "X5";
console.log(Car.prototype); // You should see
{
model: "X5";
constructor: f (make),
__proto__: Object
}
console.log(myCar.model); // "X5"
```
---
### Inheriting "methods"
* Recall: property in an object can be a function.
```javascript
var Car = function(make) {
this.make = make;
this.drive = function () {
console.log(this.make + " is driving");}
}
var car = new Car("BMW");
car.drive(); // "BMW is driving"
var myCar = Object.create(car);
myCar.make = "Lexus";
myCar.drive(); // "Lexus is driving"
Car.prototype.park = function () { // add a function
console.log(this.make + " is parking"); }
myCar.park(); // "Lexus is parking"
```
---
### Arrow Function (=>)
* 如前所述,當初 JavaScript 在設計上,有很多會讓 programmer 混淆的語法問題,例如:"this" bind 錯誤,在 ES6 提出 arrow function 後獲得很大的改善
* Arrow function 就像是 lamda function in Python
```javascript
(argument1, argument2, ... argumentN) => {
// function body
}
const add = (a, b) => a + b;
const getFirst = array => array[0];
```
----
### Used with Array
* Arrow function is particularly useful when works with Array
```javascript
var materials = [ 'Hydrogen', 'Helium', 'Lithium', 'Beryllium'];
console.log(materials.map(material => material.length));
// expected output: Array [8, 6, 7, 9]
```
```javascript
var todoListData = [ ... ];
todoListData.filter(elem => !elem.isComplete);
if (todoListData.some(ele => ele.isComplete))
doSomething...
```
---
## End
{"metaMigratedAt":"2023-06-14T20:27:28.540Z","metaMigratedFrom":"YAML","title":"More on JavaScript (03/06)","breaks":true,"slideOptions":"{\"theme\":\"beige\",\"transition\":\"fade\",\"slidenumber\":true}","contributors":"[{\"id\":\"ae1d234d-f143-4cee-92b5-e303abdd6d82\",\"add\":2,\"del\":2},{\"id\":\"a202b02b-072b-4474-be14-c5a3f8932dbb\",\"add\":5,\"del\":2},{\"id\":\"752a44cb-2596-4186-8de2-038ab32eec6b\",\"add\":15186,\"del\":4088}]"}