首页 > 其他分享 >TS-引用类型

TS-引用类型

时间:2024-06-01 23:34:07浏览次数:15  
标签:console log array1 TS object1 let 引用 类型

1.定义

TS中的数据值分为原始值和引用值两种类型。原始值即最简单的数据,而引用值则是有多个值构成的复合对象。

原始值和引用值的声明方式类似,都需要创建常量或变量,然后对其赋值。其不同之处是,在变量或常量保存之后,可以对这个值进行的操作有所区别。

2.原始值与引用值

原始值:存储在栈中(stack)中的数据,它们的值直接存储在变量的存储空间中。

引用值:存储在堆(heap)中的对象,存储在变量中的值是一个指针,它指向实际存储对象的内存地址。

布尔类型、数值类型、长整型和字符串类型等原始类型,它们的值即原始值。这些原始类型占据的空间通常是固定的,所以可将它们存储在较小的内存区域——栈中,便于迅速查询变量的值。

引用类型通常是由多个原始值组成的复合对象类型,这些类型(数组、函数、对象与类等)将在后面一一介绍。对于引用类型的值,由于它们的大小并不固定,且通常较大,因此不能把它们放在栈中,否则会降低变量查询的速度。栈中只存放了对象在堆中的地址,而对象实际存放在堆中。

 

 3.值的复制

对于原始值,赋值时会在栈中产生一个新的副本,因此复制的值和原来的值之间没有任何联系,它们各自位于不同的栈区。

let number1 = 7;
let number2 = number1; //将number1的值复制到number2
let bool1 = true;
let bool2 = bool1;     //将bool1的值复制到bool2

 当发生修改时,各变量的栈区独立变化,互不干扰。例如,在以下代码中,对变量number1和bool1的操作不会影响number2和bool2的值。

number1 = 8;
console.log(number2); // 输出7
bool1 = false;
console.log(bool2);   //输出true

对于引用值,在赋值时会赋予变量对象的引用(即对象的存储地址),而并非对象本身,因此复制时变量复制了相同的引用地址。例如,以下代码分别创建了名为object1、object2的两个字面量对象和名为array1、array2的两个数组

let object1 = { property1: 1 };
let object2 = object1; //将object1的引用地址复制到object2
let array1 = ["a", "b", "c"]
let array2 = array1; //将array1的引用地址复制到array2 

 由于多个变量实际上引用了同一个对象,因此对该对象的修改会在其他相关引用中体现出来

object1.property1 = 2;
console.log(object2);  //输出{ property1: 2 }
array1[1] = "x";
console.log(array2); //输出["a", "x", "c"]

引用值的对象修改后在堆和栈中的存储方式如图

 

但如果重新给引用变量赋新值,引用发生改变,指向另外的堆地址,变量和原有对象不再有任何关系,两者之间互不影响。 

object2 = { property1: 3 };
array2 = ["x", "y", "z"]
console.log(object1); //输出{ property1: 2 }
console.log(array1);  //输出["a", "x", "c"]

引用值重新赋值后在堆和栈中的存储方式如图

 

4.值的传递

值的传递和值的复制具有相似的规则。对于原始值,复制各自独立的副本;而对于引用值,复制相同的引用地址。
当把原始值传递给函数的参数时,参数是全新的副本。在函数中修改参数值,并不会影响原来的值。 

let number1 = 7;
function testNumber(para: number) {
    para = 8;
}
testNumber(number1);
console.log(number1);//输出7
 
let bool1 = true;
function testBool(para: boolean) {
    bool1 = false;
}
testBool(bool1);
console.log(bool1); //输出true

当把引用值传递给函数时,传递给函数的是对原值的引用,在函数内部可以使用此引用来修改对象本身的值。代码如下。 

let object1 = { property1: 1 };
function testObject(para: any) {
    para.property1 = 2;
}
testObject(object1);
console.log(object1); //输出{ property1: 2 }
 
let array1 = ["a", "b", "c"]
function testArray(para: string[]) {
    para[1] = "x";
}
testArray(array1);
console.log(array1); //输出["a", "x", "c"]

 如果给函数参数赋予新值,引用就会发生改变,指向另外的堆地址,参数和原有对象不再有任何关系,两者之间互不影响。

function testObject2(para: any) {
    para = { property1: 3 };
}
testObject2(object1);
console.log(object1); //输出{ property1: 2 }
 
function testArray2(para: string[]) {
    para = ["x", "y", "z"];
}
testArray(array1);
console.log(array1); //输出["a", "x", "c"]

5.值的比较

 当对原始值进行比较时,会逐字节地比较,以判断它们是否相等。注意,比较的是值本身,而不是值所处的栈的位置。当比较结果为相等时,表示它们在栈中所包含的字节信息是相同的。

let number1 = 7;
let number2 = 7;
//number1 和number2的值具有相同的字节信息,比较结果为相等,输出true
console.log(number1 == number2); 
 
let bool1 = true;
let bool2 = true;
//bool1和bool2的值具有相同的字节信息,比较结果为相等,输出true
console.log(number1 == number2); 

原始值的比较方式如图 

 

当对引用值进行比较时,比较的是两个引用地址,看它们引用的是否是同一个对象,而不是比较它们的字节信息是否相同。即使两个引用值引用的对象具有相同的字节信息,如果引用的堆地址不同,它们也不是相等的。 

 

let object1 = { property1: 1 };
let object2 = { property1: 1 };
//object1和object2指向不同的对象地址,因此不相等,以下语句输出false
console.log(object1 == object2); 
let object3 = object1;
//object1和object3均指向同一个对象地址,因此相等,以下语句输出true
console.log(object1 == object3); 
object1.property1 = 5;
console.log(object1 == object3); //输出true
 
let array1 = ["a", "b", "c"];
let array2 = ["a", "b", "c"];

//array1 和array2 指向不同的对象地址,因此不相等,
//以下语句输出false
console.log(array1 == array2); 
let array3 = array1;
//array1 和array3均指向同一个对象地址,因此相等,
//以下语句输出true
console.log(array1 == array3); 
array1[1] = "x";
console.log(array1 == array3); //输出true

引用值的比较方式如图

 

6.常量的使用

 使用const关键字声明常量,而常量的值是不可改变的。例如,在以下代码中,修改常量的值会引起编译错误。

const number1 = 7;
const bool1 = true;
//编译错误:无法分配到 "number1" ,因为它是常数。ts(2588)
number1 = 8;
//编译错误:无法分配到 "bool1" ,因为它是常数。ts(2588)
bool1 = false;

然而,严格来说,常量仅能限定栈上的内容不可编辑,但堆上的内容可以编辑。例如,以下代码不会引起编译错误。 

const object1 = { property1: 1 };
const array1 = ["a", "b", "c"]
object1.property1 = 2;
array1[1] = "x";

但如果更改栈上的引用地址,就会引起编译错误,示例代码如下。

const object1 = { property1: 1 };
const array1 = ["a", "b", "c"];
// 编译错误:无法分配到 "object1" ,因为它是常数。ts(2588)
object1 = { property1: 1 };
// 编译错误:无法分配到 "array1" ,因为它是常数。ts(2588)
array1 = ["a", "b", "c"];

 虽然const关键字限定了栈上的内容不可编辑,但堆上的内容可以编辑,因此对于引用类型来说,要使堆上的内容不可编辑,需要额外使用readonly关键字

标签:console,log,array1,TS,object1,let,引用,类型
From: https://blog.csdn.net/weixin_45636198/article/details/139373060

相关文章

  • TS-类型转换(显式)
    1.将其他类型转换为布尔类型要将其他类型转换为布尔类型,只需要将待转换的值传入Boolean()函数varmsg:string="ok";varmsgToBollean:boolean=Boolean(msg);//得到trueBoolean()函数会判断传入的值是空值还是非空值。若表示非空值,则返回true若表示空值,则返回fals......
  • java中判断String类型为空和null的方法
    1.判断一个String类型的变量是否为空(即长度为0)或者为null在Java中,判断一个String类型的变量是否为空(即长度为0)或者为null,通常需要使用两个条件语句来进行检查。这是因为null表示变量没有引用任何对象,而空字符串("")表示变量引用了一个没有内容的字符串对象。下面是一个具体的代码......
  • free batches of packets in tcp_prune_ofo_queue()
      之前在做waf并发压力测试的时候,遇到一个问题,仪器测试正常,但是真实环境测试超时丢包的验证的时候,并发cps都很低。查看cat/proc/net/netstat发现OfoPruned对应值很大,看内核代码才发现,内存不够或rmem超过sk_rcvbuf,就会私房ofo队列,还是全部释放。当时将全部释放改为释放最高的5......
  • CF1961E Turtle and Intersected Segments 题解
    题目链接点击打开链接题目解法不是,我这咋不会做/fn边数很多的最小生成树有一个方法是\(boruvka\),但这个处理完全图的比较方便另一个方法是用到一个\(trick\):连出的图中的环,可以删去最长边扫描线是容易想到的,主要是如何把连的边数缩减到合理的范围内考虑扫描线到当前时刻......
  • ts 装饰器测试
    interfacemycbdInterface{alert(name:string):void,one?:string}//函数装饰器constmyconsole:MethodDecorator=(...rest)=>{console.log(rest,"rest")}//类装饰器constmylog2:ClassDecorator=(target)=>{console.log(target,......
  • PowerShell 来操作 Windows 防火墙,实现网络访问控制和防火墙规则的设置。下面是一些常
    PowerShell来操作Windows防火墙,实现网络访问控制和防火墙规则的设置。下面是一些常见的PowerShell命令,用于创建阻止特定类型文件传输协议的规则和限制电子邮件附件的规则:阻止FTP传输协议:powershellCopyCodeNew-NetFirewallRule-DisplayName"BlockFTP"-DirectionOu......
  • ref和reaction的区别(以及TS中ref,computed函数会自动推断定义其泛型(一般不用自己动手))
    其次就是了解ref,reactive的区别。ref通过对象名.value来访问对象里的值,若对象里还有属性则访问其需要:对象名.value.属性名reactive则通过:对象名.属性名,来直接访问属性值其次,两者都是响应式对象。但如果对直接对reactive对象进行赋值,那么其会丢失响应性。代码示例如下:<scri......
  • MySql 数据类型选择与优化
    选择优化的数据类型更小的通常更好一般情况下尽量使用可以正确存储数据的最小类型。更小的数据类型通常更快,因为它们占用更少的磁盘,内存和CPU缓存,并且处理时需要的CPU周期也更少。但也要确保没有低估需要存储值的范围。简单就好简单的数据类型通常需要更少的CPU周期。......
  • 儿童节变身小小音乐家,用ModelArts制作一张AIGC音乐专辑
    本文分享自华为云社区《儿童节变身小小音乐家,用ModelArts制作一张AIGC音乐专辑》,作者:华为云社区精选。儿童节,如何给小朋友准备一份特别的礼物?这份AIGC音乐专辑制作攻略一定要收下一段文字灵感就能编织出一曲悠扬悦耳的旋律童话、梦幻、探险……任何关键词都可以成为音乐......
  • 第2章 变量和简单数据类型
            在本章中,你将学习可在Python程序中使用的各种数据,还将学习如何将数据存储到变量中,以及如何在程序中使用这些变量。2.1运行hello_world.py时发生的情况        运行hello_world.py时,Python都做了些什么呢?下面来深入研究一下。实际上,即便是运行简单......