第壹章第1节 C#和TS/UTS语言对比-基础语法

C#、JS/TS/UTS的最基础语法,包括了变量、常量、运算符、控制语句和作用域。我觉得大家应该可以在5分钟之内看完。。。what!开个玩笑!大家可以多看看作用域这节,还是费了点心思来缕清楚的。

一、程序开始

1.1 C#程序的开始

//Program.cs
//C#的代码都必须包含在类中,Program类是程序默认的入口类,Main方法是程序默认的入口方法
//关于类,详见类章节
public class Program
{ 

    public string Country = "cn"; //类的成员之一:字段

    public string Street{get;set} //类的成员之二:属性,本质上是方法

    public void SayHi(){Console.WriteLine("Hi");} //类的成员之三:方法

    //Main方法,也是类的成员之一,它比较特殊,是程序的入口方法
    static void Main(string[] args)
    { 
        SyaHi(); //调用函数
        var a = 10; //定义变量
        Console.WriteLine(a); //控制台打印变量a的值
                              //WriteLine()是Console类的静态方法
    }
}

1.2 TS程序的开始(JS和UTS一样)

//如果没有工程化,我们要创建立即执行函数来模拟程序入口
//函数式编程,可以直接在全局作用域中定义任意元素
()=>{
  
  let x = 1; //定义变量
  console.log(x); //调用console对象的方法log(),控制台打印变量x的值
  
  function func(){console.log("hi");} //定义函数
  func(); //调用函数
  
}();

二、命名规范

2.1 C#命名规范

  1. 类/枚举/结构体/委托:大驼峰
  2. 接口:I大驼峰
  3. 方法/属性/事件:大驼峰
  4. 字段:_小驼峰
  5. 变量/参数:小驼峰
  6. 明确使用访问修饰词,如public、private、protect、internal,默认是private

2.2 TS命名规范(JS和UTS一样)

  1. 类/枚举:大驼峰
  2. 接口:I大驼峰
  3. 方法/属性:小驼峰
  4. 变量/参数:小驼峰
  5. 除非必要,不用加访问修饰词,默认为public,按需使用private和protect

三、定义变量和常量

3.1 C#中定义变量和常量

//1、定义变量========================================================================
//C#中,变量必须在方法内部定义和使用,不存在脱离类的全局变量
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; //使用var定义,类型推断,编译器自动推断a5类型为int
        //var a6;  //报错,使用自动推荐功能,申明变量时必须初始化
    }
}



//2、定义编译时常量==================================================================
//编译时,比如在编写代码时、重新生成时,代码编辑器会自动调用编译器对代码进行检查和编译
//运行时,比如调试状态中运行的程序、项目上线后运行的程序
public class Program
{
    static void Main(string[] args)
    {
        //const int a; //报错,const定义编译时常量,必须初始化赋值
      
        const int a = 1; //定义方法中的本地常量
        //a = 2; //报错,常量赋值后不能再改变
    }
}

//类中的常量字段,详见《类》

3.2 TS中定义变量和常量(UTS和TS一样)

//1、定义变量========================================================================
//使用let,不要使用var
let a = 1 //自动推断类型,指定类型方式:let a:number = 1
a = 2 //通过
a = "hello" //报错,申明是自动推导为number类型,不能再赋值为string类型
let b:number //如果申明变量时没有初始化,则必须确定类型

//使用let后,不存在变量提升,它们定义的变量有明确的作用域。不要再使用var。

//var a //下面代码中,a使用了var,变量定义会提升到全局作用域,重复申明,报错
{
    let a = 1 //通过
    var a = 1 //报错
}



//2、const定义编译时常量=============================================================
const a = 1
a = 2 //报错,常量不能修改值

const b = {name:"mc",age:28}; b.age = 40; //通过,为什么?详见下节的类型概述

class Program{
    //public const a2:number = 1; //报错,不能在类中使用const创建数据成员
    main():number{
        const a2:number = 2; //可以在方法中定义局部常量
        return a1+a2;
    }
}

//类中的常量属性,详见《类》

四、运算符(C#和TS几乎一样)

4.1 基本的运算符(赋值、比较、算术、逻辑、三元)

//1、赋值运算符=====================================================================
x = y	x = y
x += y	x = x + y
x -= y	x = x - y
x *= y	x = x * y
x /= y	x = x / y
x %= y	x = x % y //取余



//2、比较运算符,返回true或false=====================================================
//值类型比较值,引用类型比较地址
var1==var2
var1!=var2
//只能用于数值类型
var1>var2
var1>=var2
var1<var2
var1<=var2
//***注意JS和TS中的双等号,等式两边会自动转换类型后再进行比较,三等号是全比较
1 == "1" //true,自动转换类型了
1 === "1" //false,不会自动转换类型,即仅值要一样,类型也要一样
//***UTS中,强类型约束,两等号必须类型和值都一样,三等号只用于判断引用类型的地址



//3、算数运算符=====================================================================
++ //有前后之分。(let a=++b; b先自增,再赋值给a) (let c=b++; b先赋值给c,再自增)
--
+
-
*
/
% //取余。TS例子:let a = 10%3;(a=1)

  

//4、逻辑运算符=====================================================================
//JS和TS中condition会自动转换,0、""、null、undefined、false等为假,其它为真
//UTS不会自动转换,condition必须为boolean类型。强类型语言C#,也是如此
condition1 && condition2	//逻辑与
condition1 || condition2	//逻辑或
!condition1	//逻辑非


//5、三元运算符?:===================================================================
const status = age >= 18 ? "adult" : "minor"

4.2 字符串运算符

//1、字符串连接======================================================================
"my " + "string"; 

//转义字符
\\ //反斜杠本身
\' //单引号
\" //双引号
\n //换行
\r //回车
\t //制表符
\b //退格
\f //换页


//2、C#的模板字符串(插值)===========================================================
string name = "mc";
int age = 28;
string greeting = $"Hello, 我是{name},我今年{age}岁了";
//C#的原始字符串,带来JS中``的爽感,不用再到处写转义符了(C#11新增功能)
var jsonStr = """{"id":1, "url":"/static/my.jpg", "name":"MC"}""";
//或者多行(多行时,首尾的""",必须独占一行)
var jsonStr = """
  {
    "id":1, 
    "url":"/static/my.jpg", 
    "name":"MC"
  }
""";
//和模板字符串一起使用,注意是$$,{{}}。如果里面
var jsonStr = $$"""
  {
    "id":1, 
    "url":"/static/my.jpg", 
    "name":{{name}}
  }
""";
//插值变量外面需要有{}符号,输出you are at:{...},{...}
var location = $$"""
   You are at:{{{Longitude}}, {{Latitude}}}
   """;
//之前还有一个@原义标识符,有了原始字符串后,可以丢弃


//3、JS、TS和UTS的模板字符串=========================================================
const name = 'mc';
const age = 28;
const greeting = `Hello, 我是${name},我今年${age}岁了`;

4.3 展开运算符

//1、C#中的展开运算符和集合字面量定义,在C#11中带来,比较新,使用上有限制===============
int[] a = [1, 2, 3, 4, 5, 6, 7, 8]; //创建数组
List<string> b = ["one", "two", "three"]; //创建集合
Span<char> c  = ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'i']; //创建span
int[][] twoD = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; //创建二维数组
//展开运算符
int[] row0 = [1, 2, 3];
int[] row1 = [4, 5, 6];
int[] row2 = [7, 8, 9];
int[] single = [..row0, ..row1, ..row2]; //创建数组



//2、JS、TS和UTS中的展开运算符=======================================================
const array1 = ['a', 'b'];
const array2 = ['c', ...array1, 'd']; //将数组展开
myFunction('a', ...['b', 'c']); //函数调用,展开参数
this.dataList.push(...res.data); //操作数组

//函数的剩余参数
function fn(str: string, ...args: string[]) {
  console.log(str, args)
}

//还可以操作对象
const person = { name: "John", age: 30, city: "New York" };
const updatedPerson = { age: 35, occupation: "Software Engineer" };
const updatedUser = {...person, ...updatedPerson};

4.4 可空类型运算符

//1、C#定义可空类型变量==============================================================
string? a = null //?紧跟类型

  
//2、TS定义可空类型变量==============================================================
let a:string|null = null
let a?:string = null //?紧跟变量
  

//3、C#和TS中,使用方式一样==========================================================

//使用方法A,if判断
if (a != null) {} 

//使用方法B:成员调用,?.运算符,可以连续使用
console.log(a?.length) 
bob?.department?.head?.name

//使用方法C:空值合并,??运算符
let b = a??"hello" //如果a不为空,则直接赋值给b;如果为空,则将默认值"hello"赋值给b

//使用方法D:非空断言,!运算符,明确知道有值时使用
const l = a!.length

4.5 类型断言运算符

//C#中的类型断言,复杂些,涉及多态====================================================
class Parent{}

class Child : Parent
{
    public void SomeMethod() { }
}

class Program
{
    static void Main()
    {
        //变量obj是Parent类型,但可以指向Child类型的实例对象,详见《多态》章节
        Parent obj = new Child(); 

        // 尝试进行类型断言
        Child childObj = obj as Child;
        if (childObj!= null)
        {
            childObj.SomeMethod(); 
        }
    }
}

//2、JS不存在类型断言,以下为TS/UTS中的类型断言=======================================
const a: any = 'a' //申明时不确定,赋值后可以确定了
a as string //所以可以断言为string,之后可以当成string类型使用
const a: string | null = 'a'
a as string
1.0 as Double
1.0 as number
type t = {id:number}; {"id":1} as t
{"id":1} as UTSJSONObject; //UTSJSONObject是UTS中的内置类型,是字面量对象的默认类型

4.6 类型操作运算符

//C#中的类型操作,typeof和GetType()==================================================
//C#的typeof和GetType主要用于返回类型的元数据,用于反射操作,作用更大

//typeof,参数为类型,返回类型的元数据,编译期确定
typeof(int);
class Student{}
typeof(Student);

//GetType是所有实例对象都有的一个方法,在运行期获取实例对象所属的类型元数据
var s1 = new Student();
s1.GetType();



//2、JS、TS和UTS中的类型操作,typeof和instanceof======================================
//typeof用于返回变量或表达式的类型,UTS中可以返回kotlin或swift的原生类型
let a = 10.0
let b: Double = 3.14 //原生类型
let c: Int = 2 //原生类型
typeof a == "number" //true
typeof b == "Double" //true
typeof c == "Int" //true

//typeof的结果,即可用于判断实例,也可用于判断类,但判断类型没有实际意义
boolean类型对象 > boolean
number类型对象 > number
string类型对象 > string
null > object
any > 运行时的实际类型
function > function //function是一种特殊类型
class类名 > function
class实例 > object
interface接口名 > undefined
type类型别名 > object
内置对象,如Array、Data等 > object
平台专有的数值和字符串类型 > 相对应的平台数据类型 (UTS适用)

//instanceof用于判断对象的原型链上是否有该类实例
//boolean,number,string,null,any等基本类型不能使用
//内置对象,如Array、Data等 > 具体的内置类型
//自定义类型 > 具体定义的类型或其父类
function fn(obj: any) {
  if (obj instanceof Date) {
    // ...
  }
}
class MyClass{}
type MyType = {name:string}
let myClass = new MyClass()
let myType:MyType = {name:"MC"}
console.log(myClass instanceof MyClass) //true
console.log(myType instanceof MyType) //true

五、控制流程(C#和TS几乎一样,例子为TS)

5.1 条件分支

//1、if=============================================================================
if (condition_1) {
    // statement_1;
} else if (condition_2) {
    // statement_2;
} else {
    // statement_last;
}



//2、switch=========================================================================
switch (expression) {
   case label_1:
      // statements_1
      break;
   case label_2:
      // statements_2
      break;
   default:
      // statements_def
      break;
}

5.2 循环

//1、for============================================================================
for (let i = 0; i < 10; i++) {
    //...
}
//Array等集合类型可以使用集合类型的实例方法forEach()



//2、while==========================================================================
let n = 0;
let x = 0;
while (n < 3) {
    n++;
    x+=n;
}



//3、do while=======================================================================
let i = 0;
do {
    i += 1;
} while (i < 10);



//4、break/continue=================================================================
//break,跳出当前整个循环
let x = 0;
while (true) {
    x++;
    if (x > 5) {
        break;
    }
} // 输出 6

//continue,跳出当次循环,继续下一个循环
for (let i = 0; i < 10; i++) {
    if (i > 5) {
        console.log(i)
        continue; // continue 后,本次循环结束,i+1后开始下一次循环。
        // 这里的代码不会被执行,因为上一行 continue 了
    }
}



//***5、C#中的foreach循环和TS中的forof/forEach/forin=================================

//C#中的foreach--------------------------
int[] numbers = { 10, 20, 30, 40, 50 };
foreach (int num in numbers) //int类型定义,可以使用var代替,类型推断
{
    Console.WriteLine(num);
}

//TS中的for...of,遍历可迭代对象-----------------
let numbers: number[] = [10, 20, 30, 40, 50];
for (let num of nmbers) {
  console.log(num);
}

//TS中的forEach,可迭代对象的实例方法-----------
let numbers: number[] = [10, 20, 30, 40, 50];
numbers.forEach(num => {
  console.log(num);
});

//TS中的for...in,遍历对象-------------------
const person: {name:string;age:number} = {
  name: "John",
  age: 30
};
for (const key in person) {
  console.log(`Key: ${key}, Value: ${person[key]}`);
}

5.3 异常

//抛出异常
throw new Error("Hi There!");

//捕获异常
try {
    // 检测的代码
} catch (e: Error) {
    // 捕获到异常后执行
} finally {
    // 无论是否捕获到异常,都会执行
}

六、作用域

2.1 C#中的作用域

作用域指当前代码执行的环境。这个环境包括硬件和软件两个层面,硬件通常指机算机划给程序运行的内存区域,软件是指程序的运行时环境。C#是类型化的语言,所有代码都必须包含在类中,作用域划分清晰,符号{}定义了作用域,作用域之间的嵌套关系也很明确,所以在C#中很少有作用域的问题。

public class Program
{ //程序开始,在内存中创建一个作用域A

    public string Country = "cn"; //字段Country在作用域A内
  
    static void Main(string[] args)
    { //方法Main开始,创建一个作用域B

        //在new Student()创建实例时,也会创建一个作用域B1,执行完并将对象赋值给s1后销毁
        var student = new Student("mc",28);
      
        //Console.WriteLine(x); //报错,不能访问嵌套的内部作用域变量x
      
        { //创建作用域B2
            var x = 1; //变量x在作用域B2内

            //可以访问外部作用域定义的变量student
            //嵌套作用域中,内层作用域可以使用外层作用域的变量,反过来则不行
            //内层作用域使用变量时,会先从当前作用域找,如果找不到,则向外逐层开始找
            //如果到最外层还找不到,则报错
            Console.WriteLine(student.Name); 
          
        } //销毁作用域B2
      
    } //方法Main结束,作用域B销毁
  
} //程序结束,作用域A销毁


public class Student
{
    public string Name; 
    public int Age; 
    public Shape(string name, int age)
    {
        //Shape()是构造函数,构造函数内的this,指向调用构造函数时创建出来的实例对象
        this.Name = name;
        this.Age = age
    }
}

2.2 TS中的作用域(JS和UTS一样)

  1. TS中存在全局作用域(程序入口)、函数作用域(函数/模块)和块级作用域({}内)
  2. 作用域是静态的,编写代码时就确定,但代码运行时有一个执行上下文,这个是动态的
  3. 执行上下文可以认为是代码执行时所在的对象,this指向的就是这个对象
  4. 全局执行上下文,浏览器端是window,node端是global,存在于整个程序的生命周期
  5. 函数执行上下文,函数运行开始前创建,函数运行结束后销毁
  6. 模块化后,包含export的文件就是一个模块,模块作用域本质上是一个函数作用域
  7. 再说this指向问题,也即执行上下文的问题:
    • 在全局环境下,this指向全局对象
    • 普通函数的this是动态的,指向调用该函数的对象,call()、apply()和bind()方法可以动态变换this
    • 箭头函数的this是静态的,指定定义时所在的对象,call()、apply()和bind()方法不能动态变换this
    • 在使用类(构造函数)创建对象实例时,this指向新创建的实例对象,和C#表现一致
//假设当前运行环境为浏览器,当前文件为程序入口
//程序开始,创建全局作用域A,全局执行上下文为window

let a = 1; //变量a在全局作用域内,运行在全局上下文window中

console.log(this); //log方法在全局上下文中执行,this指向window

//函数func在全局作用域A内,此处代码只是定义,没有执行,没有函数执行上下文
function func(){ //函数开始执行前,创建函数作用域B(调用函数时才会创建)
  
  let x = 1; //变量x在作用域B内
  console.log(this) //函数运行时才有this,此例指向window,定义时没有执行上下文
  var y = 1; //使用var定义,变量y会提升到全局作用域,挂在window下,易出错,不要用
  
  { //创建块级作用域B1
     var z = 1; //变量z在块级作用域B1内
     console.log(x); //可以访问外部作用域定义的变量x
     console.log(this); //块级作用域的this继承自所在的函数
  } //销毁块级作用域B1
  
}  //销毁函数作用域B

func(); //调用函数,创建函数作用域B,在全局对象中调用,this指向window

//this是window
const arrowFn = () => console.log(this);
arrowFn();

//this是obj,call()方法不能变更this
const obj = { 
  arrowFn: () => console.log(this) 
}; 
const newContext = { name: 'New Context' }; 
obj.arrowFn.call(newContext); 

  • 29
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Module build failed (from ./node_modules/@dcloudio/uni-cli-shared/lib/uts/uts-loader.js)是一个错误信息,它表示在使用./node_modules/@dcloudio/uni-cli-shared/lib/uts/uts-loader.js时,模块构建失败了。这个错误可能有多种原因。其中可能包括v-model绑定的空字符串、父组件向子组件传递的属性值为空、渲染字段为空或者标签缺少闭合标签。根据代码的具体情况,你可以检查这些可能的原因,找出造成错误的具体原因,并进行相应的修复。希望这些信息对你有所帮助,祝你在前端代码开发中顺利进行!<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [UTS_.NetApplicationDev_Spring_2020:https://www.handbook.uts.edu.ausubjectsdetails32998.html](https://download.csdn.net/download/weixin_42097533/15238792)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [app报错:Module build failed (from ./node_modules/@dcloudio/vue-cli-plugin-uni/packages/vue-loader/](https://blog.csdn.net/weixin_55778010/article/details/126924506)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值