JS数据结构
饭啊饭° 人气:01.JS有哪些数据类型有什么区别
答:JS共有八大数据类型,分别是:String、Number、Boolean、Object、Null、Undefined、Symbol、BigInt。其中Symbol(独一无二不可变)和BigInt(任意精度的数字)是ES6中新加入的数据类型。这些数据类型可以分为原始数据类型(String、Number、Boolean、Null、Undefined)和引用数据类型(Object、数组、函数等)。
**区别:**存储位置不同 原始数据类型直接存储在栈(stack)中的简单数据段,占据空间、大小固定,属于被频繁使用的数据,所以放在栈中存储;引用数据类型存储在堆中的对象,占据空间大、大小不固定,如果存储在栈中,将会影响程序运行的性能。
- 在数据结构中,栈中数据的存取方式为先进后出。
- 堆是一个优先队列,是按优先级来进行排序的,优先级可以按照大小来规定。
2.数据类型检测的方式
答:JavaScript有4种方法判断变量的类型,分别是typeof、instanceof、Object.prototype.toString.call()(对象原型链判断方法)、 constructor (用于引用数据类型) 。typeof:常用于判断基本数据类型,对于引用数据类型除了function返回’function‘,其余全部返回’object’。 instanceof:主要用于区分引用数据类型,检测方法是检测的类型在当前实例的原型链上,用其检测出来的结果都是true,不太适合用于简单数据类型的检测,检测过程繁琐且对于简单数据类型检测不出来。 constructor:用于检测所有数据类型,检测方法是获取实例的构造函数判断和某个类是否相同,如果相同就说明该数据是符合那个数据类型的,这种方法不会把原型链上的其他类也加入进来,避免了原型链的干扰。 Object.prototype.toString.call():适用于所有类型的判断检测,检测方法是Object.prototype.toString.call(数据) 返回的是该数据类型的字符串。 这四种判断数据类型的方法中,各种数据类型都能检测且检测精准的就是Object.prototype.toString.call()这种方法。
加分回答 instanceof的实现原理:验证当前类的原型prototype是否会出现在实例的原型链__proto__上,只要在它的原型链上,则结果都为true。因此,instanceof
在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype
,找到返回true,未找到返回false。 Object.prototype.toString.call()原理:Object.prototype.toString 表示一个返回对象类型的字符串,call()方法可以改变this的指向,那么把Object.prototype.toString()方法指向不同的数据类型上面,返回不同的结果
(1)typeof:返回数据的类型,但是数组、null、对象、函数,都只能返回object,所以typeof并不能区分出处理function的其他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 null); // object
衍生问题:为什么typeof null 是obect ?
原因是:在JS的第一个版本中,所有值都存储在32位的单元中,每个单元包含一个小的类型标签,以及当前要存储的真实数据,类型标签包括000(object)、1(int)、010(double)、100(string)、110(boolean)。而null的机器码全是0,所以被认为是object。
(2)instanceof:可以判断instanceof后面的类型是否正确,返回true / false,内部的运行机制是看能不能在原型链中找到该类型的原型。但是instanceof只能判断出引用数据类型,并且可以区分出数组、函数等,却不能判断基本数据类型。
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
(3)constructor可以判断数据类型,还可以访问对象的构造函数。constructor可以把object分开来判断。分为(Array、Function、object)
console.log((2).constructor === Number); // true console.log((true).constructor === Boolean); // true console.log(('str').constructor === String); // true console.log(([]).constructor === Array); // true console.log((function() {}).constructor === Function); // true console.log(({}).constructor === Object); // true
(4)Object.prototype.toString.call():使用Object对象的原型方法toString来判断数据类型
var a = Object.prototype.toString; console.log(a.call(2)); //[object Number] console.log(a.call(true)); //[object Boolean] console.log(a.call('str')); //[object String] console.log(a.call([])); //[object Array] console.log(a.call(function(){})); //[object Function] console.log(a.call({})); //[object Object] console.log(a.call(undefined)); //[object Undefined] console.log(a.call(null)); //[object Null]
3.判断是否是数组的方法
var b = new Array(); console.log(b instanceof Array); //true console.log(Object.prototype.toString.call(b)); //[object Array] console.log(Array.isArray(b)); //true console.log(b.constructor===Array); //true console.log(b.__proto__===Array.prototype); //true console.log(Array.prototype.isPrototypeOf(b)); //true
4.null和undefined的区别
答:undefind 是全局对象的一个属性,当一个变量没有被赋值或者一个函数没有返回值或者某个对象不存在某个属性却去访问或者函数定义了形参但没有传递实参,这时候都是undefined。undefined通过typeof判断类型是’undefined’。undefined == undefined undefined === undefined 。 null代表对象的值未设置,相当于一个对象没有设置指针地址就是null。null通过typeof判断类型是’object’。null === null null == null null == undefined null !== undefined undefined 表示一个变量初始状态值,而 null 则表示一个变量被人为的设置为空对象,而不是原始状态。在实际使用过程中,不需要对一个变量显式的赋值 undefined,当需要释放一个对象时,直接赋值为 null 即可。 让一个变量为null,直接给该变量赋值为null即可。typeof null是object。
undefined == null //true undefined === null //false undefined !== null //true
5.手写instanceof方法
function myInstanceof(left,right){ let proto = Object.getPrototypeOf(left) let prototype = right.prototype; while(true){ if(!proto) return false if(proto === prototype) return true proto = Object.getPrototypeOf(proto) } } console.log(myInstanceof("",Array)); //false console.log(myInstanceof([1,2,3],Array)); //true
6.为什么0.1+0.2 !==0.3
答:首先要知道小数是如何转为二进制的,整数部分就是不断除2取余,小数部分就是乘二取整,超过1以后还是用小数部分乘,如下所示:
//不断的乘以二然后拿掉整数部分,直到积为0。
//但是结果是不可能为0的,所以是循环的
0.1 * 2 = 0.2 => 0
0.2 * 2 = 0.4 => 0
0.4 * 2 = 0.8 => 0
0.8 * 2 = 1.6 => 1
0.6 * 2 = 1.2 => 1
0.2 * 2 = 0.4 => 0
…
因此,0.1的二进制是0.0001 1001 1001 1001…无限循环,0.2的二进制是0.0011 0011 0011 0011…无限循环,所以0.3的二进制就是0.0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100,转换为十进制就是0.300000004,这就是精度丢失问题,所以0.1+0.2 !== 0.3。可以用toFixed(1)来解决,但也要注意,toFixed()返回的类型是String。
7.isNaN和Number.isNaN函数的区别
- isNaN接受参数后,会尝试将这个参数转换为数值,任何不能转换的都会返回true,因此,非数字值传入也会返回true,会影响NaN的判断。
- Number.isNaN会首先判断传入参数是否是数字,如果是数字再继续判断是否为NaN,不会进行数据类型的转换,更加准确。
console.log(isNaN(NaN)) //true console.log(isNaN("123")); //false console.log(isNaN("NaN")); //true console.log(Number.isNaN(NaN)); //true console.log(Number.isNaN("123")); //false console.log(Number.isNaN("NaN")); //false
8.==操作符的强制类型转换规则
(1)类型相同的话就直接比较;
(2)类型不同的话,会进行类型转换;
(3)先判断是不是null 和 undefined,是的话就返回true;
(4)判断是否是string 和 number,string --> number;
(5)如果有一方是boolean,那么boolean --> number;
(6)如果一方是object,另一方是string number symbol,把object–> 原始类型。
console.log(NaN == NaN); //false console.log(null instanceof Object); //false 因为null是原型链的顶端了,而instanceof是根据Object.getPrototypeof()实现的,找不到他的父类了 console.log(null == null); //true console.log(false == ""); //true console.log(undefined == false); //false
9.强制转换的规则
(1)其他值–>字符串:Null、Undefined、Boolean、Number、Symbol都是直接转换为字符串,加上双引号,对于普通对象来说,一般会用toString()转换为内部属性[[Class]]的值;
(2)其他值–>数字值:①Undefined类型的值转换为NaN,Null类型转换为0,true为1,false为0,String如果包含非数字就为NaN,否则为数字,空字符串为0,Symbol会报错;
(3)其他值–>布尔值:false值包括(undefined,null,false,+0,-0,NaN,“”),其他值都是真值。
10.Object.is()与比较操作符===和==的区别
答:==在进行判断时,如果两边类型不一致,会进行转换,转换以后再比较;===如果两边类型不一致,就不会进行强制类型转换,直接返回false;Object.is()一般情况下和三等号相同,但是-0和+0不再相等,两个NaN是相等的。
加载全部内容