2-JavaScript基础知识-数据类型以及数据的三种判断方式


前言

我们要了解JavaScript这门脚本的来源,他的一些数据类型,以及如何判断数据类型,而且在JavaScript中存在隐式转化要注意一些阴间玩意~~~~


一、JavaScript是什么语言类型?

  • 静态语言: 在声明变量之前需要先定义变量类型。我们把这种在使用之前就需要确认其变量数据类型的称为静态语言。
  • 动态语言:在声明变量之前不需要先定义变量类型。我们把这种在使用之前不需要确认其变量数据类型的称为动态语言。
  • 强/弱语言:通常把会偷偷转换的操作称为隐式类型转换。而支持隐式类型转换的语言称为弱类型语言,不支持隐式类型转换的语言称为强类型语言。
    在这里插入图片描述
    由上面类型的判断,我们可以知道JavaScript 是一种弱类型的、动态的语言。这些特点也意味着。弱类型,你不需要告诉JavaScript引擎这个变量是什么类型的数据,JavaScript引擎在运行代码的时候回自己机计算出来。动态也就以为这你可以用同一个变量保存不同类型的数据。
	//弱类型
	let a = 'sadf';
    let b = 4573;
    let c = undefined;
    console.log(typeof(a));  //string
    console.log(typeof(b));  //number
    console.log(typeof(c));  //undefined
    //动态
    a = 5645
    console.log(typeof(a));  //number

二、数据类型

  1. undefined : 一个没有被赋值的变量会有个默认值 undefined
  2. Null : Null 类型只有一个值: null
  3. Boolean : 表示逻辑实体,有两个值true和false
  4. Number : 数字类型 ,范围 -/+( 2^63-1)
  5. String : 字符串类型,不可修改,第一个字下表为0
  6. Symbol:符号类型是唯一的且不可修改的,通常用来做object的key
  7. BigInt : 新的数据类型,可以用任意精度表示整数
  8. Object : 一组属性的集合

注意点

  • 除了引用型数据是存储在堆中的,其他类型都是存储在栈中的,而引用型的数据会在栈中保留一个指针,指向在堆中的位置
  • 除了Object是引用数据类型,其他都是基本类型,而深/浅拷贝只对object和Array这些引用类型起作用
  • 使用 typeof 检测 Null 类型时,返回的是 Object。这是当初 JavaScript 语言的一个 Bug,一直保留至今,之所以一直没修改过来,主要是为了兼容老的代码。
  • Object 类型比较特殊,它是由上述 7 种类型组成的一个包含了 key-value 对的数据类型。如下所示:
  • 栈内存是自动分配内存的。而堆内存是动态分配内存的,不会自动释放。所以每次使用完对象的时候都要把它设置为null,从而减少无用内存的消耗
  • 除了Object是引用型数据,其他都是基本数据类型,而在JavaScript中,赋值操作(=)和其他语言有很大的不同,原始类型的赋值会完整复制变量值,而引用类型的赋值是复制引用地址。也应为这个原因对于引用型数据有深拷贝这个影响的出现。
  • 对于变量,永远不要显式给它赋值为undefined,但对于变量要是要保存对象的话,永远要对他保存为null,这样我们就能保证null指向空指针的语义,同时区分开和undefined

三、真值/假值

补充一个知识点,就是什么是真值和假值,以及他们的用途效果

  • 假值:
    • false
    • null
    • undefined
    • 0
    • ‘’(空字符串)
    • NAn
  • 真值
    *除了上面以外的都为真值

注意
在判断是要注意区分开了,自己判断的是某个字变量(null,undefined…)同时他还是个假值的影响

四、类型判断

简介

typeof

定义

  • 这个方法很常见,一般用来判断基本数据类型,如:string,number,boolean,symbol,bigint(es10新增一种基本数据类型bigint),undefined等。
    typeof 目前能返回string,number,boolean,symbol,bigint,unfined,object,function这八种判断类型
		//用typeof判断类型
        let a ;
        let b = null;
        let c = true;
        let d = 666;
        let e = "牛逼";
        let f = 6546513248976512376878646514657876534535434n;
        let g = {
            a: 7856,
            b: 4613
        }let h = function() {};	
        
        
        console.log(typeof a);  //undefind
        console.log(typeof b);  //object
        console.log(typeof c);  //boolean
        console.log(typeof d);  //number
        console.log(typeof e);  //string
        console.log(typeof f);  //bigint
        console.log(typeof g);  //object
        console.log(typeof h);  //function
        console.log(typeof aa);  //undefind
        

注意点

  1. 对于null的判断是object
  2. 对于未初始化和声明的变量的判断都是undefined

instanceof

定义

  • 一般用来判断引用数据类型的判断,如:Object,Function,Array,Date,RegExp等
    instanceof 主要的作用就是判断一个实例是否属于某种类型
  • instanceof 也可以判断一个实例是否是其父类型或者祖先类型
  • instanceof原理实际上就是查找目标对象的原型链

缺点

  1. 不能检测原始值类型;
  2. 原型链可以重构,导致结果不准确
//这段代码来自MDN
// 定义构造函数
function C(){}
function D(){}

var o = new C();


o instanceof C; // true,因为 Object.getPrototypeOf(o) === C.prototype


o instanceof D; // false,因为 D.prototype 不在 o 的原型链上

o instanceof Object; // true,因为 Object.prototype.isPrototypeOf(o) 返回 true
C.prototype instanceof Object // true,同上

C.prototype = {};
var o2 = new C();

o2 instanceof C; // true

o instanceof C; // false,C.prototype 指向了一个空对象,这个空对象不在 o 的原型链上.

D.prototype = new C(); // 继承
var o3 = new D();
o3 instanceof D; // true
o3 instanceof C; // true 因为 C.prototype 现在在 o3 的原型链上

手写实现instanceof
思路

  • 先判断是否为对象类型或者特殊情况null
  • 再比较实例对象的原型等不等于构造函数的prototype,
  • 如果等于,则返回true
  • 如果不等于,则找实例对象原型的原型,比较它等不等于构造函数的prototype,
  • 如果等于,则返回true
  • 如果不等于,则继续在原型链往上找,直到找到原型链的最顶层,即null,则为false
//后面打算写篇关于手写实现所有JavaScript中关键的方法的。
function myInstanceof(left, right) {
    //基本数据类型直接返回false
    if(typeof left !== 'object' || left === null) return false;
    //getProtypeOf是Object对象自带的一个方法,能够拿到参数的原型对象
    let proto = Object.getPrototypeOf(left);
    while(true) {
        //查找到尽头,还没找到
        if(proto == null) return false;
        //找到相同的原型对象
        if(proto == right.prototype) return true;
        proto = Object.getPrototypeOf(proto);
    }
}
console.log(myInstanceof("111", String)); //false
console.log(myInstanceof(new String("111"), String));//true

Object.prototype.toString.call(这个是判断类型最准的方法)

定义

  • 每一个Object原型上的都会继承toString()方法,该方法没有重写,都会返回其调用者的具体类型,返回的类型格式为[object,xxx],xxx是具体的数据类型
  • 但是我们使用的很多数据类型都重写了toString()方法,所以我们同时还得用call()或Reflect.apply()指向它的Object,确保执行的是object的toString方法。
  • 不能通过new来创建,我们是根据原型链来查找到该元素的Object下的toString()方法的。

Object.prototype.toString() 的原理

  • 如果参数为null或undefined,会直接返回。
  • 如果并不是,就会把参数转化为对象,再判断。
  • 转为对象后,取得该对象的获取this对象的[[Class]]属性的值. 作为 tag,返回 "[object " + tag + “]” 形式的字符串。

console.log(Object.prototype.toString.call(null));            // => "[object Null]"
console.log(Object.prototype.toString.call(undefined));       // => "[object Undefined]"
console.log(Object.prototype.toString.call(true));            //  "[object Boolean]"
console.log(Object.prototype.toString.call(1753));            //  "[object Number]"
console.log(Object.prototype.toString.call("你好"));          //  "[object String]"
console.log(Object.prototype.toString.call([1,2,5]));         //  "[object Array]"
console.log(Object.prototype.toString.call((function() {
  return arguments;
})()));                                                       //  "[object Arguments]"
console.log(Object.prototype.toString.call(function(){}));    //  "[object Function]"
console.log(Object.prototype.toString.call(new Error()));     //  "[object Error]"
console.log(Object.prototype.toString.call(/\d+/));           //  "[object RegExp]"
console.log(Object.prototype.toString.call(new Date()));      //  "[object Date]"
console.log(Object.prototype.toString.call(new class {}));    //  "[object Object]"


总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

提问环节

1.问:为什么一定要分“堆”和“栈”两个存储空间呢?所有数据直接存放在“栈”中不就可以了吗?

答:不可以的。这是因为 JavaScript 引擎需要用栈来维护程序执行期间上下文的状态,如果栈空间大了话,所有的数据都存放在栈空间里面,那么会影响到上下文切换的效率,进而又影响到整个程序的执行效率。

2.在JS中为什么0.2+0.1>0.3?

答:因为在JS中,是转化为二进制计算,浮点数是使用64位固定长度来表示的,第一位表示符号位,11位用来表示指数位,剩下的52位尾数位,由于只有52位表示尾数位。标准位数的多余的位数会被截断,造成进度缺失了,计算完成后又转化为十进制就变为0.300000000000004

演变题型:

  1. 为什么0.2 + 0.3 = 0.5 (因为刚好)
  2. 那么如何让0.1+0.2 = 0.3

3.为什么typeof null是Object

答:在JavaScript中,对象都是使用二进制存储的,如果二进制前三位都是0的话,系统会判断为是Object类型,而null的二进制全为0,所以判断出来的结果object,并且null在逻辑上讲,表示一个空对象指针。(想深入看看如何二进制的存储的,随便看了眼,好像跟前端二进制啥的有关,还没了解过,埋个坑吧)

其他的一些常用的

  • 000 对象
  • 1 整型
  • 010 双精度类型
  • 100字符串
  • 110布尔类型
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

文默

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值