简单谈谈Javascript中类型的判断


Posted in Javascript onOctober 19, 2015

数据类型的判断有这么几种方式

1、一元运算符 typeOf

2、关系运算符 instanceof

3、constructor 属性

4、prototype属性

一、typeof

typeof的返回值有以下几种

类型 结构
Undefined "undefined"
Null "object" (见下方)
布尔值 "boolean"
数值 "number"
字符串 "string"
Symbol (ECMAScript 6 新增) "symbol"
宿主对象(JS环境提供的,比如浏览器) Implementation-dependent
函数对象 (implements [[Call]] in ECMA-262 terms) "function"
任何其他对象 "object"

简单粗暴的方法,直接看代码

// 以下代码在版本 Google Chrome 45.0.2454.101 m 中测试通过
// Numbers
console.log(typeof 37 === 'number');
console.log(typeof 3.14 === 'number');
console.log(typeof Math.LN2 === 'number');
console.log(typeof Infinity === 'number');
console.log(typeof NaN === 'number'); // 尽管NaN是"Not-A-Number"的缩写,意思是"不是一个数字"
console.log(typeof Number(1) === 'number'); // 不要这样使用!
 
// Strings
console.log(typeof "" === 'string');
console.log(typeof "bla" === 'string');
console.log(typeof (typeof 1) === 'string'); // console.log(typeof返回的肯定是一个字符串
console.log(typeof String("abc") === 'string'); // 不要这样使用!
 
// Booleans
console.log(typeof true === 'boolean');
console.log(typeof false === 'boolean');
console.log(typeof Boolean(true) === 'boolean'); // 不要这样使用!
 
// Symbols
console.log(typeof Symbol() === 'symbol');
console.log(typeof Symbol('foo') === 'symbol');
console.log(typeof Symbol.iterator === 'symbol');
 
// Undefined
console.log(typeof undefined === 'undefined');
console.log(typeof blabla === 'undefined'); // 一个未定义的变量,或者一个定义了却未赋初值的变量
 
// Objects 使用Array.isArray或者Object.prototype.toString.call方法可以从基本的对象中区分出数组类型
console.log(typeof {a:1} === 'object');
console.log(typeof [1, 2, 4] === 'object');
console.log(typeof /^[a-zA-Z]{5,20}$/ === 'object');
console.log(typeof {name:'wenzi', age:25} === 'object');
console.log(typeof null === 'object');//true
 
// 下面的容易令人迷惑,不要这样使用!
console.log(typeof new Boolean(true) === 'object');
console.log(typeof new Number(1) === 'object');
console.log(typeof new Date() === 'object');
console.log(typeof new String("abc") === 'object');
console.log(typeof new Error() === 'object');
 
// 函数
console.log(typeof function(){} === 'function');
console.log(typeof Math.sin === 'function');

typeof 只能检查出来以上7几种类型

二、instanceof

instanceof 运算符用于识别正在处理的对象的类型,要求开发者明确地确认对象为某特定类型

1、instanceof 和 constructor 没有关系

var A = function() {};
A.prototype = {};
 
var B = {};
console.log(A.constructor);//function Function() { [native code] }
console.log(B.constructor);//function Object() { [native code] }
 
var a = new A();
A.prototype = {};
 
var b = new A();
b.constructor = A.constructor;
 
console.log(a.constructor === A);//false
console.log(a.constructor);//function Object() { [native code] }
console.log(typeof A);//function Object() { [native code] }
 
console.log(a.constructor === b.constructor);//false
console.log(b.constructor);//function Function() { [native code] }
 
console.log(a instanceof A);//false
console.log(b instanceof A);//true

2、instanceof又叫关系运算符,可以用来判断某个构造函数的prototype属性是否存在另外一个要检测对象的原型链上

var str = new String("hello world");
console.log(str instanceof String);//true
console.log(String instanceof Function);//true
console.log(str instanceof Function);//false

第三次输出为什么会返回false呢 ?原文地址:Javascript中一个关于instanceof的问题

//表达式一的指向
console.log(str.__proto__ === String.prototype);//true
console.log(str instanceof String); //true
 
//表达式二的指向
console.log(String .__proto__ === Function.prototype);//true
console.log(String instanceof Function);//true
 
//表达式三的指向
console.log(str .__proto__ === String.prototype);//true
console.log(str .__proto__.__proto__ === String.prototype.__proto__);//true
console.log(str .__proto__.__proto__ === Object.prototype);//true
console.log(str .__proto__.__proto__.__proto__ === null);//true
console.log(str instanceof Object);//true
console.log(str instanceof Function);//false

 再看一个复杂的用法

console.log(Object instanceof Object);//true
console.log(Function instanceof Function);//true
console.log(Number instanceof Number);//false
console.log(String instanceof String);//false
 
console.log(Function instanceof Object);//true
 
console.log(Foo instanceof Function);//true
console.log(Foo instanceof Foo);//false

为什么,这是为什么呢,要搞明白以下含义

1、语言规范中是如何定义这个运算符的

2、JavaScript 原型继承机制

Object instanceof Object

// 为了方便表述,首先区分左侧表达式和右侧表达式
ObjectL = Object, ObjectR = Object;
console.log(ObjectL instanceof ObjectR);//true

 

// 下面根据规范逐步推演
console.log(ObjectL.__proto__ === Function.prototype); //true
console.log(ObjectL.__proto__.__proto__ === Object.prototype);//true

Function instanceof Function

FunctionL = Function, FunctionR = Function;
console.log(FunctionL instanceof FunctionR);//true
console.log(FunctionL.__proto__ === Function.prototype); //true

Foo instanceof Foo

function Foo(){}
var foo = new Foo();
FooL = Foo, FooR = Foo;
console.log(FooL instanceof FooR);//false
console.log(FooL.__proto__ === Function.prototype );//true
console.log(FooL.__proto__.__proto__ === Object.prototype );//true
console.log(FooL.__proto__.__proto__.__proto__ === null );//true

 instanceof 在 Dojo 继承机制中的应用

在 JavaScript 中,是没有多重继承这个概念的,就像 Java 一样。但在 Dojo 中使用 declare 声明类时,是允许继承自多个类的

dojo.declare("Aoo",null,{});
dojo.declare("Boo",null,{});
dojo.declare("Foo",[Aoo,Boo],{});
 
var foo = new Foo();
console.log(foo instanceof Aoo);//true
console.log(foo instanceof Boo);//false
 
console.log(foo.isInstanceOf(Aoo));//true
console.log(foo.isInstanceOf(Boo));//true

instanceof和多全局对象(多个frame或多个window之间的交互)

在浏览器中,我们的脚本可能需要在多个窗口之间进行交互。多个窗口意味着多个全局环境,不同的全局环境拥有不同的全局对象,从而拥有不同的内置类型构造函数。这可能会引发一些问题。比如,表达式 [] instanceof window.frames[0].Array 会返回false,因为 Array.prototype !== window.frames[0].Array.prototype,因此你必须使用 Array.isArray(myObj) 或者Object.prototype.toString.call(myObj) === "[object Array]"来判断myObj是否是数组。

// 以下代码在版本 Google Chrome 45.0.2454.101 m 中测试通过
// Numbers
console.log(37 instanceof Number);//false
console.log( 3.14 instanceof Number);.//false
console.log( Math.LN2 instanceof Number);//false
console.log( Infinity instanceof Number);//false
console.log( NaN instanceof Number); // false尽管NaN是"Not-A-Number"的缩写,意思是"不是一个数字"
console.log( Number(1) instanceof Number); // false不要这样使用!
 
// Strings
console.log( "" instanceof String);// false
console.log( "bla" instanceof String);// false
console.log( ( 1) instanceof String); // falseconsole.log(返回的肯定是一个字符串
console.log( String("abc") instanceof String); // false 不要这样使用!
 
// Booleans
console.log( true instanceof Boolean);// false
console.log( false instanceof Boolean);// false
console.log( Boolean(true) instanceof Boolean); //false 不要这样使用!
 
// Symbols
console.log( Symbol() instanceof Symbol);// false
console.log( Symbol("foo") instanceof Symbol);// false
console.log( Symbol.iterator instanceof Symbol);// false
 
// Undefined
var blabla;
//console.log( undefined instanceof Undefined);// Uncaught ReferenceError: Undefined is not defined
//console.log( blabla instanceof Undefined); // Uncaught ReferenceError: Undefined is not defined
console.log( undefined instanceof Object);// false
console.log( blabla instanceof Object);// false
 
// Objects 使用Array.isArray或者Object.prototype.toString.call方法可以从基本的对象中区分出数组类型
console.log( {a:1} instanceof Object);//true
console.log( [1, 2, 4] instanceof Object);//true
console.log( /^[a-zA-Z]{5,20}$/ instanceof Object);//true
console.log( {name:'wenzi', age:25} instanceof Object);//true
console.log( null === Object);//false
 
// 下面的容易令人迷惑,不要这样使用!
console.log( new Boolean(true) instanceof Object);//true
console.log( new Number(1) instanceof Object);//true
console.log( new Date() instanceof Object);//true
console.log( new String("abc") instanceof Object);//true
console.log( new Error() instanceof Object);//true
 
// 函数
console.log( function(){} instanceof Function );//true
console.log( Math.sin instanceof Function);//true

注意:undefined和null是检测的Object类型,因为js中没有Undefined和Null的这种全局类型,number, string和boolean无法检测出它的类型

三、constructor

在使用instanceof检测变量类型时,我们是检测不到number, 'string', bool的类型的。因此,我们需要换一种方式来解决这个问题

Object.prototype.constructor返回一个指向创建了该对象原型的函数引用。需要注意的是,该属性的值是那个函数本身,而不是一个包含函数名称的字符串。对于原始值(如1,true 或 "test"),该属性为只读,所有对象都会从它的原型上继承一个 constructor 属性

constructor本来是原型对象上的属性,指向构造函数。但是根据实例对象寻找属性的顺序,若实例对象上没有实例属性或方法时,就去原型链上寻找,因此,实例对象也是能使用constructor属性的

function Person(){
 
}
var Tom = new Person();
 
console.log(Tom.constructor === Person);//true

不过要注意,constructor属性是可以被修改的,会导致检测出的结果不正确

function Person(){
 
}
function Student(){
 
}
Student.prototype = new Person();
var John = new Student();
console.log(John.constructor==Student); // false
console.log(John.constructor==Person); // true

改变这个对象的constructor属性的值

function Type() { };
 
var types = [
  new Array,
  [],
  new Boolean,
  true,    // remains unchanged
  new Date,
  new Error,
  new Function,
  function(){},
  Math, 
  new Number,
  1,      // remains unchanged
  new Object,
  {},
  new RegExp,
  /(?:)/,
  new String,
  "test"    // remains unchanged
];
 
for(var i = 0; i < types.length; i++) {
  types[i].constructor = Type;
  types[i] = [ types[i].constructor, types[i] instanceof Type, types[i].toString() ];
};
 
console.log( types.join("\n") );

除了undefined和null,其他类型的变量均能使用constructor判断出类型

四、万能的Object.prototype.toString.call

使用toString()方法来检测对象类型

function Type() { };
 
var toString = Object.prototype.toString;
console.log(toString.call(new Date) === '[object Date]');//true
console.log(toString.call(new String) ==='[object String]');//true
console.log(toString.call(new Function) ==='[object Function]');//true
console.log(toString.call(Type) ==='[object Function]');//true
console.log(toString.call('str') ==='[object String]');//true
console.log(toString.call(Math) === '[object Math]');//true
console.log(toString.call(true) ==='[object Boolean]');//true
console.log(toString.call(/^[a-zA-Z]{5,20}$/) ==='[object RegExp]');//true
console.log(toString.call({name:'wenzi', age:25}) ==='[object Object]');//true
console.log(toString.call([1, 2, 3, 4]) ==='[object Array]');//true
//Since JavaScript 1.8.5
console.log(toString.call(undefined) === '[object Undefined]');//true
console.log(toString.call(null) === '[object Null]');//true

附上判断函数 Javascript中的数据类型知多少

五、jquery的实现  jquery: "1.8.2",

jquery中提供了一个$.type的接口,看看代码

var m = Object.prototype.toString //501行
 
E = {};//512行
 
isFunction: function(a) { //645行
  return p.type(a) === "function"
},
isArray: Array.isArray || function(a) {
  return p.type(a) === "array"
}
,
isWindow: function(a) {
  return a != null && a == a.window
},
isNumeric: function(a) {
  return !isNaN(parseFloat(a)) && isFinite(a)
},
type: function(a) {
  return a == null ? String(a) : E[m.call(a)] || "object"
},
isPlainObject: function(a) {
  if (!a || p.type(a) !== "object" || a.nodeType || p.isWindow(a))
    return !1;
  try {
    if (a.constructor && !n.call(a, "constructor") && !n.call(a.constructor.prototype, "isPrototypeOf"))
      return !1
  } catch (c) {
    return !1
  }
  var d;
  for (d in a)
    ;
  return d === b || n.call(a, d)
},
isEmptyObject: function(a) {
  var b;
  for (b in a)
    return !1;
  return !0
},

可以看出来,jquery中就是用Object.prototype.toString.call实现的

Javascript 相关文章推荐
jQuery学习笔记之jQuery的动画
Dec 22 Javascript
jQuery之end()和pushStack()使用介绍
Feb 07 Javascript
javascript字符串替换及字符串分割示例代码
Dec 12 Javascript
js判断手机浏览器操作系统和微信浏览器的方法
Apr 30 Javascript
AngularJS过滤器filter用法实例分析
Nov 04 Javascript
原生JS实现导航下拉菜单效果
Nov 25 Javascript
JS简单判断字符在另一个字符串中出现次数的2种常用方法
Apr 20 Javascript
vue input 输入校验字母数字组合且长度小于30的实现代码
May 16 Javascript
js tab栏切换代码实例解析
Sep 03 Javascript
javascript的惯性运动实现代码实例
Sep 07 Javascript
JS实现横向轮播图(初级版)
Jun 24 Javascript
Vue +WebSocket + WaveSurferJS 实现H5聊天对话交互的实例
Nov 18 Vue.js
AngularJS 实现按需异步加载实例代码
Oct 18 #Javascript
学习javascript的闭包,原型,和匿名函数之旅
Oct 18 #Javascript
Javascript中的数据类型之旅
Oct 18 #Javascript
谈谈JavaScript自定义回调函数
Oct 18 #Javascript
JS实现的网页背景闪电闪烁效果代码
Oct 17 #Javascript
JavaScript实现点击按钮切换网页背景色的方法
Oct 17 #Javascript
JavaScript实现的背景自动变色代码
Oct 17 #Javascript
You might like
一次编写,随处运行
2006/10/09 PHP
destoon实现调用图文新闻的方法
2014/08/21 PHP
php中switch与ifelse的效率区别及适用情况分析
2015/02/12 PHP
php+jquery+html实现点击不刷新加载更多的实例代码
2016/08/12 PHP
PHP isset()与empty()的使用区别详解
2017/02/10 PHP
Yii2中hasOne、hasMany及多对多关联查询的用法详解
2017/02/15 PHP
PHP性能测试工具xhprof安装与使用方法详解
2018/04/29 PHP
PHP连接sftp并下载文件的方法教程
2018/08/26 PHP
地址栏上的一段语句,改变页面的风格。(教程)
2008/04/02 Javascript
番茄的表单验证类代码修改版
2008/07/18 Javascript
用JavaScript编写COM组件的步骤
2009/03/17 Javascript
JQuery解析HTML、JSON和XML实例详解
2014/03/29 Javascript
JavaScript实现的石头剪刀布游戏源码分享
2014/08/22 Javascript
浅析javascript中函数声明和函数表达式的区别
2015/02/15 Javascript
JavaScript forEach()遍历函数使用及介绍
2015/07/08 Javascript
jQuery无刷新上传之uploadify3.1简单使用
2016/06/18 Javascript
给easyui datebox扩展一个清空的实例
2016/11/09 Javascript
如何在vue中使用ts的示例代码
2018/02/28 Javascript
Vue之mixin全局的用法详解
2018/08/22 Javascript
浅谈angular表单提交中ng-submit的默认使用方法
2018/09/30 Javascript
layui在form表单页面通过Validform加入简单验证的方法
2019/09/06 Javascript
[46:20]DOTA2-DPC中国联赛 正赛 PSG.LGD vs LBZS BO3 第二场 1月22日
2021/03/11 DOTA
python获取当前目录路径和上级路径的实例
2018/04/26 Python
python 字符串和整数的转换方法
2018/06/25 Python
Python文件操作函数用法实例详解
2019/12/24 Python
在 Python 中接管键盘中断信号的实现方法
2020/02/04 Python
python将YUV420P文件转PNG图片格式的两种方法
2021/01/22 Python
基于HTML5陀螺仪实现ofo首页眼睛移动效果的示例
2017/07/31 HTML / CSS
一个J2EE项目团队的主要人员组成是什么
2012/06/04 面试题
客服专员岗位职责范本
2013/11/29 职场文书
财务总经理岗位职责
2014/02/16 职场文书
个人专业技术总结
2015/03/05 职场文书
导师工作推荐信
2015/03/27 职场文书
党委工作总结2015
2015/04/27 职场文书
员工年度工作总结2015
2015/05/18 职场文书
Unity连接MySQL并读取表格数据的实现代码
2021/06/20 MySQL