前言
在程序设计的类型系统中,数据类型(英语:Data type),又称数据型态、数据型别,是用来约束数据的解释。
数据类型描述了数值的表示法、解释和结构,并以算法操作,或是对象在存储器中的存储区,或者其它存储设备。
高级语言中设计数据类型可以具有如下优点。
- 方便管理计算机的内存空间,提高运行时效率;
- 帮助构建抽象数据类型和模块化;
- 构建语言的语义模型。
数据类型背后隐藏的是编译器或者解释器对数据处理方式的定义。
当我们真正掌握数据类型后,我们清楚的知道某种数据类型可以进行哪些操作,这些操作的规则又是什么,从而提高我们的编码效率。
JS 里的数据类型
JavaScript 中的变量分为基本类型和引用类型。一共有八种,分别是:
- Undefined
- Null
- Boolean
- String
- Number
- Symbol
- BigInt (新增)
- Object (引用数据类型)
前七种是基本数据类型,最后一种是引用数据类型。
undefined
JavaScript 中下述情况下结果为 undefined
- 声明一个变量未赋值;
- 访问某个对象不存在的属性;
- 没有返回值的函数或者
return;的函数
// 1.
const num;
console.log(num); // undefined
// 2.
const book = {};
console.log(book.title); // undefined
// 3.
const foo = () => {};
console.log(foo()); // undefined
undefined 值没有任何属性、没有任何方法。访问 undefined 值的任何属性和方法,都会报错。
const val = undefined;
console.log(val.title); // Cannot read property 'title' of undefined
console.log(val.toString()); // Cannot read property 'toString' of undefined
undefined 一般认为是属于系统层面的、报错层面的信息缺失。
null
null 表示的是一个明确的已经知道的值,是一个空对象。null 代表有存储信息的容器 (比如之前被赋过值的变量),但该容器中的内容为空。
const obj = null;
null 值没有任何属性、没有任何方法。访问 null 值的任何属性和方法,都会报错。
const val = null;
console.log(val.title); // TypeError: Cannot read property 'title' of null
console.log(val.toString()); // Cannot read property 'toString' of null
null 一般认为是属于编程层面的、逻辑操作层面的信息值为空。
String、Number 和 Boolean
在 JS 中,String、Number 和 Boolean 分别是 string、number boolean 值对应的引用类型。
包装类型,是一个专门封装原始类型的值,并提供对原始类型的值执行操作的 API 对象。
普通的内置对象与基本包装类型的主要区别就是对象的生命期,使用 new 操作符创建的引用类型的实例,
在执行流离开当前作用域之前都一直保存在内存中,而自动创建的基本包装类型的对象,则只是存在于一
行代码的执行瞬间,然后立即被立即销毁。这意味着我们不能再运行时为基本包装类型值添加属性和方法。
基本包装对象类型在运行时不能添加属性和方法,以 String 包装对象举例子说明如下:
var str = "some text";
str.color = "red";
console.log(str.color); //undefined
普通对象类型在运行时可以添加属性和方法,如下:
const book = {};
book.title = "JavaScript 高级程序设计";
book.showTitle = function () {
return this.title;
};
console.log(book.title); //'JavaScript 高级程序设计'
console.log(book.showTitle()); //'JavaScript 高级程序设计'
string 类型的值有 3 类,分别是单引号、双引号和模板字符串。
console.log("foo"); // 'foo';
console.log("foo"); // 'foo';
es6 新增了模板字符串,用反引号表示。模板字符串使用反引号 (``) 来代替普通字符串中的 用双引号和单引号。模板字符串可以包含特定语法(${expression})的占位符。
const name = "qinghuanI";
console.log(`Hi ${name}`); // 'Hi qinghuanI'
number 类型的值有 5 类, 分别是整型、浮点型、NaN、Infinity、 -Infinity。
console.log(2); // 2 整型
console.log(2.33); // 2.33 浮点型
console.log(Number("aaa")); // NaN 不是一个数
console.log(1 / 0); // Infinity
console.log(1 / -0); // -Infinity
boolean 类型的值有两个, 分别是 true 和 false。
const bool = true || false;
Symbol
Symbol 是一种基本数据类型。每个从 Symbol() 返回的 symbol 值都是唯一的。
const s1 = Symbol();
const s2 = Symbol();
console.log(s1 === s2); // false
一个 symbol 值能作为对象属性的标识符。来看下面的例子。
const name = Symbol();
const person = { [name]: "qinghuanI" };
console.log(person[name]); // 'qinghuanI'
BigInt
BigInt 是新增的基本数据类型。它提供了一种方法来表示大于 25³ - 1 的整数。这原本是 Javascript 中可以用 Number 表示的最大数字。BigInt 可以表示任意大的整数。
console.log(typeof BigInt(1)); // 'bigint'
Object
JS 中最重要同时也是最复杂的类型是 Object 类型。
JavaScript 中的所有对象都来自 Object,所有对象从 Object.prototype 继承方法和属性。 我们常用的 Array、Set、Map、Date 等等内置对象均继承 Object 基对象。
console.log(Array instanceof Object); // true
console.log(Set instanceof Object); // true
console.log(Map instanceof Object); // true
console.log(Date instanceof Object); // true
但是,Array、Set、Map、Date 等等内置对象会重写 Object 的 constructor 属性和 toString() 方法。看看 Array 的例子。
console.log(Object.toString()); // function Object() { native code }
console.log(Array.toString()); // function Array() { native code }
console.log({}.toString()); // "[object Object]"
console.log([].toString()); // ""
如果想了解对象更底层的实现,请阅读《从 Chrome 源码看 JS Object 的实现》。
Object 类型是一个包含键/值对的集合。ECMAScript 提供了两种创建创建对象的方式:构造函数创建和字面量创建。
构造函数创建是指使用 new Object()的方式创建,而字面量创建是指使用{}创建。
// 构造函数创建
const obj = new Object();
// 对象字面量 推荐使用该方式
const obj = {};
使用对象字面量创建对象比使用构造函数创建对象更简洁,所以推荐使用对象字面量方式创建对象。
ECMAScript 还为对象提供了更精细的控制。对象的属性分为数据属性和访问器属性, 就是属性的属性,用来描述属性的行为特性。
数据属性
数据属性包含一个数据值的位置。在这个位置可以读取和写入值。
[[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性, 或者能否把属性修改为访问器属性。默认值为true[[Enumerable]]:表示能否通过for-in循环返回属性值。默认值为true。[[Writable]]:表示能否修改属性的值。默认为true。[[Value]]:包含这个属性的属性值。读取属性值的时候,从这个位置读;写入属性值的时候,把 新值保存在这个位置。默认值为undefined。
我们通过一个例子,将对象的某个属性设置为不可以修改。
const book = {};
Object.defineProperty(book, "title", {
writable: false,
value: "JavaScript 高级程序设计",
});
book.title = "JavaScript 权威指南";
console.log(book.title); // 'JavaScript 高级程序设计'
访问器属性
[[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性, 或者能否把属性修改为访问器属性。默认值为true[[Enumerable]]:表示能否通过for-in循环返回属性值。默认值为true。[[Get]]:在读取属性时调用的函数。默认为undefined。[[Set]]:在写入属性时调用的函数。默认值为undefined。
var dog = {
_age: 2,
weight: 10,
};
Object.defineProperty(dog, "age", {
get: function () {
return this._age;
},
set: function (newVal) {
this._age = newVal;
this.weight += 2;
},
});
dog.age = 3;
console.log(dog); // {_age: 3, weight: 12}
我们声明一个对象时,默认为访问器属性。