1. 程式人生 > 其它 >IOS實現日期選擇器

IOS實現日期選擇器

為什麼使用Typescript?

微軟推出TypeScript主要是為實現兩個目標:

  • 為Javascript提供可選的型別系統;
  • 相容當前及未來的JavaScript的特性。

靜態型別帶來的好處:

  • 有利於程式碼重構,它在編譯器編譯的時候就能捕獲錯誤。
  • 型別明確有利於閱讀。

JavaScript常見語法

TypeScript是JavaScript的“超集”,typescript將javascript語法標準化。

  1. == 與 ===

    使用==進行比較時,會進行隱式轉換。

    2 == 2 true
    2 == '2' true
    2 === '2' false
    
  2. 引用

    除字面量外,JavaScript中的任何物件(包括函式、陣列、正則表示式等)都是一個引用。

  3. null和undefined

    變數沒有初始化:undefined。變數不可用為null。

    undefined == undefined true
    undefined == null true
    // 檢查變數是否初始化
    if( typeof val !== 'undefined'){}
    
  4. this

    this關鍵字指向呼叫上下文

    function foo(){console.log(this)} /** this --> window **/
    var obj = {foo:function(){console.log(this)}} 
    obj.foo() /** this --> obj */ 
    
  5. 閉包

    內部函式訪問外部變數,此時外部函式的變數被內部函式繫結,稱為閉包。

    function outer(){
      var outerVal = '1'
      function inner(){
        console.log(outerVal)
      }
      outer()
    }
    /** inner 綁定了 outerVal */
    
  6. 數字

    JavaScript中數值是雙精度的64位的number

    console.log(.1 + .2) // 0.30000000000000004
    

    內建整數型別限制 Number.MAX_SAFE_INTEGER-Number.MIN_SAFE_INTEGER

    金融計算中一般使用 big.js

    NaN,計算出的結果不是合法數值時返回NaN,檢測NaN,Number.isNaN。

  7. thuthy

!!雙感嘆號,第一個!是將值轉為布林值,第二個邏輯反轉。

ES6語法

  1. class

    /*ES6*/
    class Point {
      x: number
      y: number
      constructor(x: number, y: number) {
        this.x = x
        this.y = y
      }
      add(point: Point) {
        return new Point(this.x + point.x, this.y + point.y)
      }
    }
    
    /*編譯後ES5*/
    var point = function(){
      function Point(x, y){
        this.x = x;
        this.y = y;
      }
      Point.prototype.add = function(point){
       return  new Point(this.x + point.x, this.y + point.y)
      }
      return Point;
    }()
    

    繼承

    /*ES6*/
    class Point3D extends Point {
      z: number
      constructor(x: number, y: number, z: number) {
        super(x, y)
        this.z = z
      }
      add(point: Point3D) {
        var point2D = super.add(point)
        return new Point3D(this.x + point2D.x, this.y + point2D.y, this.z + point.z)
      }
    }
    
    /*編譯後ES5*/
    var point3D = function(_super){
      __extends(Point3D, _super)
      function Point3D(x, y, z){
        _super.call(this, x, y)
        this.z = z;
      }
      Point3D.prototype.add = function(point){
    	 var point2D = _super.prototype.add.call(this, point)
       return new Point3D(this.x + point2D.x, this.y + point2D.y, this.z + point.z)
      }
      return Point;
    }(Point)
    
    /**__extends typescript 編譯 extends 時生成*/
    var __extends = (this && this.__extends) || (function () {
        var extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    /*
    d表示派生類,b表示基類
    */
      return function (d, b) {
            extendStatics(d, b); // 拷貝靜態變數
            function __() { this.constructor = d; } // 保留派生構造器
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); //d.prototype.__proto__ = b.prototype
        };
    })();
    

    區分 __ proto __ prototype

    javascript 中所有物件都有屬性__ proto __

    /** 查詢屬性順序 
    obj.property
    obj.__proto__.property
    obj.__proto__.__proto__.property
    **/
    

    javasript 所有的函式都有屬性 prototype,prototype有個指向函式本身的構造器constructor。

    function Foo(){
      this.name = "xm"
    }
    var foo = new Foo();
    /**通過函式建立的物件,會將函式prototype傳給物件__proto__*/
    console.log(foo.__proto__ === Foo.prototype)
    
  2. 箭頭函式

    var inc = x => x + 1;
    

    箭頭函式帶來語法簡潔和this丟失問題。

  3. rest引數

    ...+引數名的形式表示最後一個引數,獲取時轉為陣列。

  4. let和const

    var 變數是函式作用域,let 變數塊作用域

    /**閉包中的var*/
    var funcs = []
    for(var i = 0;i < 3; i++){
      funcs.push(function(){
        console.log(i)
      })
    }
    for(var j = 0;j < 3; j++){
      funcs[j]();
    }
    /*輸出 3*/
    

    const 宣告常量值。

  5. 解構

    支援物件和陣列解構。

    /*物件解構*/
    var person = {name:'x',age:12,gender:1}
    var {name, age} = person
    console.log(name, age) // x, 12
    var {x, y, ...remaining} = {x: 1, y: 2, z: 4, w: 5} // 看作刪除了x,y
    console.log(x,y,remaining) // 1,2 {z:4,w:5}
    
  6. 擴充套件運算子

    Function.prototype.apply

    /*apply呼叫*/
    function foo(x,y){}
    var args = [0,1]
    foo.apply(null, args)
    // 新語法
    foo(...args)
    // 陣列追加元素
    var list = [1, 2]
    list = [...list, 3] //  [1,2,3]
    list = [0,...list,4] // [0,1,2,3,4]
    
  7. for...of

    /*for...in*/
    for(var e in [7,8,9]){console.log(e) }// 返回索引
    for(var e of [7,8,9]){console.log(e) }// 返回元素
    
  8. Promise

    使用Promise處理非同步和回撥函式。

    var promise = new Promise((resolve, reject) => {resolve()//回撥正確值
                                                   reject() // 異常值
                                                   })
    promise.then(res => {}) // 正常
    .catch(err => {}) // 異常
    

    並行流程控制,Promise.all([promise1,promise2]).then(res => [result1, result2])

  9. generators

    function* idGen(){
        let index = 0
        while(index < 3) yield /*暫停*/ index++;
    }
    var id = idGen();
    console.log(id.next());
    console.log(id.next());
    console.log(id.next());
    console.log(id.next());
    
  10. async/await

async function foo(){
    var result = await exPromise() //等待promise執行返回
    console.log(result)
}

TS專案構成

  1. 編譯上下文

    tsconfig.json配置檔案,配置選項:tsconfig

  2. 宣告空間

    型別宣告空間和變數宣告空間。

    • 類 (class): 型別, .
    • 介面 (interface): 型別.
    • 列舉 (enum): 型別, .
    • 類別名 (type): 型別.
    • 函式 (function): .
    • 變數 (let, const, var, parameters): .
  3. 模組

    預設情況下宣告處於全域性名稱空間中。使用export變成檔案模組。

    模組路徑查詢

    /**相對路徑**/
    import * as foo from './foo' // 同級目錄
    import * as foo from '../foo' // 上級目錄
    import * as foo from '../someFolder/foo // 相對目錄
    
    /**匯入路徑不是相對路徑時,動態查詢**/
    import * as foo from 'foo'
    /*
    查詢順序
    ./node_modules/foo
    ../node_modules/foo
    ../../node_modules/foo
    */
    import * as foo from 'something/foo'
    /**
    ./node_modules/something/foo
    ../node_modules/something/foo
    ../../node_modules/something/foo
    */
    /* place */
    import * as foo from 'foo'
    /**查詢順序*/
    /**
    foo 是檔案 foo.ts
    foo 是目錄 foo/index.ts
    foo 是目錄 foo/package.json 有 types
    foo 是目錄 foo/package.json 有 main
    **/
    
  4. 名稱空間

    //typescript 宣告
    namespace Utility {
      export function log(msg) {
        console.log(msg);
      }
      export function error(msg) {
        console.log(msg);
      }
    }
    // usage
    Utility.log('Call me');
    Utility.error('maybe');
    
    var Utility;
    (function (Utility) {
        function log(msg) {
            console.log(msg);
        }
        Utility.log = log;
        function error(msg) {
            console.log(msg);
        }
        Utility.error = error;
    })(Utility || (Utility = {}));
    // usage
    Utility.log('Call me');
    Utility.error('maybe');
    
  5. 動態匯入表示式

    // 動態載入
    import(/* webpackChunkName: "momentjs" */ 'moment')
      .then(moment => {
        // 懶載入的模組擁有所有的型別,並且能夠按期工作
        const time = moment().format();
        console.log('TypeScript >= 2.4.0 Dynamic Import Expression:');
        console.log(time);
      })
      .catch(err => {
        console.log('Failed to load moment', err);
      });
    

建立TS專案

  1. 安裝node環境,建立目錄進入執行 npm init -y;
  2. 安裝ts npm install typescript --save-dev ;
  3. 建立檔案 node.d.ts npm install @types/node --save-dev;
  4. 初始化tsconfig.json npx tsc --init --rootDir src --outDir lib --esModuleInterop --resolveJsonModule --lib es6 , dom --module commonjs;
  5. 新增ts-node:npm install ts-node --save-dev 實現實時編譯和執行;
  6. 新增nodemon:npm install nodemon --save-dev,只要檔案被改變,它就會呼叫ts-node。

TS型別系統

  1. 基本概念

    基本型別 number string boolean string[]

    介面 interface

    特殊型別 any、null、undefined和void

    // 介面
    interface Name{
        first: string,
        last: string
    };
    let n : Name;
    n = {
        first: 'Li',
        last:'p'
    }
    // 泛型
    function contact<T>(items : T[]): T[]{
        //......
        return items;
    }
    // 聯合型別
    function join(items : string[] | string){
        //......
    }
    // 交叉型別
    function extend<T, U>(first: T, last : U) :T & U{
        const result = <T & U>{}
        return result
    }
    // 元祖型別
    let nameNum : [string, number]
    //類型別名
    type mind = string | Number
    let m : mind
    
  2. @types

    倉庫 @types 通過配置tsconfig.json的compilerOptions.types控制全域性。

  3. 環境宣告

    使用關鍵字declare進行宣告,一般放在.d.ts檔案。

  4. 列舉

    數字列舉和字串列舉。

  5. lib.d.ts

    安裝TypeScript時,會順帶安裝一個lib.d.ts宣告檔案。這個檔案包含JavaScript執行時及DOM(Document Object Model,文件物件模型)中存在的各種常見的JavaScript環境宣告。

  6. 函式

    宣告函式 type inc = (num : number) => number

  7. 可呼叫可例項化

// 可呼叫
interface ReturnStr{
  () : string;
}
declare const foo : ReturnStr
const str = foo() // str 字串
// 內聯註解
const overload: {
  (foo: string): string;
  (foo: number): number;
} = (foo: any) => foo
// 可例項化
interface NewAble {
  new (): string;
}
declare const newAble: NewAble;
const foo = new newAble
  1. 型別斷言

    Ts可以以任何方式去重寫其推斷和分析的型別,稱為型別斷言。

    interface Foo{
      Bar : string
    }
    const f1 = {} as Foo;
    f1.bar = "1";
    const f2 = <Foo>{};
    f2.bar = "2";
    
  2. Freshness

    檢查字面量型別

    function hasName(some: { name: string }) {
      some.name = "name"; // 正確
      some.age = 12; // 錯誤
    }
    
  3. 型別保護

typeof (typeof x === 'string')

instanceof (foo instanceof Foo)

in 檢查物件是否存在對應屬性

  1. readonly

    type Foo = {
      readonly bar: string;
    };
    const f: Foo = { bar: "x" };
    f.bar = "y"; // 錯誤,不可修改
    
  2. 泛型

    類的例項成員、類的方法、函式的引數、函式返回值之間的約束。

  3. never

    never型別就是TypeScript中的底部型別。用於一個總會丟擲錯誤的函式或一個總會丟擲錯誤的函式。

    never與void的差異,void表示沒有任何型別,never表示永遠不存在的值的型別。

  4. 異常處理

    try {
      throw new Error("err.");
    } catch (error) {
      console.log(error)
    } 
    

程式碼風格約定

  1. 使用camelCase形式為變數和函式命名。

  2. 使用PascalCase形式為類命名。

  3. 使用PascalCase形式為介面命名。

  4. 類型別名使用PascalCase形式進行命名。

  5. 名稱空間使用PascalCase形式進行命名。

  6. 列舉型別使用PascalCase形式進行命名。

  7. 對於需要明確表明不可用的情況,null和undefined都不建議使用。

  8. 格式化

    tsfmt命令格式化,使用單引號,空格兩tab,如果想用extends或implements,則建議使用interface。

TS編譯原理

.....待續再看