Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

javascript如何判断变量的数据类型 #7

Open
Array-Huang opened this issue Nov 15, 2019 · 0 comments
Open

javascript如何判断变量的数据类型 #7

Array-Huang opened this issue Nov 15, 2019 · 0 comments

Comments

@Array-Huang
Copy link
Owner

typeof

用法示例

var arr = [];
typeof arr;    //'object'
typeof(arr);    //'object'

typeof实际上是一个一元运算符,因此可以用上述代码所示的两种用法。

typeof所支持的数据类型

image

从上表可以看出,typeof支持的数据类型还是比较齐全的,除了俩比较特殊以外:

  • Null使用typeof返回object,这跟我们的认知还是有一定差距的,这是javascript的一个设计上的bug,ECMAScript 6中有提议修改此bug,但已经被否决了;不过只要加个逻辑非!运算符,就能把Null这种情况给排除了。
  • 除了function以外,其它具体的对象类型都无法判断出来。

typeof浏览器兼容性注意点

对正则表达式字面量的类型判断在某些浏览器中不符合标准:

typeof /s/ === 'function'; // Chrome 1-12 , 不符合 ECMAScript 5.1
typeof /s/ === 'object'; // Firefox 5+ , 符合 ECMAScript 5.1

IE 宿主对象是对象而不是函数

在 IE 6, 7 和 8 中,大多数的宿主对象是对象,而不是函数,例如:

typeof alert === 'object'

instanceof

用法示例

// 定义构造函数
function C(){} 
function D(){} 

var o = new C();

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

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

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

instanceof是一个二元运算符。

instanceof总结

  • javascript中的原生对象以及用户的自定义对象基本上都能利用instanceof识别出来,除了NullUndefined
  • instanceof无法区分开同一原型继承链:
function A(){
    //...
}

function B(){
    //...
}

function C(){
    //...
}

var a = new A();
B.prototype = a;

var b = new B();
C.prototype = b;

var c = new C();

c instanceof A;    //true
c instanceof B;    //true
c instanceof C;    //true

Object.prototype.toString.call

用法示例

function type(obj) {
  return Object.prototype.toString.call(obj).slice(8, -1);
}
type(1);    //"Number"
type("1");    //"String"
type(true);    //"Boolean"
type(undefined);    //"Undefined"
type(null);    //"Null"
type({});    //"Object"
type([]);    //"Array"
type(new Date);    //"Date"
type(/\d/);    //"RegExp"
type(function() {});    //"Function"

function Point(x, y) {
    //
}
type(new Point(1, 2));    //"Object"

用法解析

从以上用法示例可以看出,这个基于Object.prototype.toString.call封装好的函数用法跟typeof非常相似,但是在支持的数据类型上比typeof强多了,所有的javascript原生数据类型都能判断出来。遗憾的是,Object.prototype.toString.call也不是万能的方案:无法识别自定义的对象类型。
Object.prototype.toString.call实际上是返回这样形式的值:

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

因此只要用slice方法把数据类型“切”出来就成了。

constructor(构造函数)

用法示例

/*
* 获取对象构造函数名称
*/
function getConstructorName(obj){
    return obj && obj.constructor && obj.constructor.toString().match(/function\s*([^(]*)/)[1]; //利用obj && obj.constructor来判断null和undefined
}

用法解析

这是一种非常巧妙的判断数据类型的方法——利用构造函数判断数据类型,这是基于javascript的特性/规范:

  • 对象的构造函数名就是该数据类型。
  • NullUndefined外,所有的数据类型都是/可以转化为对象,而如果是对象,就肯定有构造函数。

特性

  1. 因为NullUndefined没有构造函数,因此不能用此方法来判断。
  2. 由于同一条原型继承链上的各个对象的构造函数都不一样,因此,此方法可以区分开继承链上的各个自定义数据类型。
function A(){
    //...
}

function B(){
    //...
}

function C(){
    //...
}

var a = new A();
B.prototype = a;

var b = new B();
C.prototype = b;

var c = new C();

getConstructorName(a);    //A
getConstructorName(b);    //B
getConstructorName(c);    //C

总结

以上这四种方法都有不同程度的缺陷,如果从实用性的角度来考虑,可以综合一下:

function type(obj) {console.dir(obj);
  if(!obj) {
    return Object.prototype.toString.call(obj).slice(8, -1);
  }
  return obj.constructor.toString().match(/function\s*([^(]*)/)[1];
}
var t = type(1) // t==="number"
var t = type(new Number(1)) // t==="number"
var t = type("abc") // t==="string"
var t = type(new String("abc")) // t==="string"
var t = type(true) // t==="boolean"
var t = type(undefined) // t==="undefined"
var t = type(null) // t==="null"
var t = type({}) // t==="object"
var t = type([]) // t==="array"
var t = type(new Date) // t==="date"
var t = type(/\d/) // t==="regexp"
var t = type(function(){}) // t==="function"

参考资料

typeof - JavaScript | MDN
instanceof - JavaScript | MDN

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant