一、JavaScript 数据类型大盘点
JavaScript 中的数据类型主要分为两大阵营,就像我们生活中 "基本生活用品" 和 "组合家具" 的区别:
1. 原始类型(基本类型)
这些是 JavaScript 中最基础的数据单元,就像搭建积木的最小块:
- string(字符串) :用单引号、双引号或反引号包裹的文本,比如
"你好"
、'hello'
或JavaScript
- number(数字) :包括整数和小数,例如
66
、3.1415
,特别的是,NaN
(不是数字)也属于 number 类型 - boolean(布尔值) :只有两个可能的值:
true
(真)和false
(假) - undefined(未定义) :变量声明了但没赋值时的状态,比如
let a;
此时a
就是 undefined - null(空值) :表示 "故意为空",通常用来主动清空变量的值
- symbol(符号) :ES6 新增,能创建独一无二的值,即使描述相同也不相等,比如
Symbol('id') !== Symbol('id')
- bigint(大整数) :处理极大的整数,在数字后面加
n
表示,比如9007199254740993n
,解决了普通数字的精度限制问题
2. 引用类型(复杂类型)
这些类型可以包含多个值,就像能装东西的容器:
- object(对象) :用键值对存储数据的集合,比如
{ name: "小明", age: 18 }
- array(数组) :按顺序排列的值的集合,比如
[1, 2, 3, "苹果"]
- function(函数) :可执行的代码块,比如
function add(a, b) { return a + b; }
- Date(日期对象) :专门处理时间的对象,比如
new Date()
能获取当前时间
二、JavaScript 语言的独特个性
JavaScript 是一种动态的、弱类型的脚本语言,这让它和其他语言有明显区别:
-
静态语言 vs 动态语言:
- 静态语言(如 C、Java)在写代码时就要规定变量的类型,比如
int age = 18;
,而且不能随便改类型 - 动态语言(如 JavaScript)不需要提前声明类型,变量的类型在运行时才确定,比如
let x = 10; x = "hello";
- 静态语言(如 C、Java)在写代码时就要规定变量的类型,比如
-
强类型 vs 弱类型:
- 强类型语言(如 Python)不允许不同类型随便运算,比如
"1" + 2
会报错 - 弱类型语言(如 JavaScript)支持隐式类型转换,比如
"1" + 2
会自动变成"12"
,"5" - 3
会变成2
- 强类型语言(如 Python)不允许不同类型随便运算,比如
三、内存空间:数据存哪里?
JavaScript 引擎(比如 V8)会管理三个主要的内存空间,就像我们家里的不同储物区域:
-
代码空间:存放要执行的代码,相当于书架,专门放说明书
-
栈空间:存放原始类型的值和引用类型的 "地址",特点是存取快,空间小,就像抽屉,放常用的小物件
-
堆空间:存放引用类型的实际数据,空间大,但存取稍慢,就像仓库,放体积大的东西
举个例子:let name = "张三"; let user = { age: 20 };
中,"张三"
存在栈里,而 { age: 20 }
存在堆里,栈里只存了指向这个堆数据的地址。

javascript
function foo(c) {
c.age = 20
c = {
name:'11'
}
return c
}
let p1 = {
name:'22',
age:33
}
let p2 = foo(p1)
console.log(p1); //{ name: '22', age: 20 }
console.log(p2); //{ name: '11' }

对象是 JavaScript 中最常用的数据结构,就像现实中的 "档案袋",可以装各种信息。
1. 创建对象的三种方式
ini
// 1. 字面量方式(最常用)
let obj1 = { name: "张三", age: 20 };
// 2. new Object() 方式
let obj2 = new Object();
obj2.name = "李四"; // 给对象添加属性
obj2.age = 22;
// 3. 构造函数方式(适合创建多个相似对象)
function Person(name, age) {
this.name = name; // this 指向新创建的对象
this.age = age;
}
// 用 new 关键字创建实例
let obj3 = new Person("王五", 25);
2. new 关键字的工作原理
当用 new
调用函数时,背后发生了一系列操作,就像工厂生产产品的流程:
- 先创建一个空对象(
{}
),相当于准备一个空盒子 - 把构造函数里的
this
指向这个新对象,相当于给盒子贴标签,说明 "这个盒子归它管" - 执行构造函数里的代码,给新对象添加属性和方法,相当于往盒子里装东西
- 让新对象的
__proto__
指向构造函数的prototype
(原型),相当于给盒子配一把钥匙,能打开公共仓库 - 返回这个新对象,相当于把装好的盒子送出来
五、原型与原型链:对象的 "继承" 机制
JavaScript 中的对象通过原型链实现继承,就像家族传承一样。
1. 原型系统的两个核心概念
- prototype(显式原型) :只有函数才有这个属性,它是一个对象,相当于 "公共仓库",里面的属性和方法可以被所有实例共享
- *proto(隐式原型) *:每个对象都有这个属性,它指向创建自己的构造函数的
prototype
,相当于每个对象都有一把钥匙,能打开对应的公共仓库
2. 原型链的查找规则
当访问对象的某个属性时,查找过程就像找家谱:
-
先在对象自身查找,如果找到就直接使用(比如找自己口袋里的东西)
-
如果没找到,就通过
__proto__
去它的原型对象里找(比如问爸爸要) -
还没找到就继续往上找,直到找到
Object.prototype
(比如问爷爷、太爷爷) -
如果最后到了
null
还没找到,就返回undefined
(比如追溯到祖宗十八代也没找到)
举个例子:
javascript
function Animal() {}
// 往原型里添加方法,所有实例都能用上
Animal.prototype.eat = function() {
console.log("吃东西");
};
let dog = new Animal();
dog.eat(); // 自身没 eat 方法,就去 Animal.prototype 里找,输出"吃东西"

六、特殊对象的创建
1. 完全没有原型的对象
通常对象都有原型,但我们可以创建一个 "无父无母" 的对象:
javascript
let obj = Object.create(null);
console.log(obj.__proto__); // undefined,它没有原型
这种对象不会继承任何东西,连 toString
这样的基本方法都没有。
2. 原型链的终点
所有对象的原型链最终都会指向 Object.prototype
,而 Object.prototype.__proto__
是 null
,就像所有家族最终都能追溯到一个源头。 如图:
七、如何判断数据类型?
1. typeof 运算符
简单快速,但有一些局限性:
csharp
typeof "hello"; // "string"(正确)
typeof 42; // "number"(正确)
typeof true; // "boolean"(正确)
typeof undefined; // "undefined"(正确)
typeof null; // "object"(历史遗留问题)
typeof Symbol(); // "symbol"(正确)
typeof BigInt(1); // "bigint"(正确)
typeof {}; // "object"(正确,但分不清是普通对象还是数组)
typeof []; // "object"(会把数组当成对象)
typeof function(){}; // "function"(正确)
2. instanceof 运算符
用于判断对象的具体类型,原理是检查构造函数的 prototype
是否在对象的原型链上:
javascript
[] instanceof Array; // true(数组是 Array 的实例)
{} instanceof Object; // true(对象是 Object 的实例)
function(){} instanceof Function; // true(函数是 Function 的实例)
但它不能判断原始类型,比如 "hello" instanceof String
会返回 false
。
3. Object.prototype.toString
这是判断类型的 "万能钥匙",能精准识别所有类型:
javascript
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call("hello"); // "[object String]"
Object.prototype.toString.call(123); // "[object Number]"
Object.prototype.toString.call([]); // "[object Array]"
Object.prototype.toString.call({}); // "[object Object]"
通过这些核心概念的学习,你已经掌握了 JavaScript 的基础骨架。这些知识是理解更复杂概念(如闭包、异步、面向对象编程)的前提,打好基础才能在 JavaScript 的世界里游刃有余。