数据类型
JavaScript有哪些数据类型,他们的区别
JavaScript有八种数据类型,分别是Undefined,Null,Boolean,Number,String,Object,Symbol,BigInt
其中Symbol和BigInt是ES6中新增的数据类型:
-
Symbol代表创建后独一无二且不可变的数据类型,主要是解决可能出现的全局变量冲突的问题
-
BigInt是一种数字类型的数据,它可以代表任意精度格式的整数,使用BigInt可以安全地存储和操作大整数,即使超出了Number的范围
数据还可以分为原始数据类型和引用数据类型
-
栈:原始数据类型(Undefined,Null,Boolean,Number,String)
-
堆:引用数据类型(对象,数组和函数)
两种类型的区别在于存储位置的不同:
-
原始数据类型直接存储在栈中的简单数据段,占据空间小,大小固定,属于被频繁使用的数据
-
引用数据类型在堆中的对象,占据空间大,大小不固定,如果存到栈,会影响程序运行的性能
在操作系统中,内存被分为栈区和堆区
-
栈区内存由编译器自动分配释放,存放函数的参数值,局部变量等,其操作方式类似于数据结构中的栈
-
堆区内存一般由开发者分配释放,若开发者不释放,程序结束时可能由垃圾回收机制回收。
数据类型检测的方式有哪些
-
typeof
javascriptconsole.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 null); // object
其中数组,对象,null都会被判断为object,其他判断都正确
-
instanceof
可以正确判断对象的类型,其内部运行机制是判断在其原型链中能否找到该类型的原型
javascriptconsole.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
可以看出来,instanceof只能正确判断引用数据类型,而不能判断基本数据类型 ,instanceof运算符可以用来测试一个对象在其原型链中是否存在一个构造函数的prototype属性
-
constructor
javascriptconslog.log((2).constructor === Number); // true conslog.log((true).constructor === Boolean); // true conslog.log(('str').constructor === String); // true conslog.log(([]).constructor === Array); // true conslog.log((function(){}).constructor === Function); // true conslog.log(({}).constructor === Object); // true
constructor有两个作用,一是判断数据的类型 ,二是对象实例通过constructor对象访问它的构造函数 ,需要注意,如果创建一个对象来改变它的原型 ,constructor就不能用来判断数据类型了
javascriptfunction 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来判断数据类型
javascriptvar a = Object.prototype.toString; console.log(a.call(2)); // Number console.log(a.call(true)); // Boolean console.log(a.call('str')); // String console.log(a.call([])); // Array console.log(a.call(function(){})); // Function console.log(a.call{}); // Object console.log(a.call(undefined)); // undefined console.log(a.call(null)); // Null
obj.toString()和Object.prototyep.toString.call(obj)的结果不一样 ,因为toString是Object原型方法,而Array,function等类型作为Object实例,都重写了toString方法。
判断数组的方式有哪些
-
通过Object.prototype.toString.call()做判断
javascriptObject.prototype.toString.call(obj).slice(8,-1) === 'Array';
-
通过原型链做判断
javascriptobj.__proto__ === Array.prototype;
-
通过ES6的Array.isArray()做判断
javascriptArray.isArray(obj);
-
通过instanceof做判断
javascriptobj instanceof Array
-
通过Array.prototype.isPrototypeOf
javascriptArray.prototype.isPrototypeOf(obj);
null和undefined区别
Undefined和Null都是基本数据类型,这两个基本数据类型分别都只有一个值,就是undefined和null。
undefined代表的含义是未定义 ,null代表的含义是空对象,一般变量声明了但还没有定义的时候会返回undefined,null主要用于赋值给一些可能会返回对象的变量,作为初始化。
undefined在JavaScript中不是一个保留字,可以使用undefined作为一个变量名。
当对这两种类型使用typeof进行判断 时**,Null类型会返回"Object"** ,当使用双等号对两种类型的值进行比较会返回true,使用三个等号会返回false
javascript
console.log(null === undefined); // false
console.log(null == undefined); // true
typeof null的结果是什么,为什么
typeof null的结果是Object
在JavaScript第一个版本中,所有值都存储在32为单元中,每个单元包含一个小的类型标签 以及当前要存储值的真实数据 。类型标签存储在每个单元的低位中,共有五种数据类型:
javascript
000:object - 当前存储的数据指向一个对象
1:int - 当前存储的数据是一个31为的有符号整数
010:double - 当前存储的数据指向一个双精度的浮点数
100:string - 当前存储的数据指向一个字符串
110:doolean- 当前存储的数据是布尔值
有两种特殊数据类型:
-
undefined的值是(-2)30(一个超出整数范围的数字)
-
null的值是机器码NULL指针(null指针的值全为0)
也就是说null的类型标签也是000,和Object的类型标签一样,所以会被判定为Object
6.
instanceof操作符的实现原理及实现
instanceof运算符用来判断构造函数的prototype属性是否出现在对象的原型链中的任意位置
javascript
function myInstanceof(left,right){
// 获取对象的原型
let proto=Object.getPrototypeOf(left)
// 获取构造函数的prototype对象
let prototype = right.prototype;
// 判断构造函数的prototype对象是否在对象的原型链上
while(true){
if(!protp) return false;
if(proto === prototype) return true;
// 如果没有找到,就继续从其原型上找,Object.getPrototypeOf方法用来获取指定对象的原型
proto = Object.getPrototypeOf(proto);
}
}
为什么0.1+0.2 !== 0.3,如何让其相等
javascript
let n1 = 0.1,n2=0.2
console.log(n1+n2) // 0.300000000000000000004
得到的不是想要的结果,要想等于0.3,把它进行转化
javascript
(n1+n2).toFixed(2) // 注意,toFixed为四舍五入
如果实现01.+0.2=0.3呢,ES中,提供了Number.EPSILON属性,它的值是2的-52次方,只要判断01.+0.2-0.3是否小于Number.EPSILON
javascript
function numberpsilon(arg1,arg2){
return Math.abs(arg1-arg2) < Number.EPSILON;
}
console.log(numberpsilon(0.1+0.2,0.3));
如何获取安全的undefined值
因为undefined是一个标识符 ,所以可以被当作变量来使用和赋值,这样会影响undefined的正常判断 ,表达式void__没有返回值,因此返回结果为undefined,void并不改变表达式的结果,只是让表达式不返回值,可以用void 0 来获取undefined
javascript
console.log(void 0); // 获取undefined
typeof NaN 的结果是什么
NaN指"不是一个数字",NaN是一个"警戒值",用于支出数字类型中的错误情况
javascript
typeof NaN; // "number"
NaN是一个特殊值,它和自身不相等,是唯一一个非自反的值,NaN !== NaN 为true