js类型检测

typeof

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

语法

typeof operand 或者 typeof (operand)

描述

下表总结了typeof可能的返回值

类型结果
Undefined“undefined”
Null“object”
Boolean“boolean”
Number“number”
String"string "
Symbol (ECMAScript 6 新增)“symbol”
宿主对象(由JS环境提供)“Implementation-dependent”
函数对象([[Call]] 在ECMA-262条款中实现了)“function”
任何其他对象“object”

示例

// Numbers
typeof 37 === 'number';
typeof 3.14 === 'number';
typeof Math.LN2 === 'number';
typeof Infinity === 'number';
typeof NaN === 'number'; // 尽管NaN是"Not-A-Number"的缩写
typeof Number(1) === 'number'; // 但不要使用这种形式!

// Strings
typeof "" === 'string';
typeof "bla" === 'string';
typeof (typeof 1) === 'string'; // typeof总是返回一个字符串
typeof String("abc") === 'string'; // 但不要使用这种形式!

// Booleans
typeof true === 'boolean';
typeof false === 'boolean';
typeof Boolean(true) === 'boolean'; // 但不要使用这种形式!

// Symbols
typeof Symbol() === 'symbol';
typeof Symbol('foo') === 'symbol';
typeof Symbol.iterator === 'symbol';

// Undefined
typeof undefined === 'undefined';
typeof declaredButUndefinedVariable === 'undefined';
typeof undeclaredVariable === 'undefined'; 

// Objects
typeof {a:1} === 'object';

// 使用Array.isArray 或者 Object.prototype.toString.call
// 区分数组,普通对象
typeof [1, 2, 4] === 'object';

typeof new Date() === 'object';

// 下面的容易令人迷惑,不要使用!
typeof new Boolean(true) === 'object';
typeof new Number(1) === 'object';
typeof new String("abc") === 'object';

// 函数
typeof function(){} === 'function';
typeof class C{} === 'function'
typeof Math.sin === 'function';
typeof new Function() === 'function';

使用new 操作符号

// All constructor functions while instantiated with 'new' keyword will always be typeof 'object'
//所有使用new 和构造函数创建的对象 使用typeof  都会返回 ‘object’
var str = new String('String');
var num = new Number(100);

typeof str; // It will return 'object'
typeof num; // It will return 'object'
// But there is a exception in case of Function constructor of Javascript
// 只有一个例外 那就是 Function 构造函数
var func = new Function();

typeof func; // It will return 'function'

正则表达式

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

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

暂存死区

typeof undeclaredVariable === 'undefined';
typeof newLetVariable; let newLetVariable; // ReferenceError
typeof newConstVariable; const newConstVariable = 'hello'; // ReferenceError

IE 特别提示

在IE 6,7和8上,很多宿主对象是对象而不是函数。例如:

typeof alert === 'object'

instanceof

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

语法

object instanceof constructor
object: 要检测的对象.
constructor: 某个构造函数

描述

instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。

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

var o = new C();


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


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

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

C.prototype = {};
var o2 = new C();

o2 instanceof C; // true

o instanceof C; // false,C.prototype指向了一个空对象,这个空对象不在o的原型链上.

D.prototype = new C(); // 继承
var o3 = new D();
o3 instanceof D; // true
o3 instanceof C; // true 因为C.prototype现在在o3的原型链上

需要注意的是,如果表达式 obj instanceof Foo 返回true,则并不意味着该表达式会永远返回true,因为Foo.prototype属性的值有可能会改变,改变之后的值很有可能不存在于obj的原型链上,这时原表达式的值就会成为false。另外一种情况下,原表达式的值也会改变,就是改变对象obj的原型链的情况,虽然在目前的ES规范中,我们只能读取对象的原型而不能改变它,但借助于非标准的__proto__伪属性,是可以实现的。比如执行obj.proto = {}之后,obj instanceof Foo就会返回false了。

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

在浏览器中,我们的脚本可能需要在多个窗口之间进行交互。多个窗口意味着多个全局环境,不同的全局环境拥有不同的全局对象,从而拥有不同的内置类型构造函数。这可能会引发一些问题。比如,表达式 [] instanceof window.frames[0].Array 会返回false,因为 Array.prototype !== window.frames[0].Array.prototype,并且数组从前者继承。

起初,你会认为这样并没有意义,但是当你在你的脚本中开始处理多个frame或多个window以及通过函数将对象从一个窗口传到另一个窗口时,这就是一个有效而强大的话题。比如,实际上你可以通过使用 Array.isArray(myObj) 或者Object.prototype.toString.call(myObj) === "[object Array]"来安全的检测传过来的对象是否是一个数组。

比如检测一个Nodes在另一个窗口中是不是SVGElement,你可以使用myNode instanceof myNode.ownerDocument.defaultView.SVGElement

示例

演示String对象和Date对象都属于Object类型和一些特殊情况

下面的代码使用了instanceof来证明:String和Date对象同时也属于Object类型(他们是由Object类派生出来的)。

但是,使用对象文字符号创建的对象在这里是一个例外:虽然原型未定义,但instanceof Object返回true。

var simpleStr = "This is a simple string"; 
var myString  = new String();
var newStr    = new String("String created with constructor");
var myDate    = new Date();
var myObj     = {};
var myNonObj  = Object.create(null);

simpleStr instanceof String; // 返回 false, 检查原型链会找到 undefined
myString  instanceof String; // 返回 true
newStr    instanceof String; // 返回 true
myString  instanceof Object; // 返回 true

myObj instanceof Object;    // 返回 true, 尽管原型没有定义
({})  instanceof Object;    // 返回 true, 同上
myNonObj instanceof Object; // 返回 false, 一种创建对象的方法,这种方法创建的对象不是Object的一个实例

myString instanceof Date; //返回 false

myDate instanceof Date;     // 返回 true
myDate instanceof Object;   // 返回 true
myDate instanceof String;   // 返回 false

演示mycar属于Car类型的同时又属于Object类型

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
var mycar = new Car("Honda", "Accord", 1998);
var a = mycar instanceof Car;    // 返回 true
var b = mycar instanceof Object; // 返回 true

不是一个实例

要测试对象是否不是特定构造函数的实例,你可以这样做

if (!(mycar instanceof Car)) {
  // Do something, like mycar = new Car(mycar)
}

下面代码完全不同

if (!mycar instanceof Car)

这将永远是假的(!mycar将在instanceof之前被处理,所以你总是验证布尔值是否是Car的一个实例)。

安全检测

原因:当检测对象的原型时 instanceof 存在缺陷

  1. iinstanceof 在一个页面包含多个iframe时问题多多
  2. 无法确定某个对象是不是原生对象

function getType (value){
	return Object.prototype.toString.call(value)
}
//JavaScript 中一切都是对象,任何都不例外,对所有值类型应用 Object.prototype.toString.call() 方法结果如下:
getType('hello') // "[object String]"
getType(123) //"[object Number]"
getType(true) // "[object Boolean]"
getType(Symbol(1)) // "[object Symbol]"
getType(null) // "[object Null]"
getType() // "[object Undefined]"
getType({}) // "[object Object]"
getType(Date) //"[object Function]"
getType([])  //"[object Array]"
getType(new Date()) //"[object Date]"
getType(JSON) // "[object JSON]"

总结

  1. typeof 可以检测 除了 null、Object、Array 以外的数据类型
  2. instanceof 可以目标对象的原型的链是否包含某个构造函数
  3. Object.prototype.toString.call() 可以检测所有的数据类型比较好用。
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值