Dart和JavaScript对比小结
作为一名web前端来入门dart,新语言和我们熟悉的js有所差异,写dart的过程中容易受到原有思维的影响,这里把dart和js做一个对比总结,方便查找和熟悉。
变量声明
- var 关键字
dart和js都支持var关键字,使用 var 关键词进行声明的时候,dart 会自动推断出 当前变量的类型,如果在变量声明的时候没有进行赋值,那么该类型就是动态的,类似于 TS 的 any。在类型推断上跟 TypeScript
是一致的。
众所周知,JavaScript 是一门弱类型的语言,而 Dart 是强类型的语言
但dart也支持一些弱类型,Dart 中弱类型有var
, Object
以及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
- 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
- 默认值
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
- 类型判断
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
- 类型转换
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 \n breakLine' // 不换行,输出haha \n 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) //
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); //
// 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] 向数组中添加另一个数组的所有元素
Dart和JavaScript对比小结的更多相关文章
- javascript对比两个数组,打印出差异值
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- JavaScript中数组slice和splice的对比小结
前言 今天重温了一下Javascript,看到了数组的方法,其中有两个比较相似的方法——splice和splice,看着很像,就是多了一个p,但是用法却相当不一样. 在使用中,可以通过选择一个具有强语 ...
- javascript闭包小结
对比看了几本书关于闭包的介绍,感觉<JavaScript面向对象编程指南>一书中介绍的最为清楚,其他部分书籍很多只讲结果,不讲具体原因,不易理解.总结如下 1.闭包的定义 如果一个函数会在 ...
- JavaScript 数据类型小结
数据类型对于机器而言,其意义在于更加合理的分配内存空间,而对于编程者而言,数据类型提供了我们相对应的一系列方法,对数据进行分析与处理. 在本文中,将对JavaScript数据类型的基础知识进行总结,全 ...
- JavaScript 学习小结
简要的功能点: 是一种轻量级的编程语言. JavaScript 是可插入 HTML 页面的编程代码. JavaScript 插入 HTML 页面后,可由所有的现代浏览器执行. 操作 HTML 元素 d ...
- JavaScript函数小结
JS基础知识 /********************** 1:基础知识 1 创建脚本块 1: <script language=”JavaScript”> 2: JavaScript ...
- JavaScript事件小结
我们都晓得JavaScrip事件的重要性,所以下面小结一下以备后用! 序号 事件 描述 备注 onclick 鼠标点击某个对象时触发此事件 是最常用的事件之一 onchange 用户改变域的内容时 ...
- JavaScript学习小结(一)——JavaScript入门基础
一.JavaScript语言特点 1.1.JavaScript是基于对象和事件驱动的(动态的) 它可以直接对用户或客户输入做出响应,无须经过Web服务程序.它对用户的响应,是采用以事件驱动的方式进行的 ...
- javascript事件小结(事件处理程序方式)--javascript高级程序设计笔记
1.事件流:描述的是从页面中接收事件的顺序. 2.事件冒泡:IE的事件流叫做事件冒泡,即事件开始从具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到不具体的节点(文档). 3.事件捕获 ...
随机推荐
- Spark之RDD依赖关系及DAG逻辑视图
RDD依赖关系为成两种:窄依赖(Narrow Dependency).宽依赖(Shuffle Dependency).窄依赖表示每个父RDD中的Partition最多被子RDD的一个Partition ...
- 小程序canvas绘制base64数据格式图片
翻了微信小程序官方文档,看了看画板drawImage的用法,官方对所要绘制的图片资源路径并没有很详细,模棱两可,没说支持什么格式的路径.今天我就试一下支不支持base64格式的图片 随便找张图片从网上 ...
- Tomcat组件梳理—Service组件
Tomcat组件梳理-Service组件 1.组件定义 Tomcat中只有一个Server,一个Server可以用多个Service,一个Service可以有多个Connector和一个Contain ...
- 题解 POJ 2559-SP1805 【HISTOGRA - Largest Rectangle in a Histogram】
题目链接: https://www.luogu.org/problemnew/show/SP1805 http://poj.org/problem?id=2559 思路: ## 单调栈 首先如果所有矩 ...
- Python进阶(一)----函数
Python进阶(一)----函数初识 一丶函数的初识 什么函数: 函数是以功能为导向.一个函数封装一个功能 函数的优点: 1.减少代码的重复性, 2.增强了代码的可读性 二丶函数的结构 ...
- 对比分析HashMap、LinkedHashMap、TreeMap
HashMap的原理 :简单地说,HashMap 在底层将 key-value 当成一个整体进行处理,这个整体就是一个 Entry 对象.HashMap 底层采用一个 Entry[] 数组来保存所有的 ...
- vue中is与:is的区别
简略回答 假设父组件中有一个show数据,show="one":is="show"-->实际上是is="one" is="s ...
- workermanPHP聊天框架项目windows环境部署实践
一.官方下载地址: https://www.workerman.net/workerman-chat 二.下载后解压至任意目录,如下图: 三.windows需配置PHP环境变量,如下图: 四.双击st ...
- Java 之 Session
Session 一.概述 Session技术:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象(HttpSession)中. 二.使用步骤 1.获取 HttpSession ...
- jetbrains全家桶激活
56ZS5PQ1RF-eyJsaWNlbnNlSWQiOiI1NlpTNVBRMVJGIiwibGljZW5zZWVOYW1lIjoi5q2j54mI5o6I5p2DIC4iLCJhc3NpZ25lZ ...