#### More on JavaScript ![](https://i.imgur.com/0kWBESs.png) 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"); ---- ![](https://i.imgur.com/9ehapm6.png) --- #### 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; ``` ![](https://i.imgur.com/m08e5RP.png) ---- ### 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}]"}
    1282 views
   owned this note