首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaScript数据类型判断

JavaScript数据类型判断

作者头像
闲花手札
发布2021-09-08 11:13:54
9090
发布2021-09-08 11:13:54
举报
文章被收录于专栏:闲花手札闲花手札

JavaScript数据类型判断

1. typeof

使用typeof判断数据类型

console.log(typeof  1) //number

console.log(typeof NaN) //number

console.log(typeof "1") //string

console.log(typeof true) //boolean

let s = Symbol()
console.log(typeof s) //Symbol

console.log(typeof undefined) //undefined

function islu(){
    console.log("this is a function!")
}
console.log(typeof islu) //function

let obj = {
    name: '闲花手札'
}
console.log(typeof obj) //object

console.log(typeof null) //object

let array = [0,1,2,3] //数组
console.log(typeof array) //object

  1. 使用typeof可以检测大部分的基本类型。但无法检测出来null,会认为是对象。
  2. NaN也会认为是number。
  3. 可以检测出函数,但是对象数组和对象无法区分。

2. instanceof

instanceof可以用来判断对象是否是某个类的实例。instanceof的实现原理出门左转查看手撕instanceof

简单说就是左边对象的原型(通过.__proto__访问)是否和右边对象的原型相等(通过.prototype访问),如果相等则返回true。

var arr = [1, 2, 3];
var date = new Date();
var fn= function () {
  alert(123);
};
console.log(arr instanceof Array);
console.log(date instanceof Date);
console.log(fn instanceof Function);
console.log(Function instanceof Object)
console.log(Object instanceof Function)

再来看另外一种情况:

在 a.html中定义了数组a:

// a.html
<script>
  var a = [1,2,3];
</script>

然后通过iframe引入main.html页面:

// main.html
<iframe src="a.html"></iframe>

<script>
  var frame = window.frames[0];
  var a = frame.a;
  console.log(a instanceof Array);  // false
  console.log(a.constructor === Array);  //false
  console.log(a instanceof frame.Array); // true
</script>

在main.html页面通过iframe获取到a页面的数组检测,发现a 不是 Array的实例对象,这是什么原因呢?

其实 iframe 之间不会共享原型链, 因为他们有独立的执行环境, 所以 frame a 中的数组 a 不会是本执行环境的实例对象.

3. constructor

使用构造函数判断类型:

var bool = true;
var num = 123;
var str = "Davie"
var arr = [1,2,3]
var obj = {name:"Davie"}
var fun = function(){}
var sy = Symbol("Davie")

function Person(){}
function Student(){
  Person.call(this)
}
var stu = new Student()


console.log(bool.constructor === Boolean);// true

console.log(num.constructor === Number);// true

console.log(str.constructor === String);// true

console.log(arr.constructor === Array);// true

console.log(obj.constructor === Object);// true

console.log(fun.constructor === Function);// true

console.log(sy.constructor === Symbol);// true

console.log(stu.constructor === Student);// true

console.log(stu.constructor === Person);// false
  • undefined和null没有contructor属性,所以constructor不能判断undefined和null
  • 使用constructor判断类型是不安全的,因为contructor的指向是可以改变的
arr.constructor = Object
console.log(arr.constructor === Object);// true

4. 特性嗅探

或者一些特有的方法,比如数组特有的sort,slice等:

console.log(typeof arr.sort === 'function')

但是这种方式也不是特别牢靠,因为很难保证其他对象里面没有这些方法。

5. 万能方法

在任何值上调用 Object 原生的 toString() 方法,都会返回一个 [object NativeConstructorName] 格式的字符串。 需要注意的是,它不能检测非原生构造函数的构造函数名。

function foo(){};
var div = document.createElement('div')

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

Object.prototype.toString.call(NaN); 	'[object Number]'

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

Object.prototype.toString.call(true); 	'[object Boolean]'

Object.prototype.toString.call(undefined); '[object Undefined]'

Object.prototype.toString.call(null); 	'[object Null]'

Object.prototype.toString.call(Symbol());'[object Symbol]'

Object.prototype.toString.call(foo);  '[object Function]'

Object.prototype.toString.call([1,2,3]); '[object Array]'

Object.prototype.toString.call({});				'[object Object]'

Object.prototype.toString.call(/\d+/);    "[object RegExp]"

Object.prototype.toString.call(div) ;			'[object HTMLDivElement]'

Object.prototype.toString.call((function() {
  return arguments;
})());    
"[object Arguments]"

Object.prototype.toString.call(new Error());     // => "[object Error]"

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

从上面的例子可以看到,Object.prototype.toString 方法能有效弥补typeof不能很好区分数组对象函数的短板。

每个类在内部都有一个 [[Class]] 属性,这个属性中就指定了上述字符串中的构造函数名。

Object.prototype.toString 的原理是当调用的时候, 就取值内部的 [[Class]] 属性值, 然后拼接成 ‘[object ‘ + [[Class]] + ‘]’ 这样的字符串并返回. 然后我们使用 call 方法来获取任何值的数据类型。

6. 检测函数

Array.isArray()

用于确定传递的值是否是一个Array。如果对象是Array,则返回true,否则为false。

Array.isArray([1, 2, 3]);  

判断是否是 DOM 元素

在实际项目里面, 有时或许我们需要判断是否是 DOM 元素对象, 那么在判断的时候利用的是 DOM 对象特有的 nodeType 属性:

isElement: function(obj){  return !!(obj && obj.nodeType === 1);}

判断是否是对象

isObject: function(obj){  var type = typeof obj;  return type === 'function' || typeof === 'object' && obj !== null;}

这里的对象是狭义的, 是通常所指的 key-value 型的集合, 或者是 function 函数并且不为 null.

判断是否是 arguments 对象

判断一个对象是不是 arguments 对象可以通过 Object.prototype.toString 来判断, 但是低版本的浏览器不支持, 他们返回的是 [object Object], 所以需要兼容:

isArguments: function(obj){  return Object.prototype.toString.call(obj) === '[object Arguments]' || (obj != null && Object.hasOwnProperty.call(obj, 'callee'));}

兼容做法原理是通过对象的 hasOwnProperty 方法来判断对象是否拥有 callee 属性从而判断是不是 arguments 对象.

isNaN()和Number.isNaN

isNaN函数可以检测某个值是否是NaN:

isNaN(NaN); // true

但是:

isNaN(undefined); // trueisNaN({}); // trueisNaN([]); // false

只要传入的参数不是数字,都会返回true,但是数组会返回false,所以任然无法很好进行区分。

ES6为了修正这个BUG,引入了Number.isNaN()

Number.isNaN(NaN); // true

Number.isNaN('A String'); // false

Number.isNaN(undefined); // false

Number.isNaN({}); // false

Number.isNaN(1); // false

Number.isNaN([]); // false

没有ES6的情况下,可以采用以下polyfill

if (!Number.isNaN) {
  Number.isNaN = function(n) {
    return (
      typeof n === "number" &&
      window.isNaN( n )
    );
  };
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-09-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • JavaScript数据类型判断
    • 1. typeof
      • 2. instanceof
        • 3. constructor
          • 4. 特性嗅探
            • 5. 万能方法
              • 6. 检测函数
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档