变量和类型
Javascript规定了几种语言类型
| 基本类型 | 引用类型 | |
|---|---|---|
| 类型 | String, Number, Boolean, Undefined, Null, Symbol | Object |
| 访问 | 按值访问 | 按引用访问 |
| 存储 | 栈内存(Stack) | 保存在堆内存(Heap)中的对象 |
| 图解 |
Javascript对象底层数据结构是什么
typeof null 为"Object"的原因,Javascript的底层数据是以二进制存储的。而null所以存储的值都是0,而判断Object的逻辑是以前三个0来判定,所以才会有typeof null 为"Object"这个bug 基本包装类型:String, Number, Boolean,自动创建的基本包装类型对象,非String, Number, Boolean内置函数new出来的
| 类型 | 底层存储方式 |
|---|---|
| 数组 | 是一种聚合数据类型,将相同类型若干变量有序的组织在一起的集合,一个数组可以可以分解为多个数组元素。按照数据元素的类型,数组可以分为整型数组、字符型数组、浮点型数组、指针数组和结构数组等。数组还可以有一维、二维以及多维等表现形式。 |
| 栈 | 栈是一种特殊的线性表,它只能在一个表的一个固定端进行数据结点的插入和删除操作。栈按照后进先出的原则来存储数据,也就是说,先插入的数据将被压入栈底,最后插入的数据在栈顶,读出数据时,从栈顶开始逐个读出。栈在汇编语言程序中,经常用于重要数据的现场保护。栈中没有数据时,称为空栈。 |
| 队列 | 队列和栈类似,也是一种特殊的线性表。和栈不同的是,队列只允许在表的一端进行插入操作,而在另一端进行删除操作。一般来说,进行插入操作的一端称为队尾,进行删除操作的一端称为队头。队列中没有元素时,称为空队列 |
| 链表 | 链表是一种数据元素按照链式存储结构进行存储的数据结构,这种存储结构具有在物理上存在非连续的特点。链表由一系列数据结点构成,每个数据结点包括数据域和指针域两部分。其中,指针域保存了数据结构中下一个元素存放的地址。链表结构中数据元素的逻辑顺序是通过链表中的指针链接次序来实现的。 |
JavaScript基本类型数据都是直接按值存储在栈中的(Undefined、Null、不是new出来的布尔、数字和字符串),每种类型的数据占用的内存空间的大小是确定的,并由系统自动分配和自动释放。这样带来的好处就是,内存可以及时得到回收,相对于堆来说 ,更加容易管理内存空间。
JavaScript引用类型数据被存储于堆中 (如对象、数组、函数等,它们是通过拷贝和new出来的)。其实,说存储于堆中,也不太准确,因为,引用类型的数据的地址指针是存储于栈中的,当我们想要访问引用类型的值的时候,需要先从栈中获得对象的地址指针,然后,在通过地址指针找到堆中的所需要的数据。
Symbol 类型在实际开发中的应用,手动实现一个简单的Symbol
- Symbol是一种基本类型,由Symbol函数生成。
// Symbol不能new,会报错,返回一个值,不是对象
// 没有参数的情形
const sy1 = Symbol();
const sy2 = Symbol();
sy1 === sy2; // false
// 有参数的情形
const sy1 = Symbol("foo");
const sy2 = Symbol("foo");
sy1 === sy2; // false
// 使用同一个 Symbol 值,可以使用 Symbol.for
const sy1 = Symbol.for("foo");
const sy2 = Symbol.for("foo");
sy1 === sy2; // true
// instanceof 的结果为false
const sy = Symbol("foo");
sy instanceof Symbol
- Symbol 值可以作为标识符,用于对象的属性名,可以保证不会出现同名的属性。
const mySymbol = Symbol();
// First
const obj = {};
obj[mySybol] = "Hello World!!";
// Second
const obj = {
[mySymbol]: "Hello World!!"
};
// Third
const obj = {};
Object.defineProperty(obj, mySymbol, {value: "Hello World!!"});
- 该属性不会出现在 for…in、for…of 循环中,也不会被 Object.keys()、Object.getOwnPropertyNames()、JSON.stringify() 返回
- 使用 当需要区分形状,正方形,圆形,菱形 会使用 const shape = { triangle: 'triangle', circle: 'circle'},不优雅,可以使用 const shape = { triangle: Symbol(), circle: Symbol()};
- 手动实现简单的Symbol
// 要求:
// sym('key') 创建一个新的值
// sym.for('key') 检测创建的话取值,未创建新建值
// sym.keyFor(value) 取sym值对应的key
// new sym() 报错,Uncaught TypeError: sym is not a constructor
const sym = (() => {
const cache = new Map();
function fn(key) {
if (this instanceof fn) {
throw TypeError('sym is not a constructor');
}
return {};
}
fn.for = function(key) {
if (!cache.has(key)) {
cache.set(key, {});
}
return cache.get(key);
}
return fn;
})();
new sym();
Uncaught TypeError: sym is not a constructor
at new fn (<anonymous>:6:19)
at <anonymous>:1:1
const name1 = sym('name');
const name2 = sym('name');
name1 === name2; // false
var name3 = sym.for('name');
var name4 = sym.for('name');
name3 === name4; // true