基本类型
(基本数值、基本数据类型)是一种既非对象也不是方法的数据,js中共有七种基本类型 String
Number
Bigint
Boolean
null
undefined
Symbol
所有基本类型的值都是 不可改变 的。基本类型的值可以被替换,但不能被改变。
当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行结束,这个方法的内存栈也将自然销毁了。因此,所有在方法中定义的变量都是放在栈内存中的;栈中存储的是基础变量以及一些对象的引用变量,基础类型的值是存储在栈中, 而引用变量存储在栈中是指向堆中的对象的地址
// 使用字符串方法不会改变一个字符串
var a = "hello";
console.log(a); // hello
a.toUpperCase();
console.log(a); // hello
// 赋值行为是给基本类型一个新值,是替换他而不是改变
a = a.toUpperCase(); // HELLO
除了 null
和 undefined
之外,所有的基本类型都有其对应的包装对象:
- String 为字符串基本类型
- Number 为数值基本类型
- BigInt 为大整数基本类型
- Boolean 为布尔基本类型
- Symbol 为字面量基本类型
这个包裹对象的valueOf()方法返回基本类型值。
引用类型
js中引用类型包括 Obejct
Array
Function
。
当我们创建一个对象时,由于对象的创建成本较高,对象会被保存到堆内存中以便反复利用。对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用,只有当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在核实的时候回收它。
基本类型与引用类型的区别
基本类型
- 占用空间固定,保存在栈中
- 保存与复制的是本身
- 使用typeof检测数据的类型
- 基本类型数据是值类型
引用类型
- 占用空间不固定,保存在堆中
- 保存与复制的是指对象的指针
- 使用instanceof检测数据类型
- 使用new()方法构造出的对象是引用型
复制变量值
从一个变量向另一个变量复制基本类型值,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上,此后这两个变量不会互相影响。
var a = 'hello'
var b = a
b = 'world'
console.log(a) // hello
console.log(b) // world
当从一个变量向另一个变量复制引用类型的值时, 同样也会将存储在变量对象中的值复制一份放到为新变量分配的空间中。 不同的是,这个值的副本实际上是一个指针,而这个指针指向存储在堆中的一个对象。复制操作结束后,两个变量实际上引用同一个对象。 因此,改变其中一个变量,就会影响另外一个变量
var a = {
b: 'hello'
}
var c = a
console.log(c.b) // hello
c.b = c.b.toUpperCase()
console.log(a.b) // HELLO
console.log(c.b) // HELLO
== 和 ===
对于引用类型的变量,==
和===
只会判断引用的地址是否相同,而不会判断对象具体里属性以及值是否相同。因此,如果两个变量指向相同的对象,则返回true
传递参数
按值传递
也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。
在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量(即命名参数,就是 arguments 对象中的一个元素)。
共享传递
在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反映在函数的外部。
function upper(a) {
a = a.toUpperCase()
return a;
}
var a = 'hello';
var b = upper(a);
console.log(a); // hello 没有变化
console.log(b); // HELLO
function setName(c) {
c.name = 'nizhja'
}
var d = {}
setName(d)
console.log(d.name) // nizhja
思考题
function change(person) {
person.age = 25;
person = {
name: "John",
age: 50
};
return person;
}
var personObj1 = {
name: "Alex",
age: 30
};
var personObj2 = change(personObj1);
console.log(personObj1); // -> ?
console.log(personObj2); // -> ?