JavaScript 补全计划 【1】JS中的数据类型

发布于:2022-12-06 ⋅ 阅读:(755) ⋅ 点赞:(0)

目录

1 基本类型

Number

String

Undefined

Null

Boolean

Symbol

2 引用类型(复杂类型)

Object

Array

Function

3 变量在哪儿呢?

基本数据类型

引用数据类型 

小结


学习新语言的第一步就是明白一个语言中的数据类型。作为一门解释型语言,JS声明变量的方式很简单,你只需要在你想使用变量的时候说出他的名字,JS就会为你自动开辟一个内存空间,存放你的变量,就像这样:

var a; // 很少使用
let b; // 通过 let 声明一个变量

// 你突发奇想, 告诉浏览器: 我要一个变量,这个值不准改变
// 浏览器: 收到, 那你使用 const 告诉我那些变量不允许改变

const c; // 使用 const 声明一个常量

很简单吧(事实上这种简单会带来一些类型转换上的问题,后面会提到)。

相比其它一些强类型语言还还需要注明变量类型,JS似乎显得更加聪明一些(浏览器:你只管告诉我里面放什么东西,其他的交给我!),但这是基于对语言灵活性的需求在浏览器这个运行环境中做出的一种综合性考量。

进入正题:虽然在JS中声明变量是不需要声明变量类型,但JS在处理各种各样变量的过程中,依旧会对这些变量进行分类以便于管理,其中主要包含以下两大类的变量类型:

  • 基本类型
  • 引用类型(也叫作复杂类型)

1 基本类型

Number

let decNum = 10
let hexNum = 0xA //16进制的10

let floatNum1 = 1.1;
let floatNum2 = 1.123e7; // 等于 11230000

console.log(0 / 0); // NaN 指代无法被转换成数字的值

相比于其他语言,JS会把数字类型作为一类数据进行统一管理,其中 NaN 意为不能被转换为数字的数值。

String

可以通过双引号、单引号、反引号创建字符串变量。

let name1 = "John";
let name2 = 'Jason';
let name3  = `Jack`;

Undefined

Undefined 从字面意义理解即变量被声明了,但未被定义,可以从下面这个例子理解。

let var1;

console.log(var1); // "undefined"
console.log(var2); // 报错 ReferenceError: a is not defined

对于之前只有强类型语言学习经验的人来说这个类型可能看起来有些奇怪,不过我们可以按照这种思路进行理解。

Undefined var1 = undefined;

var1 = 1; // 此时 Undefined 就变成了 Number, 而 undefined 变成了 1

我们声明了一个 Undefined 类型的变量 var1,这种类型的变量只有一个值,那就是 undefined。

Null

这个类型和上面提到的 Undefined 相似,但和其不一样的是,Null 在JS中代表一个本该指向一个实例对象的空指针,这个指针指向一个空对象,类型为 Null。只要变量要保存对象,而当时又没有那个对象可保存,就可用来填充该变量。

let obj = null;
console.log(typeof obj); // "object"

Boolean

let flag1 = true;
let flag2 = false;

Boolean 值有两个,true 和 false,可以根据以下规则进行类型转换。

类型 转换为True 转换为False
String 非空字符串 ""
Number 所有非零数字 0和NaN
Object 所有非空对象 null
undefined / undefined

Symbol

Symbol (符号)是原始值,且符号实例是唯一、不可变的。

let symbol1 = Symbol('sth');
let symbol2 = Symbol('sth');
console.log(Symbol1 == Symbol2 ); // false

2 引用类型(复杂类型)

终于到引用类型了!

想必大家都听过JS中的 “万物皆对象” 这句话,不得不说这句话也是有些年头了。来吧。

引用类型主要介绍这几种:

  • Object
  • Array
  • Function

Object

为了不把这一章节变得过于臃肿,这里只介绍最常见的创建对象的方式——通过字面量创建。

let person = {
    name: '京都心转手',
    age: '25',
    'key': '字符串也可', // 键名可以是字符串
    1: '数字也行?'  // 键名可以是数值
}

person.name // '京都心转手'
person['name'] // '京都心转手'

person['key'] // '字符串也可'
person.key // '字符串也可'

person[1] // '数字也行?'
person.1 // Error 报错! 这样可不行

Array

let desk = ["cup", "plate"] // 桌子上好多东西啊
let box = ["stuff"] // 好大一个箱子
let kid = {
    name: "kid"
}

desk.push(box) // 放到桌子上
desk.push(kid) // 孩子爬到了桌子上

console.log(desk) // ["cup", "plate", ["stuff"], { name: "kid" }]

desk.length = 0; // 桌子倒了
console.log(desk) // [] 什么都没了

我们可以看到,在JS中数组不需要指明内部的数据类型,可以随意的添加内容,数组的 length 也会随之自动扩充。并且我们可以通过将长度置为0来轻易地清空数组。

Function

函数实际上是对象,Function 也有属性和方法,跟其他引用类型一样。函数存在下面几种常见的表达方式:

const foo1 = function(){
    // Todo..
}

function foo2(){
    // Todo..
}

const foo1 = () => {
    // Todo..
}

3 变量在哪儿呢?

基本数据类型

基本数据类型和引用类型的存储在内存中有很大的差别,尤其在赋值操作的过程中会出现不同的行为。这也涉及到了另一个问题,JS中变量是按引用传递吗?还是按值传递呢?

我们先来了解一下基本数据类型的存储过程。

let a = 1;
let b = a;
b = 2;
console.log(a); // 1
console.log(b); // 2

引用数据类型 

a 的值为一个基本类型,是存储在栈中,将 a 的值赋给 b,虽然两个变量的值相等,但是两个变量保存了两个不同的内存地址

let obj = { name: '京都心转手' }

let obj2 = obj; // 我们用 obj 初始化 obj2

// obj 和 obj2 是怎么存储的?

obj2.name = "重庆心转手"; // 修改 obj2 的名字

// obj 和 obj2 值会发生什么变化呢?

obj2 = { name: '深圳心转手' } // 重新赋值

// 现在呢?

1、代码第一行,根据声明,在堆内存中地址为 0001 的位置开辟了一块空间,用于存储 obj 对象。包含一个属性 name。  

2、代码第二行,使用 obj 的值初始化 obj2 对象,我们可以看到本质是是将 obj 指向的地址值,赋值给了 obj2 作为初始值。

 3、代码第三行,我们改变了 obj2 指向地址 0001 中对象的属性,所以我们此时打印会发现两个对象的 name 属性都会发生变化

let obj = { name: '京都心转手' }
let obj2 = obj; 
obj2.name = "重庆心转手"; 

console.log(obj.name); // '重庆心转手'
console.log(obj2.name); // '重庆心转手'

此时内存中的数据变化如图所示:

 3、代码第四行,我们使 obj2 指向另一个新的对象空间,下图演示这个引用类型赋值过程

小结

  • 简单类型的值存放在栈中,在栈中存放的是对应的值
  • 引用类型对应的值存储在堆中,在栈中存放的是指向堆内存的地址

网站公告

今日签到

点亮在社区的每一天
去签到