JavaScript 的数据类型
原文地址
javascript 的数据类型有:
- undefined
- null
- boolean
- string
- Symbol
- number
- object
前 6 种属于根底类型,根底类型
的数据在被援用或拷贝时是值传递的,也就是说会创立一个齐全相等的变量;object 属于 援用类型
,援用类型只是在栈中创立一个指针指向堆内存中原有的变量,实际上两个变量是”共享“这个数据的,并没有从新创立一个新的数据。
这里捡重要的讲一下:
undefined
undefined 类型数据只有一个值:undefined
以下这些形式能够失去 undefined 值:
- 援用已申明但未初始化的变量
- 援用未定义的对象属性
- 执行无返回值函数
- 执行 void 表达式
- 全局常量 window.undefined 或 undefined
其中举荐用 void 0 来示意 undefined,这样不仅能够少用一个变量或者对象的属性,而且 void 0 是一个表达式,能够用于三目运算符中:
let x = 10;
x > 1 ? fn() : void 0;
判断一个值是否是 undefined
// 1 这个办法不精确,x 可能是一个 falthy 的值
if (!x) {//}
// 2 这个办法是精确的,然而最好先查看 x 是否曾经申明
if (x === undefined) {
}
// 3 这个办法也是精确的,同样的也要查看 x 是否申明,否则会呈现 refrenceError
if (typeof x === "undefined") {}
null
null 类型的值只有一个: null
null 和 undefined 都能够示意空值,当应用”==“的时候,它们是相等的,然而 null 是 js 的 保留关键字
,而 undefined 只是一个常量。
number
- NaN(Not a Number) 通常在计算失败的时候会失去该值,要判断一个变量是否为 NaN,能够通过 Number.isNaN 函数来判断。
- Infinity 是无穷大,加上负号”-“会变成无穷小,在某些场景下比拟有用。比方通过数值来示意权重或者优先级,Infinity 能够示意最高优先级或最大权重。
// 将 10 进制转换成其余进制的数,能够用 toString()
(10).toString(2); // '1010'
// 精度问题
0.1 + 0.2; // 0.30000000000000004
// 解决精度问题
parseFloat((0.1 + 0.2).toPrecision(12));
Symbol
Symbol 是 ES6 中引入的新数据类型,示意一个惟一的常量
理论举例:
防止常量笼罩
const KEY = {
baidu: "A",
alibaba: "B",
// ...
};
function getValue(type) {switch (type) {
case KEY.baidu:
// ...
case KEY.alibaba:
// ...
}
}
// 这里定义常量 KEY 属性的值的时候,容易造成值的反复,比方
const KEY = {
baidu: "A",
alibaba: "B",
// ...
bilibili: "B",
};
// 如果用 Symbol 作为属性值,就不会呈现反复的景象
const KEY = {baidu: Symbol(),
alibaba: Symbol(),
// ...
bilibili: Symbol(),};
// 这里咱们只关怀键的类型,而不关怀属性的值
防止对象属性笼罩
let o = {user: { name: "tom"},
// ...
};
// 这里的 o 对象,有很多属性,咱们想再往 o 上增加属性时,为了不笼罩它原有的属性,能够用 Symbol 失去一个键值
const s = Symbol();
o[s] = 1234;
// 获取这个 Symbol 属性的值
o[s]; // 1234
Object
简略的说,Object 类型数据就是 键值对的汇合
,键是一个字符串(或者 Symbol),值能够是任意类型的值。
简单的说,Object 又包含很多子类型,比方 Date,Array,Set,RegExp…
对象的拷贝
因为援用类型在赋值时只传递指针,这种拷贝形式称为 浅拷贝
而创立一个新的与之雷同的援用类型数据的过程称之为 深拷贝
。
[undefined, null, true, 0, "", Symbol(), {}].map((it) => typeof it);
// => ["undefined", "object", "boolean", "number", "string", "symbol", "object"];
const clone = (obj) => {
// 这里援用 es6 中的 weakMap 是为了避免循环援用
let map = new WeakMap();
function deep(data) {if (typeof data !== "object") {return data;}
let result = {};
const keys = [...Object.getOwnPropertyNames(data),
...Object.getOwnPropertySymbols(data),
];
const exist = map.get(data);
if (exist) {return result;}
map.set(data, result);
for (const key of keys) {if (data[key] && typeof data[key] === "object") {result[key] = clone(data[key]);
}
result[key] = data[key];
}
return result;
}
return deep(obj);
};
const o1 = {name: "tom"};
const o2 = clone(o1);
console.log(o2); // {name: "tom"}
console.log(o1 === o2); // false