你真的会判断 js 的数据类型

js 基本数据类型

1. js 基本数据类型有6个依次是'Undefined','Null','Boolean','Number','String','Object'
2.'Undefined'  -- 当值未定义的时候,例如函数没有明确返回值,和声明变量没有赋值
  'Boolean'    -- 布尔类型(truefalse)
  'String'     -- 字符串类型(用单引号或者双引号表示)
  'Number'     -- 数字类型(整数和小数)
  'Null'       -- 空类型,值只有一个:null,一个对象指向为空了,此时可以赋值为null
  'object'     -- 对象
3.后续增加两个 'symbol''BigInt'
4.引用数据类型(Object)又分,Array - 数组对象、RegExp - 正则对象、Date - 日期对象、Math - 数学函数、
Function - 函数对象
5.'基础类型'存储在栈内存,被引用或拷贝时,会创建一个完全相等的变量;
6.'引用类型'存储在堆内存,存储的是地址,多个引用指向同一个地址
7.函数对象参数传递是对象在堆中的地址
复制代码

判断类型

1.判断类型常用方法'typeof''instanceof''Object.prototype.toString''constructor'
复制代码

使用typeof 区分数据类型

1.'typeof' 是一个操作符,不是方法因此使用的时候可以加括号,也可以省略
2.虽然'typeof'是用来区分数据类型的但是6个数据类型中'null'可以理解成是空
对象(object),因此'typeof' 用来区分'undefined','function','boolean','number','string','object'
3.因此简单的说'null' 在使用typeof 验证的时候是'object'
复制代码
案例说明
var num = 10;
var str = "小白";
var flag = true;
var nll = null;
var undef;
var obj = new Object();
var a = function(){}
//是使用typeof 获取变量的类型
console.log(typeof num); // number
console.log(typeof str); // string
console.log(typeof flag); // boolean
console.log(typeof nll); // object
console.log(typeof undef); // undefined
console.log(typeof obj); // object
console.log(typeof a); // function
复制代码

instanceof — 检测引用类型

1. a instanceof B a是不是B的实例,即a的原型链上是否有B
var a = [1,2,3]
console.log(a instanceof Array)  // 变量 A 是数组么

打印结果:
true
复制代码
实现一个instanceof
function myInstanceof(left, right) {
  // 这里先用typeof来判断基础数据类型,如果是,直接返回false
  if(typeof left !== 'object' || left === null) return false;
  // getProtypeOf是Object对象自带的API,能够拿到参数的原型对象
  let proto = Object.getPrototypeOf(left);
  while(true) {                  //循环往下寻找,直到找到相同的原型对象
    if(proto === null) return false;
    if(proto === right.prototype) return true;//找到相同原型对象,返回true
    proto = Object.getPrototypeof(proto);
    }
}
// 验证一下自己实现的myInstanceof是否OK
console.log(myInstanceof(new Number(123), Number));    // true
console.log(myInstanceof(123, Number));                // false
复制代码

利用Object.prototype.toString

1.toString() 是 Object 的原型方法,调用该方法,可以统一返回格式为 '[object Xxx]' 的字符串,Xxx 就是对象的类型
Object 对象,直接调用 toString() 就能返回 [object Object];其他对象,需要通过 call 来调用
复制代码
Object.prototype.toString({})       // "[object Object]"

Object.prototype.toString.call({})  // 同上结果,加上call也ok

Object.prototype.toString.call(1)    // "[object Number]"

Object.prototype.toString.call('1')  // "[object String]"

Object.prototype.toString.call(true)  // "[object Boolean]"

Object.prototype.toString.call(function(){})  // "[object Function]"

Object.prototype.toString.call(null)   //"[object Null]"

Object.prototype.toString.call(undefined) //"[object Undefined]"

Object.prototype.toString.call(/123/g)    //"[object RegExp]"

Object.prototype.toString.call(new Date()) //"[object Date]"

Object.prototype.toString.call([])       //"[object Array]"

Object.prototype.toString.call(document)  //"[object HTMLDocument]"

Object.prototype.toString.call(window)   //"[object Window]"

复制代码
typeof 和 Object.prototype.toString 搭配来判断数据类型
function getType(obj){
    let type  = typeof obj;
    if (type !== "object") {    // 先进行typeof判断,如果是基础数据类型,直接返回
      return type;
    }
    // 对于typeof返回结果是object的,再进行如下的判断,正则返回结果或者用slice(8,-1)来截取获得
    return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1');  // 注意正则中间有个空
  }
  
  /* 代码验证,需要注意大小写,类型首字母大写就是toString 小写就是typeof */ 
  getType([])     // "Array" typeof []是object,因此toString返回
  getType('123')  // "string" typeof 直接返回 
  getType(window) // "Window" toString返回
  getType(null)   // "Null"首字母大写,typeof null是object,需toString来判断
  getType(undefined)   // "undefined" typeof 直接返回
  getType()            // "undefined" typeof 直接返回
  getType(function(){}) // "function" typeof能判断,因此首字母小写
  getType(/123/g)      //"RegExp" toString返回
复制代码

为什么不能用 Object.toString.call()

1.如果当你使用Object.toString.call 来判断类型你会发现,会报错,其中提示内容是报错内容如下
"Function.prototype.toString requires that 'this' be a Function",内置的Object构造函数是一个 Function
(就像所有的原生构造函数一样),所以它在它自己的原型属性之前从Function.prototype继承
'Object[[Prototype]] -> Function.prototype -> Object.prototype -> null'所以实际调用的是
'Function.prototype.toString',可以通过查看 下面的两个链接可以知道
若 'this' 不是 Function 对象,则 toString() 方法将抛出 TypeError 
 ("Function.prototype.toString called on incompatible object") 异常
复制代码
console.log(typeof Object); // function
console.log(typeof Object.prototype); // object

// Object.toString.call([]) // 报错

function a () { }

Object.toString.call(a) // 不报错因为a 是function
复制代码

ecma-262

Mdn-toString
阶段参考

constructor

const array = []
console.log( array.constructor)

const num = 1
console.log(num.constructor)

打印结果
ƒ Array() { [native code] }
ƒ Number() { [native code] }

var a = [];
a.constructor === Array;
复制代码

总结关于检测数据类型

1.typeof 在引用类型检测的时候不能具体,除了function 可以判断出来,剩下的引用类型和null统一都是'object'
2.instanceof 可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型;
3.Object.prototype.toString 万能方法最终解
复制代码

null 和 undefined

1.首先当我们声明一个对象的变量的时候,如果没有给其赋值最好设置为'null',
例如: var myObject = null
2.当使用 双等时候 :console.log(null == undefined) 结果为 'true' 但不建议这么使用
3.null 是 JavaScript 保留关键字,而undefined是全局对象的一个属性。也就是说,它是全局作用域的一个变量。
undefined的最初值就是原始数据类型undefinedundefined是一个不能被配置(non-configurable),不能被重写
(non-writable)的属性,也要注意'undefined不是一个保留字'
复制代码

undefined

undefined
1.Undefined 是一个很特殊的数据类型,它只有一个值,也就是 undefined
2.产生undefined几种情况
    2.1.引用已声明但未初始化的变量;
    2.2.引用未定义的对象属性;
    2.3.执行无返回值函数;
    2.4.执行 void 表达式;
    2.5.全局常量 window.undefined 或 undefined3.void 表达式来得到 undefined 值,因为这种方式既简并且比undefined长度少,不需要引用额外变量和属性
在三目运算的时候表示不进行任何操作
    x>0 && x<5 ? fn() : void 0;
4.'undefined是全局对象的一个属性',因此在非全局作用域下可以重新赋值
    // 打印 'foo string' PS:说明undefined的值和类型都已经改变
    (function() {
    var undefined = 'foo';
    console.log(undefined, typeof undefined)
    })()
复制代码
  • 第二条对应代码
var a; // undefined
var o = {}
o.b // undefined
(() => {})() // undefined
void 0 // undefined
window.undefined // undefined
复制代码
关于对 undefined 类型的判断
1.下面的三种形式都可以对 'undefined' 做判断,但是推荐type of 的形式,原因:第一种对空字符串
数值0null等情况都会有不仅仅针对undefined,第二种用'==='但是如果变量没定义会报错,导致程序
停止运行
复制代码
// 方式1
if(!x) {
  ...
}
// 方式2
if(x===undefined) {
  ...
}
// 方式2
if(typeof x === 'undefined') {
  ...
}

复制代码

Boolean 类型

1.布尔类型只有两个字面值:'true''false', 并且区分大小写,只能小写表示
2.如果想将其他值转成布尔类型使用'Boolean()' -- 或者使用'!!'
3.有时候可以看到一些言论说数字1true 或者0false 实际只是在if条件语句中
这些值自动执行了'Boolean' 方法上的转化
复制代码
常见的类型转化成boolean
数据类型 转化为true 转化成false
Boolean true false
String 任何非空字符 字符串length等于0(空字符)
Number 非0的数字(Infinity)包括无穷大 0 和 NaN
Object 任何对象包括 {} 对象中没值 /new Boolean(false) null
Undefined n/a(不使用的意思) undefined
console.log(Boolean(Infinity)) // true
复制代码

Number 类型

1.二进制:遇到2进一
2.八进制:遇到8进一
3.十进制:遇到10进一
4.十六进制:遇到f进一
5.数字类型分整数类型和浮点数值类型
6.NaN 表示非数值类型
7.Infinity 表示无穷大
复制代码

toLocaleString 有意思

进制问题
1.十进制就是正常数字表示
2.八进制的第一位必须是0,然后数字顺序是(0-7),超出0-7前导0被忽略然后展示数字
3.十六进制必须是0x开头,后面跟着(0-9)及(A-F),字母大小写不区分,超出同理八进制
4.计算的时候会自动将八进制和十六进制转换成十进制
复制代码
var intNum = 10; // 十进制
var octalNumber1 = 070; // 八进制
var octalNumber2 = 080; // 错误的八进制只能在0-7中    
var hexNumber1 = 0xA; // 十六进制
console.log(intNum, octalNumber1, octalNumber2, hexNumber1)
打印结果:
10 56 80 10
复制代码
  • 进制计算
var octalNumber1 = 070; // 八进制
var hexNumber1 = 0xA; // 十六进制
console.log(hexNumber1+octalNumber1) // 八进制56 + 十六进制10
打印结果:
66
复制代码
浮点数值
1.浮点值内存空间是整数值的两倍,因此在特定情况下浮点值回被转成整数,例如:
var a = 1.0 打印的值就是1
2.可以使用科学计数法来表示一些数值,表现形式就是'e'前面的数值乘上后面10的次幂,
例如:var a = 3.12e5  相当于3.12 * 10^5 因此 a 的结果是'312000'
3.想用科学计数法表示小数则可以写成:var a = 3.12e-5 打印结果0.0000312
4.不要用一个小数去求证一个小数
复制代码
数值范围
1.js 表示数字的最大值/最小值 使用:'MAX_VALUE/MIN_VALUE'例如 console.log(Number.MAX_VALUE)
2.使用'Infinity / -Infinity' 表示'无穷大/无穷小' 
复制代码

NaN — 非数值(Not a Number)

1.NaN 不予任何值相等包括本身例如:alert(NaN == NaN) // false
2.任何数值除以非数值都会返回NaN
3.想判断当前是不是数字用'isNaN()' 方法,不是数字返回true,是数字返回false,这种判断不准确
  因为isNaN 接受的参数其实是数字,当然如果你传入了其他类型参数你发现他依然可以执行,
  在规范中的解释是'Let num be ToNumber(number).'
4.isNaN()  也可以验证对象,但是会先调用对象的valueOf() 看返回的是不是一个数字,
如果对象没有这个方法,则调用toString() 方法,如果都没有则为'true',反之根据刚才两
方法的返回值来做判断
5.判断一个值是不是数字'typeof value === 'number' && !isNaN(value)' ,因为NaNtypeof 是number
6.当然判断是不是NaN 最好用全等判断因为 NaN === NaN 结果为false
复制代码

tonumber
isnan

console.log(isNaN(NaN))  // true
console.log(isNaN('w')) // true
console.log(isNaN(10))  // false
console.log(isNaN('10')) // false
console.log(isNaN(true)) // false(true会被转成1)
console.log(isNaN([]) )// false
console.log(isNaN([123]) )// false
console.log(isNaN(['123']))// false
复制代码
数字类型转化 — Number()、parseInt()、parseFloat()
1.总结:想要转整数用parseInt(),想要转小数用parseFloat()想要转数字:Number();
要比上面的两种方式严格
复制代码
  • Number
1.Booleantruefalse 会被转成 10
2.如果只是数字写什么是什么,但是八进制和十六进制会被转成10进制
3.null 和 空字符串("") 都会变成0
4.如果是字符串,但只有数字的字符串会被转成十进制,例如'11' 转成 11'011' 会被转成 11 则会把前面的0去掉,但不会直接八进制转十进制
5.十六进制除外,十六进制的字符串会直接转成10进制
6.如果字符串中任何位置有非数字都是NaN
7.对象的话先调用valueOf() 在 toString() 如果这两个返回值都不符合上面的规定就是NaN
复制代码
console.log(Number(070)) 
console.log(Number(011))  
console.log(Number('070'))  
console.log(Number(NaN))  
console.log(Number("sss"))  
console.log(Number(undefined))  
console.log(Number(null))  
console.log(Number(''))
console.log(Number('0xf'))
复制代码
56
9
70
NaN
NaN
NaN
0
0
15
复制代码
  • parseInt
1.如果是整数正常解析
2.如果是字符串则开头必须是数字或者是(加减号),然后一直到后续遇到的非数字,
这里要说明如果字符串的开头是空格则忽略一直找到非空格字符,然后根据上面规则
规则转换(注意是空格开头,中间空格也不行)
3.根据上面的结论所以可以得出为什么 'parseInt' 为什么可以把小数转成整数,例
如1.1,从1开始找到后面发现点不是数字所以后面全丢弃得到 1
4.字符串的情况下,十六进制是不识别的,八进制会把前缀0舍去,要注意和'Number'
不同null 和 空字符都是 NaN
5.想让parseInt 识别十六进制 和八进制字符串可以这么写parseInt('AF',16) 第二个参数表示
几进制
复制代码
console.log(parseInt(070))   // 56
console.log(parseInt('-070   00')) // -70 
console.log(parseInt(null)) // NaN
console.log(parseInt('AF')) // NaN
console.log(parseInt('AF',16)) // 175
console.log(parseInt('070',8)) // 56
console.log(parseInt("g10"));   //NaN
复制代码
  • parseFloat
1.parseInt() 类似,只不过解释所有里面浮点类型,不同点没有第二个参数,无法把十六进制
和八进制字符串转换,十六进制字符串统一被转成 0
复制代码
 console.log(parseFloat("10"));//10
 console.log(parseFloat("10afrswfdsf"));//10
 console.log(parseFloat("g10"));//NaN
 console.log(parseFloat("1fds0"));//1
 console.log(parseFloat("10.98"));//10.98
 console.log(parseFloat("10.98fdsfd"));//10.98
复制代码
关于trunc方法说明重点

字符串String

1.toString()可以将所有的的数据都转换为字符串,但是要排除nullundefined,
也就是falsetrue,包含在内,也可以做进制转换例如:
    二进制:.toString(2);   
    八进制:.toString(8);
    十进制:.toString(10);
    十六进制:.toString(16);

2.String()可以将nullundefined转换为字符串,但是没法转进制字符串,也能对flase和true 转换

3.两个都返回新的,toString 返回的是调用者对象本身的toString 方法

复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享