重学JS–数据类型、声明和判断

这里使用《JavaScript高级程序设计第四版》和MDN来做参考。

数据类型

JavaScript 是一种弱类型或者说动态语言。在程序运行过程中,类型会被自动确定。这也意味着你可以使用同一个变量保存不同类型的数据。

let a = true;
a = 1;
a = 'string'
复制代码

红宝书的数据类型跟MDN不一致,考虑到书籍的时效性,使用MDN作为标准记录。

MDN–JavaScript 数据类型和数据结构

最新的 ECMAScript 标准定义了 9 种数据类型:

  • 6种原始类型:
    • undefiend typeof instance === "undefined"
    • Boolean typeof instance === "boolean"
    • Number typeof instance === "number"
    • String typeof instance === "string"
    • BigInt typeof instance === "bigint"
    • Symbol typeof instance === "symbol"
  • null typeof instance === "object" null被认为是空对象的指针,所以返回object
  • Object typeof instance === "object" 任何 constructed 对象实例的特殊非数据结构类型,也用做数据结构:new Object,new Array,new Map,new Set,new WeakMap,new WeakSet,new Date,和几乎所有通过 new keyword 创建的东西。
  • Funtion 非数据结构,尽管 typeof 操作的结果是:typeof instance === "function"。这个结果是为 Function 的一个特殊缩写,尽管每个 Function 构造器都由 Object 构造器派生。

typeof操作符返回的值可能并不是我们想要的,有Object派生出来的结构类型可以使用instanceof操作符来判断、Array.isArray()、isNaN()等也提供了准确的判断。

类型补充说明

Number:

根据 ECMAScript 标准,JavaScript 中只有一种数字类型:基于 IEEE 754 标准的双精度 64 位二进制格式的值(-(2^53 -1) 到 2^53 -1)。除了一般的number类型以外,+Infinity,-Infinity 和 NaN也被认为是number。在 ECMAScript 6 中,你也可以通过 Number.isSafeInteger() 方法还有 Number.MAX_SAFE_INTEGERNumber.MIN_SAFE_INTEGER 来检查值是否在双精度浮点数的取值范围内。 超出这个范围,JavaScript 中的数字不再安全了,也就是只有 second mathematical interger 可以在 JavaScript 数字类型中正确表现。

浮点数的内存空间是整数的两倍,所以ECMAScript总是会想方设法的把浮点数转成整数: let a = 1.0会被当成整数处理。

浮点数的计算可能不准确。0.1 + 0.2 !== 0.3

NaN: NaN == NaNNaN === NaN得到的都是false,我们通常用isNaN()来判断。
isNaN(xx)会尝试把xx转换为Number类型,如果不能成功,则会返回true。

  • isNaN(window) => true
  • isNaN(true) => falsetrue会被转换成Number类型的1,false则转成0
  • isNaN('10') => false
  • isNaN('abc') => true
  • isNaN(10) => false
  • isNaN(undefiend) => true

BigInt

BigInt是通过在整数末尾附加 n 或调用构造函数来创建的。

const x = 2n ** 53n;
9007199254740992n
const y = x + 1n;
9007199254740993n
复制代码

Boolean

我们通常会使用if语句来做条件判断,为了简写,if的条件通常都不会是Boolean类型的:

const a = {};
const b = 1;
const c = 'asfa';
if(a && b && c) ...
复制代码

如果if中的条件不是Boolean的话,会使用Boolean()转成Boolean类型。这里是一部分转换关系:

数据类型 结果true 结果false
Boolean true false
String 非空字符串 空字符串
Number 非0数值 0
Object 任意对象和对象的延展数据结构 null
undefiend undefiend

类型声明

声明操作符有三种:var、let、const。也可以不适用操作符直接写。

不使用操作符

gg = 1
默认创建全局变量,不建议使用

var

旧时代的产物,但任然需要了解,可能再过10年依然有人在维护var的代码。

存在变量提升,作用域会穿透if,for,switch等语句块。不建议再使用。

let

声明的变量存在块级作用域,同一作用域无法再次声明。无法再次声明var过的变量。

需要注意的是,使用let声明变量,类似于一个IIFE的效果:

// 全局作用域下
let a = 1
var b = 1
window.a === undefined
window.b === 1
// 使用let类似于
(function(){
  var a = 1;
})();


// 关于块级作用域比较常见的问题
for(var i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log(i); // 5个5
  }, 0)
}

for(let i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log(i); // 01234
  }, 0)
}
复制代码

const

跟let表现一致,多了一条:变量指向的内存地址无法被修改。如果是Object类型,只要不修改内存地址,可以做其他修改操作。

const a = 1;
a = 2; // VM6330:1 Uncaught TypeError: Assignment to constant variable.
a = '1'; // VM6330:1 Uncaught TypeError: Assignment to constant variable.

const b = [];
a.push(1); // 正常执行

const c = {name: 1};
c.name = 2; // 正常执行
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享