• home > webfront > ECMAS > typescript >

    typescript参照C#/java/swift学习小结

    Author:[email protected] Date:

    参照C java swift等传统强类型语言,对比来学习typescript,学习起来,更能理清脉络。联想性记忆

    学typescript,首先肯定是看官方文档,http://www.typescriptlang.org,国内翻译网站:https://www.tslang.cn

    说实话,这个文档看下去,是昏昏欲睡的感觉。只能作为手册查查

    在这里推荐《从C#到TypeScript - 类型》,从c#看ts,对比学起来快些,这里就个人,做一些笔记,分享一下

    TypeScript - 类型

    一般强类型编程语言基础类型有byte,short,int,long,float,double,boolean,char

    而typescript和js一样,而TypeScript和JavaScript一样,所有的数字都是double(双精度浮点数),都是用number表示,字符串都是string,其它都不差不多。这里跟php等弱类型语言差不多。

    typescript联合类型与交叉类型

    ts让我感到诡异的就是 联合类型,其实就是多个类型联合在一起,用|符号隔开

    let sn: string | number = 'string, number' //这个类型既可以是string,又可以是number

    更加迷惑的是,交叉类型(Intersection Types),交叉类型是将多个类型合并为一个类型。 Person & Serializable & Loggable同时是 Person 和 Serializable 和 Loggable。 就是说这个类型的对象同时拥有了这三种类型的成员。您将主要看到用于mixins的交集类型和其他不适合经典面向对象模具的概念

    interface T1 {
      a: boolean;
      b: string;
    }  
    interface T2 {
      a: boolean;
      b: number;
    }  
    type T = T1 & T2;
      type Ta = T['a']; // boolean
    type Tb = T['b']; // string & number
      
    declare const t: T;
    declare const t1: T1;
    t['b'] = t1['b'];

    typescript枚举

    js没有enum枚举,ts做了补充,可以实现类似C# Flag特性

    enum Action{
        add = 1,
        edit = 2,
        del = 4,
        all = add | edit | del
    }
    console.info(Action.add);  // 返回1
    console.info(Action.add.toString());  // 返回1
    console.info(Action[1]);  // 返回"add"
    console.info(Action[3]);  // 返回undefined
    console.info(Action.all); // 返回7
    console.info(Action.all & Action.add) //返回1

    对函数增加void(和java等语法类似),还有never,用来表示永远不会得到返回值

    typescript变量声明

    typesc和C#,swift 有点类似,和C/C++,java 风格不同,ts让IED有了写js有了类型安全语言的流畅感。

    let name: string = `Gene`;
    let age: number = 37;
    let sentence: string = `Hello, my name is ${ name }.
    let someValue: any = "this is a string"; //any 和C#的dynamic很相似,回归传统js模式
    let strLength: number = (someValue as string).length; //类型断言
    type newstring = string;
    let str: newstring = 'aaa';

    c++ java 声明变量一般如此 

    int sum(int n){
    int total = 0;
    //在for循环的条件语句内部定义变量i
    for(int i=1; i<=n ;i++){
    total += i;
    }
    return total;
    }

    java代码

    public class Test {
        public static void main(String[] args) {
            int a = 123;
            byte b = (byte) a;//强制类型转换为byte
            string c = 'cc'
        }
    }

    swift代码(swift let 为常量,var为变量,js里面const为常量,let为区域变量,var为普通变量)

    import Cocoa
    var varA = 42 //类型推断 会被推测为 Int 类型
    var varB:Float = 3.14159
    var 你好 = "你好世界"
    typealias Feet = Int //类型别名
    var distance: Feet = 100 //可以通过别名来定义变量:

    typescript interface 

    typescript interface 诡异的,不像opp经典java 接口,也不像C#

    interface Selectable {
        readonly isSelected: boolean; //只读属性,实现接口的类也不一定需要readonly
        body?: any;//可选属性
    }
    class Control implements Selectable {
        isSelected : boolean;
    }
    let config: RequestConfig = {url: 'google.com'};//接口不需要类的支持 
    //这种经常用在函数的参数上面,用来描述具体的参数,把具体的参数放到接口里,方便操作,也方便重构。
    function Request(config: RequestConfig){}

    接口可以多重继承其他接口,用的是extends

    interface Editable {}
    interface Deleteable {}
    interface Changeable extends Editable, Deleteable {}

    在C#等面向对象语言里面,接口如果没有类来实现的话是没有什么意义的,但在TypeScript里不一样,接口可以单独使用。这感觉特别鸡贼!

    接口除了描述属性外,还可以用来描述函数,不过一个接口只能描述一个函数,描述时定义好参数和返回值即可。WTF,吐血!

    interface CheckLogin {
        (name: string, pwd: string): boolean;
    }
    let check: CheckLogin = function(name: string, pwd: string): boolean {
        return false;
    }

    接口还可以用来描述可索引类型,就有点类似C#的Dictionary。

    索引支持两种:number和string。

    //定义一个Dict,key是string,value也是stringinterface Dict {
        [key: string] : string;
    }let dict: Dict = { 'key1': 'value1', 'key2': 'value2'};
    console.info(dict['key1']); // value1console.info(dict['key']); // undefined

    接口继承类

    接口居然还可以反过来继承类,不过对于JavaScript里来说,灵活方便很重要,所以TypeScript实现了这个功能来快速生成一个接口。对我来说,觉得简直是反人类。颠覆opp的三观!因为复杂的继承通常会引入一些问题如紧耦合,牵一发而动全身,再加上这个,可能更让人摸不着头脑,不如用组合来得好。

    typescript的类和java类C#类差不多

    修饰类中属性、方法修饰符:

    Java: public、protected、default、 private, 默认:default

    C#:   public、protected、internal、private, 默认:private

    ts:       public、protected、private,               默认:public。

    TypeScript - function

    TypeScript的参数和JavaScript的参数不太一样,调用JavaScript函数的参数可以多或少都可以,但TypeScript里函数需要确保传入参数的个数和定义的一致

    function checkLogin(name: string, pwd: string, isAdmin: boolean = false, email?: string){    console.info(isAdmin);
    }checkLogin('brook'); // 编译不了
    checkLogin('brook', '123456'); // false
    checkLogin('brook', '123456', undefined); // false
    checkLogin('brook', '123456', false); // false
    checkLogin('brook', '123456', true, '[email protected]'); // true
    
    function checkLogin2(name: string, pwd: string, ...others: string[]){    console.info(others.join(' '));
    }
    checkLogin2('brook', '123456', '[email protected]', `12800`); // [email protected] 12800

    TypeScript es6- Reflect&&Proxy

    Symbol、Reflect 和 Proxy 是属于 ES6 元编程范畴的,能“介入”的对象底层操作进行的过程中,并加以影响。元编程中的 元 的概念可以理解为 程序 本身。推荐阅读《ES6 元编程(Proxy & Reflect & Symbol)》 《ES6黑科技实践--proxy,reflect

    怎么理解reflect

    通过反射,我们可以在运行时获得程序或程序集中每一个类型的成员和成员的信息。对于Java来说,程序中一般的对象的类型都是在编译期就确定下来的,而Java反射机制可以动态地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以我们可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的。

    而对于js来说自然是有些不同了。毕竟js不需要编译,同时万物皆对象的特性,这些都让理解js的reflect起来相当简单。

    对于JS中的reflect,我们就可以理解为:有这么一个全局对象,上面直接挂载了对象的某些特殊方法,这些方法可以通过Reflect.apply这种形式来使用,当然所有方法都是可以在 Object 的原型链中找到的。是不是相当简单。

    class Test{
        constructor(age: number){
            this.age = age;
        }
    
        private _age: number;
    
        get age(): number{
            return this._age;  // this 会被receiver代替
        }
    
        set age(value: number) {
            this._age = value; // this 会被receiver代替
        }
    }
    
    class Receiver{
        _age: number = 2;
    }
    
    let t = new Test(1);
    let r = new Receiver();
    
    console.info(Reflect.get(t, "_age")); // 1, 获取t的_age值
    console.info(Reflect.get(t, "age")); // 1, 获取t的age值
    console.info(Reflect.set(t, "age", 3)); // true, 成功设置age值为3
    console.info(Reflect.get(t, "age")); // 3, 再次获取t的age值
    console.info(Reflect.get(t, "age", r)); // 2, 表面上是t的age,但实际上获取的是r的age
    console.info(Reflect.set(t, "age", 3, r)); // true, 表面上是设置t的age, 实际上是设置r的age值为3
    console.info(Reflect.get(r, "_age")); // 3, 直接获取r的_age
    console.info(Reflect.apply(t["age"], t, 3));

    proxy

    let obj = { name: 'brook' };let p = new Proxy(obj, {
        get(target, property){        return 'cnblogs';
        }
    });console.info(obj.name); // brookconsole.info(p.name); // cnblogs

    一个使用proxy和reflect实现监听对象的小例子

    // onChange 即要进行的监听操作
    module.exports = (object, onChange) => {
        const handler = {
            get(target, property, receiver) {
                try {
                    return new Proxy(target[property], handler);
                } catch (err) {
                    return Reflect.get(target, property, receiver);
                }
            },
            defineProperty(target, property, descriptor) {
                onChange();
                return Reflect.defineProperty(target, property, descriptor);
            },
            deleteProperty(target, property) {
                onChange();
                return Reflect.deleteProperty(target, property);
            }
        };
    
        return new Proxy(object, handler);
    };

    哎,前端的框架,不知道尽头,学学佛,降低下戾气!

    ——华丽分割线——

    网友:请问佛教怎么祈求?

    学诚法师:佛教的祈求,意思是:把自己需要的东西向佛菩萨报告,不是向泥塑木雕祈求,而是向佛像所代表的佛菩萨的法身祈求,让自己的所思所想与佛菩萨的心相应,这样面对境界就会有力量。祈求自己能有勇气面对一切困难,祈求自己能有信心坚定一切善法,祈求自己能有智慧洞察一切真相,祈求自己能有慈悲对待一切众生,祈求自己永远不要放弃自己,也永远不要放弃别人。

    学诚法师:佛菩萨对众生的护佑并不是帮助我们得到理想的结果,而是指示出业果之道。

    网友:今天是某市千僧颂经斋宴的好日子,尽管各地又雨又雾,这里却是阳光普照!既有祈求平安衣食无忧的普通人、亦有祈求升官发大财的达官贵人,那么请问,佛祖观音会让他们都如愿吗?

    学诚法师:佛菩萨对众生的加持,就如同向导为迷途之人指路、医生为病人开药一样,能否得到利益,要看自己是否依照指示去行路、是否遵医嘱服药,一切都遵循业果法则的规律。

    念佛诵经 为什么菩萨没保佑我呢?

     


    转载本站文章《typescript参照C#/java/swift学习小结》,
    请注明出处:https://www.zhoulujun.cn/html/webfront/ECMAScript/typescript/2014_0306_6074.html