JavaScript的数据类型
八种数据类型
- Undefined ,ES5;
- Null ,ES5;
- Boolean ,ES5;
- Number ,ES5;
- String ,ES5;
- Object ,ES5;
- Symbol ,代表创建后独一无二且不可变的数据类型,它主要是为了解决可能出现的全局变量冲突的问题;ES6
- BigInt , 是一种数字类型的数据,它可以表示任意精度格式的整数,使用 BigInt 可以安全地存储和操作大整数,即使这个数已经超出了Number 能够表示的安全整数范围;ES10
这些数据可以分为原始数据类型和引用数据类型:
栈:原始数据类型(基本类型) -Undefined、Null、Boolean、Number、String;
堆:引用数据类型(对象类型)-对象(Object)、数组(Array)、函数(Function) ,还有两个特殊的对象:正则(RegExp)和日期(Date);
两种类型的区别
存储位置的不同:
- 原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;
- 引用数据类型 存储在堆(heap)中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。
在数据结构中:
- 栈中数据的存取方式为先进后出;
- 堆是一个优先队列,是按优先级来进行排序的,优先级可以按照大小来规定,存取方式为后进先出;
在操作系统中,内存被分为栈区和堆区:
- 栈区内存由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
- 堆区内存一般由开发者分配释放,若开发者不释放,程序结束时可能由垃圾回收机制回收。
数据类型检测的方式有哪些
- typeof:数组、对象、null 都会被判断为 object,其他判断都正确。
console.log(typeof 2); // number
console.log(typeof true); // boolean
console.log(typeof 'str'); // string
console.log(typeof []); // object
console.log(typeof function(){}); // function
console.log(typeof {}); // object
console.log(typeof undefined); // undefined
console.log(typeof nu1l); // object
- instanceof:
- 可以正确判断对象的类型,其内部运行机制是判断构造函数的prototype 属性是否出现在对象的原型链中的任何位置;
- 只能正确判断引用数据类型,而不能判断基本数据类型。instanceof 运算符可以用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。
console.log(2 instanceof Number); // false
console.log(true instanceof Boolean); // false
console.log('str' instanceof String); // false
console.log([] instanceof Array); // true
console.log(function(){} instanceof Function); // true
console.log({} instanceof object); // true
- constructor
console.log((2).constructor === Number); // true
console.log((true).constructor === Boolean); // true
console.log(('str').constructor === stringy); // true
console.log(([]).constructor === Array); //.true
console.log(function() {}).constructor === Function); // true
console.log(({}).constructor === Object); // true
- constructor 有两个作用,一是判断数据的类型,二是对象实例通过constrcutor 对象访问它的构造函数。需要注意,如果创建一个对象来改变它的原型,constructor 就不能用来判断数据类型了:
function Fn(){};
Fn.prototype = new Array();
var f = new Fn();
console.log(f. constructor === Fn); // false
console.log(f. constructor === Array); // true
- Object.prototype.toString.call()
使用 Object 对象的原型方法toString 来判断数据类型
var a = Object.prototype.tostring;
console.log(a.call(2));
console.log(a.call(true));
console.log(a.call('str'));
console.log(a.call([]));
console.log(a.call(function(){}));
console.log(a.ca1l({}));
console.log(a.cal1(undefined));
console.log(a.call(null));
- 同样是检测对象 obj 调用 toString 方法,obj.toString()的结果和Object.prototype.toString.call(obj)的结果不一样,这是为什么?
- 这是因为 toString 是 Object 的原型方法,而 Array、function 等类型作为 Object 的实例,都重写了 toString 方法。不同的对象类型调用 toString 方法时,根据原型链的知识,调用的是对应的重写之后的 toString 方法(function 类型返回内容为函数体的字符串,Array
类型返回元素组成的字符串…),而不会去调用 Object 上原型toString 方法(返回对象的具体类型),所以采用 obj.toString()不能得到其对象类型,只能将 obj 转换为字符串类型;因此,在想要得到对象的具体类型时,应该调用 Object 原型上的 toString 方法。
- 这是因为 toString 是 Object 的原型方法,而 Array、function 等类型作为 Object 的实例,都重写了 toString 方法。不同的对象类型调用 toString 方法时,根据原型链的知识,调用的是对应的重写之后的 toString 方法(function 类型返回内容为函数体的字符串,Array
null 和 undefined 区别
- Undefined 和 Null 都是基本数据类型,这两个基本数据类型分别都只有一个值,就是 undefined 和 null;
- null表示"没有对象",即该处不应该有值:
- 作为函数的参数,表示该函数的参数不是对象;
- 作为对象原型链的终点
- undefined表示"缺少值",就是此处应该有一个值,但是还没有定义:
- 变量被声明了,但没有赋值时,就等于undefined;
- 调用函数时,应该提供的参数没有提供,该参数等于undefined;
- 对象没有赋值的属性,该属性的值为undefined;
- 函数没有返回值时,默认返回undefined。
- null和undefined与任何有意义的值比较返回都是false,但是null和undefined之间相互比较返回值为true。
如何获取安全的 undefined 值?
因为 undefined 是一个标识符,所以可以被当作变量来使用和赋值,但是这样会影响 undefined 的正常判断。
表达式 void ___ 没有返回值,因此返回结果是 undefined。void 并不改变表达式的结果,只是让表达式不返回值。因此可以用 void 0 来获得 undefined
如何判断一个对象是空对象
- 使用 JSON 自带的.stringify 方法来判断:
if(Json.stringify(Obj) == '{}' ){
console.log(“空对象' );
}
- 使用 ES6 新增的方法 Object.keys()来判断:
if(Object.keys(Obj).length < 0 ){
console.log(“空对象' );
}
const 对象的属性可以修改吗
- const 保证的并不是变量的值不能改动,而是变量指向的那个内存地址不能改动。
- 对于基本类型的数据(数值、字符串、布尔值),其值就保存在变量指向的那个内存地址,因此等同于常量。
- 但对于引用类型的数据(主要是对象和数组)来说,变量指向数据的内存地址,保存的只是一个指针,const只能保证这个指针是固定不变的,至于它指向的数据结构是不是可变的,就完全不能控制了。
什么是 JavaScript 中的包装类型?
在 JavaScript 中,基本类型是没有属性和方法的,但是为了便于操作基本类型的值,在调用基本类型的属性或方法时 JavaScript 会在后台隐式地将基本类型的值转换为对象,如:
const a = "abc";
//在访问'abc'.length 时,JavaScript 将'abc'在后台转换成String('abc'),然后再访问其 length 属性。
a.length; // 3
a.toUpperCase(); //“ABC"
//JavaScript 也可以使用 Object 函数显式地将基本类型转换为包装类型:
var a = "abc";
Object(a) //String {"abc"}
//也可以使用 valueOf 方法将包装类型倒转成基本类型:
var a = 'abc'
var b = Object(a)
var C = b.valueOf() // 'abc'
Object.is() 与比较操作符 “= = =”、“= =” 的区别?
- 双等号(==)进行相等判断时,如果两边的类型不一致,则会进行强制类型转化后再进行比较;
- 三等号(===)进行相等判断时,如果两边的类型不一致时,不会做强制类型准换,直接返回 false;
- 使用 Object.is 来进行相等判断时,一般情况下和三等号的判断相同,它处理了一些特殊的情况,比如 -0 和 +0 不再相等,两个 NaN是相等的。