JavaScript的数据类型及判断
栏目: JavaScript · 发布时间: 5年前
内容简介:最近自己回归基础看了下javascript的相关知识点,想着看都看了,写出来记录下足迹也是一件好事,遂记录~还有还有,哪位大佬有在
最近自己回归基础看了下javascript的相关知识点,想着看都看了,写出来记录下足迹也是一件好事,遂记录~
还有还有,哪位大佬有 广州 前端开发工程师的机会推荐一下吗,简历可以戳 blog下的resume.png ,我请你吃糖:candy::smile:
在 javascript
中有两种类型,一种是基本数据类型,一种是引用类型。
基本类型
基本数据类型,也称为简单数据类型,在 ES5
中有以下五种: Undefined、Null、Boolean、Number和String
,在 ES6
中新增了一种简单的数据类型 Symbol
。
Undefined类型
Undefined类型只有一个值 undefined
。在进行相关变量定义的时候,未赋值的情况下,默认是赋值为 undefined
了。但是也是有些特殊的情况下会报错的。情况我大致罗列下:
# 情况1⃣️:变量声明了,但是没有赋值 var message; console.log(message); // undefined # 情况2⃣️:变量声明并赋值了,但是在console运行之后 console.log(message); // undefined var message = 'find a frontend job in Canton!'; # 情况3⃣️:变量没声明,报引用报错 // var message; console.log(message); // Uncaught ReferenceError: message is not defined # 情况4⃣️:不通过var声明,直接写变量,报引用错误 message; // 不等价 var message; console.log(message); // Uncaught ReferenceError: message is not defined # 情况5⃣️:不通过var声明,直接写变量赋值 message = 'find a frontend job in Canton!'; // 默认在message前添加了var console.log(message); // find a frontend job in Canton! # 情况6⃣️:不通过var声明,直接写赋值,但是在console运行之后,报引用错误 console.log(message); message = 'find a frontend job in Canton!'; // 相当于没message变量 复制代码
上面罗列的是 ES5
中通过 var
声明的情况。也许你会对情况2⃣️产生疑惑:我都给 message
赋值了啊,但是打印出 undefined
,这就有点尴尬了?
因为在js中 执行上下文 分为两个阶段,第一个阶段是 创建阶段
,第二个阶段才是 执行阶段
。
上面情况2⃣️的执行情况如下:
1. 创建阶段:
executionContextObj = { scopeChain: { ... }, variableObject: { message: undefined }, this: { ... } } 复制代码
2. 执行阶段:
executionContextObj = { scopeChain: { ... }, variableObject: { message: 'find a frontend job in Canton!' }, this: { ... } } 复制代码
详细的解析可以看下我之前翻译的一篇文章 JS的执行上下文和环境栈是什么? 。
上面讲到的是 var
,我们引入 ES6
的 let 和 const
来演示下:
# 情况7⃣️:let声明变量赋值 let message; console.log(message); // undefined # 情况8⃣️:let声明变量但是不赋值,在console运行之后 console.log(message); // Uncaught ReferenceError: Cannot access 'message' before initialization let message = 'find a frontend job in Canton!'; # 情况9⃣️:const声明变量但是不赋值,报语法错误 const message; console.log(message); // Uncaught SyntaxError: Missing initializer in const declaration 复制代码
let和const
改变了 var
命令会发生 变量提升 的现象,即变量可以在声明之前使用,值为 undefined
。它们改变了这种奇怪的现象,声明的变量一定要在声明之后使用,否则报错。
当然还有其他声明变量的方法,比如 function
命令等,这里不一一列举,只是探讨下 undefined
的值而已~
Null类型
Null
类型的值是 null
。从逻辑角度来看, null
值表示一个空对象指针。
如果定义的变量准备在将来用来保存对象,那么最好就是将变量初始化为 null
,而不是其他的数据值。这样,只要直接检查 null
值就可以知道相应的变量是否已经保存了一个对象的引用。如下面的例子:
if(car != null) { // 对car对象执行某些操作 } 复制代码
undefined
值是派生自 null
值的。虽然两者在 ==
比较时候是相等的,如下:
console.log(null == undefined); // true 复制代码
当变量不确定类型的时候,可以不用为变量赋值,也就是默认赋值 undefined
了。但是如果你知道你的变量要保存对象但是还没有真正保存对象的时候就要赋值 null
了。
Boolean类型
Boolean
类型在日常生活中使用频繁了,其值是 true
和 false
,对应我们口头的 是
和 否
。
将布尔值的 true
和 false
转换为数值的话,可以用 非0
和 0
数字表示。
console.log( 1 == true); // true console.log( 0 == false); // true 复制代码
如果是恒等的比较方式 ===
,那数字表示法是要凉凉的~
Number类型
Number
类型有二进制表示法,八进制表示法,十六进制表示法和十进制表示法。这里只讨论 十进制表示法
,因为在平常的开发中,用到十进制的情况居多:joy:
这个类型用来表示整数值和浮点数值(即带小数点的值)。
整数值的基本操作很是简单,而且没啥bug好说,除非不在 Number.MIN_VALUE
和 Number.MAX_VALUE
范围内。带小数点的还是要留意下的,比如:
let a = 13.04; let b = 2.5; console.log(a + b); // 15.54 console.log(a * b); // 32.599999999999994 console.log(a - b); // 10.54 复制代码
咦咦,真是让人尴尬:sweat_smile:,怎么上面代码中两个浮点数相乘会出现那么多位的数字啊,不是等于 32.6
吗?
所以在进行浮点数的运算的时候还是得慎重点,先转换成整数计算,之后再切换回去浮点数,比如上面的 a * b
可以考虑写成 (a * 100 * (b * 10))/1000
。
当你要判断一个值是否是数值,可以使用 isNaN
来表示,其返回一个布尔值,如下:
console.log(isNaN(NaN)); // true console.log(isNaN(10)); // false console.log(isNaN('10'); // false , '10'会被转化为10 console.log('blue'); // true , 不能转化为数值 console.log(true); // false, 可被转化为数值1 复制代码
还有将非数值转化为数值的三个方法: Number()、parseInt()和parseFloat()
。见名思义:
**Number() 是将传入的内容转换为数字(整数)或 NaN
。但是在转换字符串的时候比较复杂,一般用 parseInt()**居多。**parseFloat()**就是转化成浮点数的方法啦。
String类型
String
类型也就是字符串类型啦。
字符串类型包含一些特殊的 字符字面量 ,也叫 转义序列 ,用来表示 非打印字符串 。比如换行符 \n
啦。
在实际的开发中,我们需要将数字类型或对象类型转换成字符串类型,那么我们可以直接使用 toString()
方法进行操作啦。好吧,这api的东西大家都会用,就不说了:joy:
Symbol类型
Symbol
类型是 ES6
引入的新类型,为了防止对象中属性名冲突的问题。
Symbol
值通过 Symbol
函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol
类型。凡是属性名属于 Symbol
类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。
具体的看下阮一峰的es6入门中Symbol部分。
上面说到的是 6种 基本的数据类型,还有一种是引用类型。
引用类型
引用类型:当复制保存对象的某个变量时,操作的是对象的引用,但是在为对象添加属性时,操作的是实际的对象。引用类型值指那些可能有多个值构成的对象。
引用类型有这几种:Object、Array、RegExp、Date、Function、特殊的基本包装类型(String、Number、Boolean)以及单体内置对象(Global、Math)。
基本包装类型
这个有点好玩,咦?上面的基本数据类型都有 String、Number和Boolean
啦,怎么这里还有这些。是的,上面的基本类型是通过基本包装类型来创建的。如下:
var s1 = 'find a frontend job in Canton'; var s2 = s1.substring(2); 复制代码
上面的代码实际进行了下面的步骤:
(1)创建String类型的一个实例;
(2)在实例中调用指定的方法;
(3)销毁这个实例。
上面的三个步骤转化为代码如下:
var s1 = new String('find a frontend job in Canton'); var s2 = s1.substring(2); s1 = null; 复制代码
(正规)的引用类型和基本包装类型的主要区别就是对象的生存期。使用 new
操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中。而自动创建的基本包装类型的对象,则只存在于下一行代码的执行瞬间,然后立即被销毁。这意味着我们不能在运行时为基本类型值添加属性和方法。来看下下面的例子:
var s1 = 'find a frontend job in Canton'; s1.name = 'jia ming'; console.log(s1.name); // undefined 复制代码
只能通过基本包装类的原型来添加了,比如改写 toString
方法:
var s1 = 'find a frontend job in Canton'; String.prototype.toString = function() { console.log('my name is jia ming'); } console.log(s1.toString()); // my name is jia ming 复制代码
嗯~苦口婆心介绍了 javascript
的数据类型,那么下面才是重头戏。我们在实际的开发中,如何识别不同的数据类型呢?
数据类型判断
数据类型有上面的 7种 类型,其中基本类型是 Undefined、Null、Boolean、Number、String和Symbol
,还有一种引用类型。引用类型又包含比较多种的对象,比如 Object
、 Array
等。
我们首先想到的是通过 typeof
来判断,直接上代码来试下吧:
let symbol = Symbol('jia ming'); let str = 'find a frontend job in Canton!'; let flag = true; let height = 99; let job; let obj = null; console.log(typeof symbol); // symbol console.log(typeof str); // string console.log(typeof flag); // boolean console.log(typeof height); // number console.log(typeof job); // undefined console.log(typeof obj); // object 复制代码
嗯~很ok啦,对基本的数据类型都能判断到啦,这个 null
得到的结果是 object
,你可以当成特殊情况来处理啦 -- 无中生有,一生万物 嘛。
我们再来看下引用类型打印出来的是什么东东:blush:
let person = { name: 'jia ming', info: 'find a frontend job in Canton!', }; let arr = ['jia ming', 'find a frontend job in Canton!']; let reg = new RegExp('jia ming', 'g'); let date = new Date(); let fn = () => { return 'find a frontend job in Canton!'; } let math = Math.min(2, 4, 8); console.log(typeof person); // object console.log(typeof arr); // object console.log(typeof reg); // object console.log(typeof date); // object console.log(typeof fn); // function console.log(typeof math); // number 复制代码
咦咦~着实让人尴尬啊,这个为啥那么多object啊,我的小心脏:pensive:。我们只是简单通过 typeof
校验比较尴尬啊,我们换个思路,我们来结合 call
改变下上下文对象,改写一个方法进行判断,如下:
let person = { name: 'jia ming', info: 'find a frontend job in Canton!', }; let arr = ['jia ming', 'find a frontend job in Canton!']; let reg = new RegExp('jia ming', 'g'); let date = new Date(); function handleType(obj, type) { if(typeof obj === 'object') { return Object.prototype.toString.call(obj) === `[object ${type}]`; } return false; } console.log(handleType(person, 'Object')); // true console.log(handleType(arr, 'Array')); // true console.log(handleType(reg, 'RegExp')); // true console.log(handleType(date, 'Date')); // true 复制代码
美滋滋,可以实现区别判断的哈。可是上面的基本类型中null也是 object
啊,然后是Math类型的typeof也是 number
啊,这个你可以自己做下处理啦。这里就不考虑了~
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。