研究JavaScript的六项基础与组织方式
一、开宗明义
JS的每一个单独的文件都是一个独立的program。
二、数值与数据Value and Data
JS中的Value就是Data,有两种形式分别为primitive和object。其中primitive包括1)number(bigint), 2)string(interpolate)3)boolean 4) undefined and null 5) Symbol
而剩下的所有的data都是object类型,比如array与function是特殊类型的object。
`typeof`检测数据的类型,但有个特殊的bug:
typeof null; // "object" -- oops, bug!
声明变量的方式 Declare Variables
声明变量有var,let,const此三种方式,特殊形式为function的声明:
function hello(myName) { console.log(`Hello, ${ myName }.`); }
三、函数 Function
在JS,function既是procedure又是value(data)。
function awesomeFunction(coolThings) { // .. return amazingStuff; } coonstn awesomeFunction = function(coolThings) { // .. return amazingStuff; };
因为function是value,因此可将其作为object的properties。
let saySomething = { greeting() { console.log("Hello!"); }, question() { console.log("What's your name?"); }, answer() { console.log("My name is Kyle."); } }; saySomething.greeting(); // Hello!
四、数值的比较 Comparison
历史的原因,JS的数值比较乃是个迷思,颇为复杂。
Triple-equals
最为常见的是triple-equals,但是有特殊案例:
NaN === NaN; // false 0 === -0; // truer
Quadruple-equals
解决方案:
> Number.isNaN(NaN) true > Object.is(0, -0) false
其中object.is又被称之为quadruple-equals "====",不仅比较值,也比较类型。
更深层次的探索,JS的equality-comparision并不是content-aware的“structual equality”,而是identity-aware的reference-equality。
var x = [ 1, 2, 3 ]; // assignment is by reference-copy, so // y references the *same* array as x, // not another copy of it. var y = x; y === x; // true y === [ 1, 2, 3 ]; // false x === [ 1, 2, 3 ]; // false
Coercive-comparision
Coercive-comparison的应用是inevitable,因为rational-operator会用到,比如:
var arr = [ "1", "10", "100", "1000" ]; for (let i = 0; i < arr.length && arr[i] < 500; i++) { // will run 3 times }
但是当比较的双方都是string的时候,就会出现错误:
> "11" > "9" false
五、用Class如何组织我们的JS代码
Class
class组织代码的关键词是concrete,instantiated, new.
class Page { constructor(text) { this.text = text; } print() { console.log(this.text); } } class Notebook { constructor() { this.pages = []; } addPage(text) { var page = new Page(text); this.pages.push(page); } print() { class Publication { constructor(title,author,pubDate) { this.title = title; this.author = author; this.pubDate = pubDate; } print() { console.log(` Title: ${ this.title } By: ${ this.author } ${ this.pubDate } `); } } for (let page of this.pages) { page.print(); } } } var mathNotes = new Notebook(); mathNotes.addPage("Arithmetic: + - * / ..."); mathNotes.addPage("Trigonometry: sin cos tan ..."); mathNotes.print(); // ..
Class Inheritance
inheritance可实现polymorphism.
class Publication { constructor(title,author,pubDate) { this.title = title; this.author = author; this.pubDate = pubDate; } print() { console.log(` Title: ${ this.title } By: ${ this.author } ${ this.pubDate } `); } } class Book extends Publication { constructor(bookDetails) { super( bookDetails.title, bookDetails.author, bookDetails.publishedOn ); this.publisher = bookDetails.publisher; this.ISBN = bookDetails.ISBN; } print() { super.print(); console.log(` Publisher: ${ this.publisher } ISBN: ${ this.ISBN } `); } } class BlogPost extends Publication { constructor(title,author,pubDate,URL) { super(title,author,pubDate); this.URL = URL; } print() { super.print(); console.log(this.URL); } }
六、用Module组织JS代码
以traditional方法实现module:
function Publication(title,author,pubDate) { var publicAPI = { print() { console.log(` Title: ${ title } By: ${ author } ${ pubDate } `); } }; return publicAPI; } function Book(bookDetails) { var pub = Publication( bookDetails.title, bookDetails.author, bookDetails.publishedOn ); var publicAPI = { print() { pub.print(); console.log(` Publisher: ${ bookDetails.publisher } ISBN: ${ bookDetails.ISBN } `); } }; return publicAPI; } function BlogPost(title,author,pubDate,URL) { var pub = Publication(title,author,pubDate); var publicAPI = { print() { pub.print(); console.log(URL); } }; return publicAPI; }
Traditional-module与class的区别之处就在于explicit的publicAPI。
ES Modules
ES modules (ESM)是基于file,一个file是一个module。ESM是single-instance即singletons.
function printDetails(title,author,pubDate) { console.log(` Title: ${ title } By: ${ author } ${ pubDate } `); } export function create(title,author,pubDate) { var publicAPI = { print() { printDetails(title,author,pubDate); } }; return publicAPI; }
在另外的文件中引用以上的函数。
import { create as createPub } from "publication.js"; function printDetails(pub,URL) { pub.print(); console.log(URL); } export function create(title,author,pubDate,URL) { var pub = createPub(title,author,pubDate); var publicAPI = { print() { printDetails(pub,URL); } }; return publicAPI; }
作为惯例,可以将所有的module都引入到main.js文件中。
建议不要将classic-module与class混用。