C#、TS和Dart对比2:变量和作用域
一、变量的声明、赋值和类型推断
1、C#
//C#是完全面向对象语言,所有代码都必须在类中 //Program类的Main方法,是程序的入口函数 public class Program { static void Main(string[] args) { int a1; //声明变量 a1 = 1; //变量赋值 int a2 = 2; //声明变量时初始化 int a3 = a2*2; //初始化时,可以使用表达式进行运算 /* 报错,使用变量a4时,未被赋值。变量使用前,必须已赋值 int a4; int a5 = a4*3; */ var a6 = 1; //类型推断,编译器自动推断a5类型为int Console.WriteLine(a1); //1 Console.WriteLine(a2); //2 Console.WriteLine(a3); //4 Console.WriteLine(a6); //1 } }
2、TS
//TS中,变量和函数都是顶级成员和一等公民,可以在全局定义和使用 let a1:number; a1 = 1; let a2:number = 2; let a3:number = a2*2; /*
以下代码报错 let a4:number; let a5:number = a4*3; */ /* TS中定义变量可以使用var或let 但var和JS中一样,存在变量提升和全局作用域的问题,在for循环、嵌套作用域中,存在奇奇怪怪的问题,不建议使用 所以在TS中,定义变量,建议一律使用let,和C#/Dart中的var一样,都是块级作用域 */ let a6 = 1; //类型推断为number console.log(a1,a2,a3,a6); //1 2 4 1
3、Dart
//Dart中的变量和函数也是顶级成员和一等公民,可以在全局定义和使用 //main函数是程序入口函数 void main(List<String> args) { int a1; a1 = 1; int a2 = 2; int a3 = a2 * 2; /*
以下代码报错 int a4; int a5 = a4 * 2; */ var a6 = 1; //类型推断为int类型,和C#一样,使用var关键字 print(a1); //1 print(a2); //2 print(a3); //4 print(a6); //1
//Dart还具有动态语言特征,以下代码不会报错。但是不建议这么使用,请按强类型语言来使用
var a7;
a7 = 123;
a7 = "abc"; }
4、总结:值以二进制形式储存在内存中,理论上可以通过内存地址访问,但对开发来说,这不现实。变量相当于内存地址的别名,通过变量就可以方便的进行值的访问和操作。
二、作用域
1、几乎所有语言,都以中括号{}来划分作用域,如上例中C#和Dart。TS和Dart存在全局使用域,可以在全局作用域中定义/使用变量和函数。而C#不存在全局作用域,变量和函数都必须在类中定义/使用。
2、作用域可以嵌套作用域,如【class program{ Main(){} }】,存在两个作用域,一个是class program{}类,一个是Main(){}方法。
3、当存在作用域嵌套时,内层作用域可以使用外层作用域的变量,反过来则不行。
4、内层作用域使用变量时,会先从当前作用域找,如果找不到,则向外逐层开始找,如果到最外层还找不到,则报错-变量未定义或赋值。
5、有一个形象的比喻,作用域就是汽车的隐私玻璃,里面可以看到外面,但外面看不到里面。
6、以C#为例说明,TS和Dart的作用域原理基本一样。注:TS作用域有效的前提是使用let声明变量,如果使用var,会存在变量提升问题(变量会提升到全局作用域),所以TS中是定义变量,如无特殊需求,请使用let。
public class Program { static void Main(string[] args) { int a1 = 1; Console.WriteLine(a1); //1 //Console.WriteLine(a2); 报错,无法看到内层作用域的变量 //Console.WriteLine(a3); 报错,无法看到内层作用域的变量 { int a2 = a1*2; //当前作用域找不到a1时,向外层作用域找a1,找到a1=1 Console.WriteLine(a1); //1,在外层作用域找到a1 Console.WriteLine(a2); //2,在当前作用域找到a2 //Console.WriteLine(a3); //报错,无法看到内层作用域的变量 { int a3 = a1*3; //当前作用域找不到a1时,逐层向外层作用域找a1,找到a1=1 Console.WriteLine(a1); //1,在外层作用域找到a1 Console.WriteLine(a2); //2,在外层作用域找到a2 Console.WriteLine(a3); //3,在当前作用域找到a3 } } } }