JavaScript数据类型
JavaScript数据类型分两大类,基本类型(或者称原始类型)和引用类型。
基本类型的值是保存在栈内存中的简单数据段,它们是按值访问的。js中有五种基本类型:Undefined、Null、Boolean、Number和String。
引用类型的值是保存在堆内存中的对象,它的值是按引用访问的。引用类型主要有Object、Array、Function。
对象是拥有属性和方法的,Array是引用类型,所以它自然可以拥有属性(length)和方法(push)等。而在如下代码中
const str="Hello world";
const sub=str.substring(2,5);
console.log(sub); //"llo"
str是string基本类型的变量,为什么它可以拥有方法呢?
这是因为有个叫“包装类型”的东西。这些包装类型允许你在基本类型上调用对象方法,因为JavaScript 在需要时会自动将基本类型转换为相应的包装类型。这被称为“自动包装”。
包装类型
在 JavaScript 中,包装类型是指基本数据类型(如字符串、数字、布尔值)的对应对象类型。这允许我们在基本类型上调用对象的方法和访问属性,在调用基本类型的属性或方法时 JavaScript 会在后台隐式地将基本类型的值转换为对象。
JavaScript中有三种主要包装类型。String 包装类型:用于字符串基本类型的操作。Number 包装类型:用于数字基本类型的操作。Boolean 包装类型:用于布尔值基本类型的操作。
通常情况下,JavaScript会在需要时自动创建和销毁这些包装对象,以便我们直接操作基本数据类型,而不需要显式创建包装对象。
字符串字面量能够直接调用原型链上的函数的原因
在执行str.substring(2,5) 这行代码时,发生了很多事。
首先,它会从内存中读取str的值;然后创建String类型的一个实例;再在实例上调用指定的方法;最后销毁这个实例。
上面的例子可以用这样的代码来说明:
const _str=new String("Hello world");
const sub=_str.substring(2,5);
_str=null; //方法调用后即销毁
这样我们就明白了,并不是基本类型string执行了自身方法,而是后台为它创建了一个对应的基本包装类型String,它根据基本类型的值实例化出了一个实例,让这个实例去调用指定方法,最后销毁自己。
注意最后一步基本包装类型“会销毁”的特性,这决定了我们不能为基本类型值添加自定义属性和方法。
let name="Kris";
name.age=18;
console.log(name.age);//undefined
给“name“这个字符串添加了age属性,值设为18,然再次访问时,这个属性不存在。这是因为执行到第二行代码属性赋值时,后台创建了一个基本包装类型的实例,这个age属性确实挂到实例上去了,但是紧跟着,这个实例就被销毁了。执行到第三行时,又重新创建了新的基本包装类型的实例,自然是没有age属性的。
这就是基本包装类型的作用了。本来你是没有方法的,但是你想用方法的时候,你尽管调,对应的基本包装类型有这个方法就行。例如上面的substring方法,string这个基本类型是不可能有这个方法的,但是String这个包装类型有,它会把这个方法执行完把结果返回。
除了在字符串处于读取模式下,后台会帮我们创建包装类型实例,我们自己也可以显示地创建。
let str=new String("hello");
let str2=str.toUpperCase();
console.log(str2);//"HELLO:
在String对象的原型链上有一系列的函数,例如substring()、split()、slice(),可以通过String对象的实例调用这些函数来处理字符串。采用字面量方式定义的字符串在访问这些函数时,后台将字符串包装成String的实例对象访问对应的函数。说明采用字面量方式定义的字符串也能直接调用原型链上的函数。
总结:包装类型是为了让基本类型也能够调用对象的方法和属性。当在基本类型上调用一个方法时,JavaScript 会临时将基本类型转换为对应的包装类型来执行操作,然后将结果返回。