zoukankan      html  css  js  c++  java
  • Dart和JavaScript对比小结

    作为一名web前端来入门dart,新语言和我们熟悉的js有所差异,写dart的过程中容易受到原有思维的影响,这里把dart和js做一个对比总结,方便查找和熟悉。

    变量声明

    1. var 关键字

    dart和js都支持var关键字,使用 var 关键词进行声明的时候,dart 会自动推断出 当前变量的类型,如果在变量声明的时候没有进行赋值,那么该类型就是动态的,类似于 TS 的 any。在类型推断上跟 TypeScript 是一致的。

    众所周知,JavaScript 是一门弱类型的语言,而 Dart 是强类型的语言

    但dart也支持一些弱类型,Dart 中弱类型有varObject 以及dynamic

    大家在学习dart的过程中,可能有疑问:同为弱类型,var, Object 以及dynamic有什么区别?

    (1) var 初始可定义, 如果有初始值,那么其类型将会被锁定,定义之后不可改变类型

    (2) Object 动态任意类型,编译阶段检查类型

    (3) dynamic 动态任意类型,编译阶段不检查类型

    var 初始化确定类型后不可更改类型, Object 以及dynamic 可以更改类型

    Object 编译阶段检查类型, 而 dynamic 编译阶段不检查类型

    // 同样在声明的时候类型
    var a = 'defalut';
    Object b = 'defalut';
    dynamic c = 'defalut'; // 编译时不会检查数据类型
    
    a = 123; 
    //出现报错提示A value of type 'int' can't be assigned to a variable of type 'String'
    //Try changing the type of the variable, or casting the right-hand type to 'String'
    
    b = 123;
    c = 123;
    
    b.foo(); // 出现报错提示The method 'foo' isn't defined for the class 'Object'.
    // Try correcting the name to the name of an existing method, or defining a method 
    // named 'foo'.dart(undefined_method)
    
    c.foo(); // 通过它定义的变量会关闭类型检查,这段代码静态类型检查不会报错,但是运行时会crash,
    // 因为mic并没有foo()方法,所以建议大家在编程时不要直接使用dynamic
    1. final 关键字  

    在学习dart 的过程中,很快就能接触到 final 关键字,大家会发现它和 const 其实很像,都是必须初始化,初始化后都是只读的,不可变

    但此时可能又会发出灵魂疑问:final和const有啥区别?

    它们的区别在于,const比final更加严格。final只是要求变量在初始化后值不变,但通过final,我们无法在编译时(运行之前)知道这个变量的值;而const所修饰的是编译时常量,我们在编译时就已经知道了它的值。

    // 定义常量
    final a = 90;
    static const b = 90;
    
    final c = new DateTime.now(); // 在编译时不知道他的值
    static const d = new DateTime.now(); // Const variables must be initialized with a
    // constant value.Try changing the initializer to be a constant 
    1. 默认值

    js中变量的初始值是undefined

    var a 
    console.log(a) // undefined

    在 Dart 中,未初始化的变量拥有一个默认的初始化值: null。即便数字也是如此,因为在 Dart 中一切皆为对象,数字也不例外。要用final的话必须定义一个初始值

    var some;  // -> null
    bool flag;  // -> null
    int number;  // -> null
    String str;  // -> null
    Object obj;  // -> null
    final namic;  // Error: must be initialized
    1. 类型判断

    js用 typeof 来判断基本类型(字符串(string)、数值(number)、布尔值(boolean)、undefined),用 instanceof 来判断引用类型(Object对象Array数组Function函数)

    var a = 0
    var b = '0'
    var c
    var d = true
    
    var e = {}
    var f = []
    var g = function(){}
    
    typeof a // number
    typeof b // string
    typeof c // undefined
    typeof d // boolean
    
    e instanceof Object // true
    f instanceof Array // true
    g instanceof Function // true

    dart 用关键字 is 来进行类型判断,返回布尔值,ps: assert 生产环境忽略,debug模式开启

    var a = 123;
    print(a is dynamic);  // true
    assert(a is Object);  // true
    1. 类型转换

    js除了自动类型转换之外,还有类型转换的方法

    // json和字符串互相转换
    var obj = {a:'2.2'}
    var str = JSON.stringify(obj) // "{"a":"2.2"}"
    JSON.parse(str) // {a: "2.2"}
    Number(obj.a) // 2.2 // 转成number类型
    parseInt(obj.a) // 2 转成int类型

    在实际项目中,后台接口往往会返回一些结构化数据,如JSON、XML等,可以通过dart:convert中内置的JSON解码器json.decode() 来进行转换。

    通过json.decode() 将JSON字符串转为List/Map的方法比较简单,它没有外部依赖或其它的设置,对于小项目很方便。但当项目变大时,这种手动编写序列化逻辑可能变得难以管理且容易出错,JSON.decode()仅返回一个Map<String, dynamic>,这意味着我们直到运行时才知道值的类型。 通过这种方法,我们失去了大部分静态类型语言特性:类型安全、自动补全和最重要的编译时异常。

    // 内连序列化JSON 使用 dart:convert手动序列化JSON
    // JSON.decode方法来解码JSON
    //一个JSON格式的用户列表字符串
    String jsonStr='[{"name":"Jack"},{"name":"Rose"}]';
    //将JSON字符串转为Dart对象(此处是List)
    List items=json.decode(jsonStr);
    //输出第一个用户的姓名
    print(items[0]["name"]);

    可以通过引入一个简单的模型类(Model class)来解决前面提到的问题

    这样,调用代码现在可以具有类型安全、自动补全字段(name和email)以及编译时异常。如果我们将拼写错误字段视为int类型而不是String, 那么我们的代码就不会通过编译,而不是在运行时崩溃。

    官方推荐的json_serializable package包 

    操作方法:JSON 转dart Model 类 

    布尔值

    在js中,自动类型转换,使用判断的时候空字符串,0,null,undefined都会被转换为false

    var flag = 1 == '1';
    console.log(flag);  // -> true

    Dart是强类型语言,不会进行自动类型转换,在判断的时候就要注意了

    bool flag = 1 == '1';
    print(flag);  // -> false
    // 检查是否为空字符串。
    var fullName = '';
    assert(fullName.isEmpty);
    // 检查是否小于等于零。
    var hitPoints = 0;
    assert(hitPoints <= 0);
    // 检查是否为 null。
    var unicorn;
    assert(unicorn == null);
    // 检查是否为 NaN。
    var iMeantToDoThis = 0 / 0;
    assert(iMeantToDoThis.isNaN);

    字符串

    js

    var str = 'string' // 单引号
    var str2 = "string2" // 双引号
    var str3 = 'test ' + "string" // 字符串拼接
    var str4 = `string3${str2}` // 反引号-变量字符串
    
    str.length // 6 字符串长度
    str.charAt(1) // s 返回给定位置的字符
    str.charcodeAt(1) // 返回给定位置字符的字符编码
    str[1] //s ie8+
    
    str.concat('a') //stringa 可以接受任意多个参数拼接成新的字符串,但不会改变原字符串
    str.slice(0,3) //str 截取字符串
    str.substring(3) //ing 截取字符串
    str.substr(0,1) //s 截取字符串
    str.indexOf('s') // 0 可接受两个参数,找到返回位置,找不到返回-1
    str.lastIndexOf('t') // 1 从数组的末尾开始查找
    str.trim() //删除前置和后缀的空格 返回的是字符串的副本,原始字符串不变
    
    str.toLowerCase() //转小写
    str.toUpperCase() //转大写
    str.toLocaleLowerCase() //string 转小写,针对地区的方法
    str.toLocaleUpperCase() //STRING 转大写,针对地区的方法
    
    str.match('s') // ["s", index: 0, input: "string", groups: undefined]
    str.search('s') //0 接受一个正则,返回字符串中第一个匹配项的索引,没有返回-1
    str.replace('s','c') //ctring 替换字符串,可正则匹配
    str.split() //["string"] 分割字符串,并返回一个数组。

    dart

    String a = 'string' // 单引号 
    String b = "string" // 双引号 
     // 多行字符串
    String c = '''string 
    huanhang'''
    // 使用前缀 r 创建 raw string,字符串内不会进行转义
    String d = r'haha 
     breakLine' // 不换行,输出haha 
     breakLine
    // 使用变量$name或${name}都可以,前一种方法的后面不能直接跟字符串,要用空格或者逗号等方式隔开
    String name = 'hello';
    assert('$name string'); // hello string
    assert('${name} string'); // hello string
    assert(name.length); // 6 字符串长度
    assert(name.isEmpty) // false 判断是否为空
    assert(name.isNotEmpty) // true 是否不为空
    assert(name.substring(0, 2)) // he 字符串切割
    assert(name.substring(3)) // lo 从指定index至末尾
    String e = "a,b,,"; 
    List<String> a6 = e.split(",");// 使用,分割,返回的是一个数组,同js [a,b, , ]
    // 查找并替换 相当于split 和 join
    String f = "a b,c";
    String g = f.splitMapJoin(",",//查询“,”
       onMatch: (Match match) { // 用匹配的值替换
         return "a";
       }, onNonMatch: (String nonMatch) { // 用不匹配的值替换
         return "b";
       });
    assert(g);//bab    a b,c  =>   bab
    // 字符串判断
    String = 'aabbbcccc';
    assert(h.startsWith("aa")); //true startsWith以某某开始
    assert(h.startsWith("aa", 3)); //false 从index=3开始判断
    assert(h.endsWith("c")); //true endsWith 以xx结尾
    assert(h.contains("ab")); //true contains是否包含
    assert(h.contains("ac")); //false
    assert(h.contains("ab", 3)); //false 从index=3开始判断
    // 字符串替换
    String i = "stringing";
    assert(i.replaceAll("st","cc"));// ccringing 替换全部符合条件的
    assert(i.replaceFirst("ing", "ss"));//strssing 只替换第一个符合条件的
    assert(i.replaceFirst("ing", "dd",5));//stringdd 从index=5开始 替换第一个符合条件的
    assert(i.replaceRange(0, 3, "z"));// zinging 范围替换 从0-3 含0不含3
    assert(i.replaceAllMapped("i", (Match match){//stryngyng 用方法返回值替换指定的字符串
      return "y";
    }));
    assert(i.replaceFirstMapped("i", (Match match){
      return "333";
    },5)); //string333ng 从index=5开始 用方法返回值替换指定的字符串
    // 字符串查找
    Sting j = 'hello'
    assert(j.indexOf('l')); // 2 从前往后找 返回第一个符合条件的index
    assert(j.lastIndexOf('l')); // 3 从后往前找 返回第一个符合条件的index
    // 转换为大小写
    Stinrg k = 'aaBBcC'
    assert(k.toLowerCase()); // aabbcc
    assert(k.toUpperCase()); // AABBCC  
    // 去除空格
    String l = " aab bcc ";
    assert(l.trim()); //aabbcc 去除左右空格
    assert(l.trimLeft()); //aabbcc 去除左边空格
    assert(l.trimRight()); // aabbcc去除右边空格
    // 补齐长度 剩余位使用指定字符串替换
    String j = "111";
    assert(j.padLeft(6));// 111 剩余3个位 默认使用""补齐
    assert(j.padRight(6,"c")); //111ccc 剩余3个位 指定使用"c"
    assert(j.padRight(6,"dd")); //111dddddd 剩余3个位 每个位指定使用"dd" 替换后总长度不是6
    assert(j.padLeft(2,"e"));//111 如果指定长度小于原字符串长度 返回原字符串

    对象

    js

    var gifts = {
      'first': 'partridge',
      'second': 'turtledoves'
    };
    gifts.first = 'hhh'
    // Object.keys(obj) 返回对象的key组成的数组
    // Object.values(obj) 返回对象的value组成的数组
    // Object.assign() 可以将源对象复制到目标对象中
    // Object.entries(obj) 返回对象的key和value组成的数组
    // obj.hasOwnProperty() hasOwnProperty 方法判断对象中属性是否存在

    dart

    var gifts = {
      'first': 'partridge',
      'second': 'turtledoves'
    };
    var gifts = Map();
    gifts['first'] = 'partridge';
    gifts['second'] = 'turtledoves';

    数组

    js

    var list = [1, 2, 3, 4, 5];
    var list1 = [1, 2, 3];
    var list2 = [4, 5];
    
    console.log(list.length) // 3
    list1.concat(list2) // [1, 2, 3, 4, 5] 连接两个或更多的数组,并返回结果。
    list.every(i=>i>3) // false 检测数值元素的每个元素是否都符合条件。
    list.some(i=>i>3) // true 检测数值元素是否有符合条件的值
    list.filter(i=>i>3)    // [4, 5] 检测数值元素,并返回符合条件所有元素的数组。
    list.find(i=>i=3) // 1 返回符合传入测试(函数)条件的数组元素。
    list.forEach() // 遍历数组
    list.join('') // 12345 把数组的所有元素放入一个字符串。
    list.map(i=>i+1) // [2, 3, 4, 5, 6] 通过指定函数处理数组的每个元素,并返回处理后的数组。
    list.pop() // 5 删除数组的最后一个元素并返回删除的元素。
    list.push(8) // 5 向数组的末尾添加一个或更多元素,并返回新的长度。
    list.shift() // 1 删除并返回数组的第一个元素。
    list.sort() // 排序
    list.toString() // 1,2,3,4,5 把数组转换为字符串,并返回结果。
    list.unshift(8) // [8, 1, 2, 3, 4, 5, 6] 向数组的开头添加一个或更多元素,并返回新的长度。
    list.reduce((curr, next) => curr + next); // 15 数组相加的总和

    dart

    var list = [1, 2, 3];
    assert(list.length == 3);
    assert(list[1] == 2);
    
    list[1] = 1;
    assert(list[1] == 1);
    
    // 同js
    list.forEach((i) => print(i)); // 遍历数组
    list.map(i=>i+1) // [2, 3, 4]
    list.sort((num1, num2) => num1 - num2); // 排序
    list.every(i=>i<5) // true 用法同上
    list.reduce((curr, next) => curr + next); // 15 数组相加的总和
    
    list.fold(2,(curr, next) => curr + next);// 17 用法同reduce,有一个初始值
    list.contains(5) // false 用于判断数组是否包含某个元素
    list.where((i) => i > 2); // [3] 返回数组中满足给定条件的元素集合
    // firstWhere() 返回数组中满足给定条件的第一个元素
    list.firstWhere((i) => i > 2, orElse: () => null); // 3
    // singleWhere() 返回数组中满足给定条件的唯一一个元素,若有多个元素满足条件会抛出异常
    list.singleWhere((i) => i < 2, orElse: () => null);
    List arr = [1, 3, 5, 2, 7, 9];
    arr.take(3).toList() // [1, 3, 5] take(n) 从数组里取 n 个元素
    arr.skip(4).toList() // [7, 9] skip(n) 跳过数组中的 n 个元素
    arr.take(3).skip(2).take(1).toList() // [5]
    var clonedArr = List.from(list); // [1, 2, 3] from 克隆一个数组
    print(clonedArr);
    var arr1 = [[2, 5], [7], [11, 12]];
    arr1.expand((item) => item).toList(); // [2, 5, 7, 11, 12]
    list.expand((item) => [item * 8]).toList();// [8, 16, 24]
    // 当对每一项进行计算时类似于 map() [8, 16, 24]
    list.map((item) => item * 8).toList();
    list.add(10); // [1,2,3,10] 向数组中添加元素
    list.addAll([15, 21]); // [1,2,3,15,21] 向数组中添加另一个数组的所有元素
  • 相关阅读:
    HDU 3081 Marriage Match II
    HDU 4292 Food
    HDU 4322 Candy
    HDU 4183 Pahom on Water
    POJ 1966 Cable TV Network
    HDU 3605 Escape
    HDU 3338 Kakuro Extension
    HDU 3572 Task Schedule
    HDU 3998 Sequence
    Burning Midnight Oil
  • 原文地址:https://www.cnblogs.com/leiting/p/11908532.html
Copyright © 2011-2022 走看看