基本数据类型
- JavaScript有六中基本数据类型:
undefined、 null、boolean、number、sring、symbol
(ES6新增) - 基本数据类型可以用
typeof
来判断(null
除外,下文会说到) - 存储在栈中的简单数据段,方便频繁使用
- 不可变性(只是改变了变量的指向,变量是没有类型的,变量的值才有)
值的比较==
&===
前者会做类型的自动转化,只比较值,后者先比较类型,再比较值。
使用==
的情况,注意下面返回true
的情况:
null == undefined
, 0, +0, -0, "", false
之间的比较, !NaN
,注意"0", [], {}
返回true
有人一昧地批判在js中使用==
的情况,在我看来不然,有时候==
能为我们省去很多不必要的判断。
顺便一提:void
,在MDN中的定义是对给定的表达式进行求值,然后返回undefined
,比如:
void 1
//undefined
void "string"
//undefined
void {}
//undefined
void []
//undefined
...
因此,对于以下比较,结果总是返回true
:
undefined === void function(){} //true
===
返回true
,==
就自然不必说了。
null判断
js中,typeof
对null
的处理有问题:
typeof null //"object"
typeof null === "object" //true
这个bug存在已久,但是修复可能会产生更多的bug,设计太多的web系统。因此可能永远也不会修复了,我们需要用复合条件(null是唯一为假值的对象)来判断null
的类型:
var n = null;
!n && typeof n === "object"; //true
可调用对象function
typeof function(){}
//"function"
实际上function
是object
的一个"子类型",也叫可调用对象,其有一个内部属性call
使其可以被调用,我们平时使用其实是省略了call
的调用:
var a = function(){
console.log("func");
}
a.call(); // func
引用数据类型
- 引用类型统称为
object
对象,包括数组、对象和函数(上面已经提到过) - 可变性(对象的属性和方法是可以动态修改的)
- 同时保存在栈内存(地址)和堆内存(实体)
- 引用传递
类型检测
typeof
:只可比较基本类型(null
除外)和function
,但是对于未定义的变量,typeof
返回的结果是让人比较混乱的:
虽然这是javascript的一个安全机制,但是如果对于temp2能返回一个undeclared(未声明)结果更好var temp1; //undefined typeof temp1; //"undefined" typeof temp2; //"undefined"
instanceof
:测试的是对象在其原型链上是否存在构造函数的prototype
属性(这里我更愿意把instanceof
看作一个比较运算符)。因此存在以下弊端:
- 以继承的角度理解原型链的话,每个子对象都是父对象的实例。比如:
var a = function(){}; a instanceof Function; //true a instanceof Object; //true
- 判断的是对象的
__propo__
属性,字面量和实例化存在区别,导致结果错误:
null
和undefined
,所属类是Nul
l和Undefined
,但是浏览器在浏览器中无法访问这两个类。(报Null未定义的错误)
constructor
:功能与instanceof
类型,属于对象的属性,解决instanceof
的前两个弊端:
但是对于var b = 1; b.constructor === Number; //true var a = function(){}; a.constructor === Function; //true a.constructor === Object; //false
null
和undefined
仍然无法检测,找不到constructor
属性Object.prototype.toString.call()
:最准确的方式。对于typeof
返回object
的对象,内部都有一个Class
属性,但是无法直接访问。一般通过Object.prototype.toString.call()
来访问:Object.prototype.toString.call([]); //"[object Array]" Object.prototype.toString.call(/test/); //"[object RegExp]"
null
和undefined
呢,其内部属性[[Class]]
仍然是正确值:
那基本类型呢,同样,基本类型被自己的封装对象自动包装(boxing),所以内部属性Object.prototype.toString.call(null); //"[object Null]" Object.prototype.toString.call(undefined); //"[object Undefined]"
[[Class]]
也为正确结果:Object.prototype.toString.call('') ; // [object String] Object.prototype.toString.call(1) ; // [object Number] Object.prototype.toString.call(true) ; // [object Boolean]
参考文章:
《你不知道的javascript(中)》第1章 类型
JavaScript的数据类型及其检测