JavaScript基础专题之类型检测(十一)

我们都知道 JavaScript 语言的每一个值都属于某一种数据类型。
JavaScript 的数据类型,共有分为七种:

数值(number):整数和小数(比如1和3.14)
字符串(string):文本(比如Hello World)
布尔值(boolean):表示真伪的两个特殊值,即true(真)和false(假)
undefined:表示“未定义”或不存在,即由于目前没有定义,所以此处暂时没有任何值
null:表示空值,即此处的值为空。
对象(object):各种值组成的集合。
symbol:具有唯一性的特殊值

通常数值、字符串、布尔值这三种类型,合称为 原始类型(primitive type)的值,即它们是最基本的数据类型,不能再细分了。
对象则称为 合成类型(complex type)的值,因为一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器。至于 undefined 和 null,一般将它们看成两个特殊值。
对象是最复杂的数据类型,又可以分成三个子类型。

狭义的对象(object)
数组(array)
函数(function)

狭义的对象和数组是两种不同的数据组合方式,除非特别声明,本文的”对象“都特指狭义的对象。函数其实是处理数据的方法,JavaScript 把它当成一种数据类型,可以赋值给变量,这为编程带来了很大的灵活性,也为 JavaScript 的“函数式编程”奠定了基础。
检测类型
JavaScript中有三种方法,可以确定一个值到底是什么类型。

typeof
instanceof
Object.prototype.toString

typeof
根据 MDN 定义

typeof操作符返回一个字符串,表示未经计算的操作数的类型。

未经计算的操作数又是什么?
举个例子:
typeof 37 //‘number’

typeof NaN //‘number’

typeof “bla” //‘string’

typeof false //boolean

typeof Symbol(‘foo’) //‘symbol’;
复制代码undefined 返回 undefined 。
typeof undefind
//“undefined”
复制代码对象和数组还会返回objet
typeof window // “object”

typeof {} // “object”

typeof [] // “object”
复制代码上面代码中,空数组([])的类型也是object,这表示在 JavaScript 内部,数组本质上只是一种特殊的对象。
关于 instanceof 对象的类型区分。
var o = {};
var a = [];

o instanceof Array // false
a instanceof Array // true
复制代码所以,可以粗暴理解为未经计算的操作数是他的基本数据类型,但还是还有几个例外。
比如:
// 函数
typeof function(){} === ‘function’;
typeof class C{} === ‘function’
typeof Math.sin === ‘function’;
typeof new Function() === ‘function’;
复制代码funtion 并属于基本类型啊,为什么会返回function,大家都知道 function 应该属于 object 中的特殊类型。
在 JavaScript 之中,就将构造函数的未经计算的操作数设置为function了,所以这里比较特殊。
还有一个特殊的点,就是null
typeof null // “object”
复制代码null的类型是object,这是由于历史原因造成的。1995年的 JavaScript 语言第一版,只设计了五种数据类型(对象、整数、浮点数、字符串和布尔值),没考虑null,只把它当作object的一种特殊值。后来null独立出来,作为一种单独的数据类型,为了兼容以前的代码,typeof null返回object就没法改变了。
instanceof
MDN 是这么说的

instanceof运算符用于测试构造函数的prototype属性是否出现在对象的原型链中的任何位置

也就是 instanceof 这个方法会遍历原型链,去寻找是否具有该原型
举个例子
function chris(){}
function james(){}

var o = new chris();

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

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

o instanceof Object // true 原型链上也有Object
复制代码需要注意的是,如果表达式 obj instanceof Foo 返回true,则并不意味着该表达式会永远返回true,因为Foo.prototype属性的值有可能会改变,改变之后的值很有可能不存在于obj的原型链上,这时原表达式的值就会成为false。
举个例子
function chris(){}
function james(){}

var o = new chris();

o instanceof chris //true

chris.prototype = {};

o instanceof chris; // false,C.prototype指向了一个空对象,这个空对象不在o的原型链上.
复制代码toString
toString() 用来返回一个表示该对象的字符串,现在大多情况被用来类型检测,toString() 返回 “[object type]”,其中type是对象的类型
举个例子:
var toString = Object.prototype.toString;

toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(2); // [object Number]
toString.call([]); // [object Array]

toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]
复制代码我们发现 type 的类型既能返回包装类型,也能返回基本类型,是一个比较全面的类型检测方法。
null和undefined的区别
null 与 undefined 都可以表示“没有”,含义非常相似。将一个变量赋值为 undefined 或null,老实说,语法效果几乎没区别。
var a = undefined;
// 或者
var a = null;
复制代码上面代码中,变量a分别被赋值为 undefined 和 null,这两种写法的效果几乎等价。
在 if 语句中,它们都会被自动转为false,相等运算符(==)甚至直接报告两者相等
if (!undefined) {
console.log(‘undefined is false’);
}
// undefined is false

if (!null) {
console.log(‘null is false’);
}
// null is false

undefined == null
// true
复制代码上面代码可见,两者的行为是何等相似!像谷歌公司开发的 JavaScript 语言的替代品 Dart 语言,就明确规定只有 null,没有 undefined!
既然含义与用法都差不多,为什么要同时设置两个这样的值,这不是无端增加复杂度,令初学者困扰吗?这与历史原因有关。
1995年 JavaScript 诞生时,最初像 Java 一样,只设置了 null 表示”无”。根据 C 语言的传统,null可以自动转为0。
Number(null) // 0
5 + null // 5
复制代码上面代码中,null 转为数字时,自动变成0。
但是,JavaScript 的设计者 Brendan Eich,觉得这样做还不够。首先,第一版的 JavaScript 里面,null 就像在 Java 里一样,被当成一个对象,Brendan Eich 觉得表示“无”的值最好不是对象。其次,那时的 JavaScript 不包括错误处理机制,Brendan Eich 觉得,如果null自动转为0,很不容易发现错误。
因此,他又设计了一个 undefined。
在Number下的区别:null是一个表示“空”的对象,转为数值时为0;undefined是一个表示”此处无定义”的原始值,转为数值时为NaN。
Number(undefined) // NaN
5 + undefined // NaN
复制代码对于null和undefined,还可以这样理解。
null表示空值,即该处的值现在为空。调用函数时,某个参数未设置任何值,这时就可以传入 null,表示该参数为空。比如,某个函数接受引擎抛出的错误作为参数,如果运行过程中未出错,那么这个参数就会传入null,表示未发生错误。
var i
function f(i = null){
return i
}
f(i)//null
复制代码undefined表示“未定义”,下面是返回 undefined的典型场景。
// 变量声明了,但没有赋值
var i;
i // undefined

// 调用函数时,应该提供的参数没有提供,该参数等于 undefined
function f(x) {
return x;
}
f() // undefined

// 对象没有赋值的属性
var o = new Object();
o.p // undefined

// 函数没有返回值时,默认返回 undefined
function f() {}
f() // undefined
复制代码JavaScript基础专题系列
JavaScript基础专题之原型与原型链(一)
JavaScript基础专题之执行上下文和执行栈(二)
JavaScript基础专题之深入执行上下文(三)
JavaScript基础专题之闭包(四)
JavaScript基础专题之参数传递(五)
JavaScript基础专题之手动实现call、apply、bind(六)
JavaScript基础专题之类数组对象(七)
JavaScript基础专题之实现自己的new Object(八)
JavaScript基础专题之创建对象几种方式及优缺点(九
JavaScript基础专题之继承的实现及其优缺点(十)
如果有错误或者不严谨的地方,还请大伙给予指正。如果这片文章对你有所帮助或者有所启发,还请给一个赞,鼓励一下作者。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值