数据类型
JavaScript中的数据类型主要分为原始类型和引用类型。原始类型的值直接存在调用栈中,而引用类型的值存在堆中,而调用栈中存放的仅是堆中的引用地址。
按正常逻辑说我先把a赋给了b,再去修改了a中的age,打印b.age应该得到18。但是得到的却是20,是因为它们都是通过同一个地址找到的age,age的存放地址是不变的。
原始类型
原始类型包括:
- String(字符串)
- Number(数字)
- Boolean(布尔值)
- Null(空值)
- Undefined(未定义)
- Symbol(符号,ES6新增)
原始类型的特点是它们是不可变的,即一旦创建,就不能被修改。
引用类型
引用类型包括:
- Object(对象)
- Array(数组)
- Function(函数)
- Date(日期)
- RegExp(正则表达式)
- 等其他自定义对象
引用类型的值是对象,存储在堆中,而在调用栈中存放的只是堆中的引用地址。这意味着引用类型的赋值实际上是复制了引用,而非对象本身。
对象
对象是JavaScript中的一种引用类型,用于存储和组织数据。对象可以通过多种方式创建。
创建对象
-
对象字面量
let person = { name: 'John', age: 30, isStudent: false }; -
new Object()
let person = new Object(); person.name = 'John'; person.age = 30; person.isStudent = false; -
自定义构造函数
function Person(name, age, isStudent) { this.name = name; this.age = age; this.isStudent = isStudent; } let person = new Person('John', 30, false);
构造函数
构造函数是一种特殊的函数,用于创建对象。它是一种工厂,可以批量生成具有相似属性和方法的对象。
new的过程
使用new关键字调用构造函数的过程包括:
-
创建this空对象
function Person(name, age) { this.name = name; this.age = age; } let person = new Person('John', 30); // 在这个过程中,JavaScript会创建一个空对象,并将其赋给this -
执行构造函数中的逻辑
function Person(name, age) { this.name = name; this.age = age; this.sayHello = function() { console.log(`Hello, my name is ${this.name}`); }; } let person = new Person('John', 30); // 在这一步,构造函数中的逻辑被执行,为对象添加属性和方法 -
返回this对象
function Person(name, age) { this.name = name; this.age = age; this.sayHello = function() { console.log(`Hello, my name is ${this.name}`); }; } let person = new Person('John', 30); // 最终,构造函数返回创建的对象(this对象)
不难理解,构造函数得到的实例化对象之间是相互独立的。例如
function Car(color){
this.name = 'BMW'
this.height = 1400
this.lang = 4900
this.weight = 1000
this.color = color
}
let car = new Car('green') //实例对象 == this
let car2 = new Car('red')
car.name = '幻影'
打印car得到
打印car2得到
包装类
包装类是原始类型和对象之间的一种桥梁。原始值是不能具有属性和方法的,属性和方法是对象独有的。为了在原始类型上调用方法,JavaScript会临时将原始值转换为对应的包装类对象。
var num = 123
num.a = 'hello'
console.log(num.a); //undefined
//因为原始类型是不能具有属性的
在js的v8引擎中,以上代码会被这样执行。这就是为什么得到undefined。
var num = new Number(123)
num.a = 'hello'
delete num.a
console.log(num.a);
考点:
var arr = [1,2,3,4]
arr.length = 2
console.log(arr);//并不会得到[1,2]
console,log(arr.length)//4
为什么下面的打印会得到4呢?不是不能有属性吗?
因为这里的length是官方内置的属性,它就是可以读到数组的长度。
需要注意的是,包装类对象是临时创建的,对原始值的修改并不会影响原始值本身。
深入理解JavaScript的数据类型和对象创建过程,对于编写高效且可维护的代码是至关重要的。通过合理地使用原始类型和引用类型,以及灵活运用构造函数和对象字面量,可以更好地组织和管理代码。