该文章主要用来介绍JavaScript中常用的一些对象检测判断方法,整理资源来自书本和网络,如有错误或说明不详之处,望评论提出,本菜定提名感谢……(本文章知识比较基础,大牛请提些意见再绕道,三克油^_^)

1.检测原始值(typeof)
结论:
JavaScript五种原始类型:字符串、数字、布尔值、undefined、null。其中前四种的类型检测请使用 typeof ,最后一种 null 的类型检测请使用恒等(===)或者非恒等(!==)运算符。
原因:
typeof 运算符返回一个表示值的类型的字符串,
如:
typeof(字符串) => "string"
typeof(数字) => "number"
typeof(布尔值) => "boolean"
typeof(undefined) => "undefined" typeof 的基本语法是:
typeof 变量 //推荐语法
也可以使用:
typeof(变量) //虽然这是合法的,但这让 typeof 看起来更像是函数,而非运算符。 typeof 检测四种原始类型做法: //检测字符串
if(typeof mytype === "string"){
……
}
// 检测数字
if(typeof mytype === "number"){
……
}
// 检测布尔值
if(typeof mytype === "boolean" && mytype){
……
}
// 检测 undefined
if(typeof mytype ==="undefined"){
……
} 最后一种是对 null 的检测,因为简单地把一个对象和 null 进行比较,不足以判断其值的类型是否合法,比如:
if(items !== null){//不好的做法
items.sort();//如果items不是数组,该执行将报错
items.foreach(function(item){
//执行一些逻辑
})
}
其实,items 是一个数组,但是仅仅通过和 null 比较,不足以判断其是合法的数组类型,因为tiems 也可以是1、字符串、对象等,都和 null 不相等。
因此,只有在你明确预见某个值真的是 null ,则可以直接和 null 比较,比如:
var element = document.getElementById("my-div");
if(element !== null){//因为 getElementById 要么返回节点,要么返回 null
……
}
特别提示:typeof(null) 返回 "object",这被认为是标准规范的严重"bug",所以一定要杜绝使用 typeof 检测 null类型。
2.检测引用值(instanceof)
结论:
JavaScript引用类型有:Object、Array、Date、Error、RegExp 等等。检测引用类型的最好方法是使用 instanceof 运算符(Array 无法跨帧,需另讲)。
原因:
不能使用 typeof 检测引用类型,因为所有对象都会返回"object":
typeof {} => "object"
typeof [] => "object"
typeof new Date() => "object"
typeof new RegExp() => "object"
所以不能用 typeof 来检测。
instanceof 意思是"实例",也就是说只要一个变量是某个对象(引用类型)的实例,则返回 true,如:
// 检测日期
if(value instanceof Date){
……
}
// 检测正则表达式
if(value instanceof RegExp){
……
}
// 检测 Error
if(value instanceof Error){
……
} 另外,instanceof 还可以检测原型链,比如,所有对象都继承自 Object,所以 value instanceof Object 都会返回 true。
如:
var now = new Date();
now instanceof Object => true
now instanceof Date => true
3.检测函数(typeof)
结论:
检测函数使用 typeof;而IE8及其更早浏览器中检测DOM的方法时(document.getElementById/document.createElement/document.getElementsByTageName……)时使用 in 运算符。
原因:
function 也是引用类型,虽然
function myFun(){}
console.log(myFun instanceof Function)// true
返回true,但是每个函数中都有自己的 Function 构造方法,如果跨帧(frame)使用,在另一个帧中就不会识别另一个帧中的实例对象。
建议使用 typeof,返回"function".
function myFun(){}
console.log(typeof myFun === "function")// true(推荐使用) 另外,在IE8和更早版本中,使用typeof 检测document.getElementById/document.createElement/document.getElementsByTageName……时,返回 "object"
推荐使用:
if("querySelectorAll" in document){
images=document.querySelectorAll('img');
}
虽然不是最理想的,如果想在IE8及其更早版本中使用,这无疑是最安全的。其他情况则使用 typeof 检测是否为函数。
4.检测数组(Array.isArray + Object.prototype.toString.call(value) === '[object Array]' )
结论:
function isArray(value){
if(typeof Array.isArray === 'function'){
return Array.isArray(value);
}else{
return Object.prototype.toString.call(value) === '[object Array]';
}
}
原因:
最开始检测数组采用“鸭式辨型”:
function isArray(value){
return typeof value.sort === 'function';
}
因为目前只有数组才有排序 sort() 方法,但是如果传递的 value 包含自定义的 sort(),该方法就会失效。 目前比较流行的方法是:
function isArray(value){
return Object.prototype.toString.call(value) === '[object Array]';
}
该方法是基于 toString()方法在所有浏览器中都会返回标准的字符串结果。对于数组则返回 '[object Array]'。
由于ECMAScript5正式引用了 Array.isArray() 方法,IE9+、FireFox4+、Safari 5+、Opera 10.5+、Chrome都支持了该方法,所以
推荐使用:
function isArray(value){
if(typeof Array.isArray === 'function'){
return Array.isArray(value);
}else{
return Object.prototype.toString.call(value) === '[object Array]';
}
}
5.检测属性(in 或 hasOwnProperty)
结论:
判断属性是否存在最好的方法是使用 in 运算符。只有需要判断实例属性时才会用到 hasOwnProperty。
原因:
有时候检测属性会这样使用:
//不好的写法:检测假值
if(object[propertyName]){
……
}
//不好的写法:和 null 比较
if(object[propertyName] != null){
……
}
//不好的写法:和 undefined 比较
if(object[propertyName] != undefined){
……
}
以上的代码,是通过获取该属性值来判断是否包含该属性,但是如果该属性的值本身就是 false、0、""、null、undefined呢?是不是就不管用了!
所以,最好的办法是使用 in 运算符。in 仅仅只会判断属性是否存在,而不会获取属性值。如果只需要判断实例属性可以用 hasOwnProperty。 in vs hasOwnProperty:
in:判断对象(包括原型链)是否具备指定的属性。(有中说法叫:判断实例对象属性、或者继承自对象的原型的属性)
hasOwnProperty:判断对象自身(不包括原型链)是否具有指定名称的属性。 (有种说法叫:仅用于判断实例属性) 上面说明很晦涩,继续看就明白了:
先来对比几个关键词:
实例属性 vs 原型的属性 vs 静态属性:
先看代码:
function Man(myname, age) {
//定义实例属性
this.myname = myname;
this.age = age;
}
//定义静态属性
Man.sex = '男';
//定义原型属性
Man.prototype.phone = '123456'; document.writeln(Man.sex);//男
document.writeln(Man.myname);//undefined
document.writeln(Man.age);//undefined
document.writeln(Man.phone);//undefined
document.writeln(Man.prototype.phone);// var man = new Man("Tom", 24);
document.writeln(man.myname);//Tom
document.writeln(Man.sex);//男
document.writeln(man.age);//
document.writeln(man.phone);//
代码总结:
实例属性:构造函数中定义的属性,类似C#/java中 只能通过 new 实例化一个对象后才能访问到的属性。
原型属性:属于原型链中的属性,通过prototype扩展的属性。
静态属性:在构造函数外,直接通过【对象名.新属性】追加的属性叫静态属性,类似C#/java中的 static 属性。

     另外,
     (1)构造函数中定义的属性和方法要比原型中定义的属性和方法的优先级高,如果定义了同名称的属性和方法,构造函数中的将会覆盖原型中的。
     (2)把方法写在原型中比写在构造函数中消耗的内存更小,因为在内存中一个类的原型只有一个,写在原型中的行为可以被所有实例共享,实例化的时候并不会在实例的内存中再复制一份。而写在类中的方法,实例化的时候会在每个实例中再复制一份,所以消耗的内存更高。所以没有特殊原因,我们一般把属性写到类中,而行为写到原型中。
        言归正传,
in 和 hasOwnProperty 如何使用呢,看代码:
function Site(){
//判断是否有这些实例属性方法:s.hasOwnProperty("name/url...") 或 "name/url..." in s
this.name = "CodePlayer";
this.url = "http://www.365mini.com/"; this.sayHello = function(){
document.writeln("欢迎来到" + this.name);
};
} Site.ower='Alec';//判断是否有静态属性方法:Site.hasOwnProperty('ower') 或 "ower" in Site var obj = {
//判断是否有这些原型属性方法:"engine/sayHi.." in s (这些对象是s原型链中的对象,如果该obj又有更高级原型域,同样可以使用 '属性名' in s 判断)
engine: "PHP",
sayHi: function(){
document.writeln("欢迎访问" + this.url);
}
};
Site.prototype = obj; var s = new Site();
document.writeln( s.hasOwnProperty("name") ); // true
document.writeln( s.hasOwnProperty("sayHello") ); // true
// 以下属性继承自原型链,因此为false
document.writeln( s.hasOwnProperty("engine") ); // false
document.writeln( s.hasOwnProperty("sayHi") ); // false
document.writeln( s.hasOwnProperty("toString") ); // false
//静态属性只能通过原型对象判断,无法用实例对象判断
document.writeln( s.hasOwnProperty("ower") ); // false
document.writeln( Site.hasOwnProperty('ower') );//true // 想要查看对象(包括原型链)是否具备指定的属性,可以使用in操作符
document.writeln( "url" in s ); // true
document.writeln( "sayHello" in s ); // true
document.writeln( "engine" in s ); // true
document.writeln( "sayHi" in s ); // true
document.writeln( "toString" in s ); // true document.writeln( "ower" in s ); // false
document.writeln( "ower" in Site ); // true 静态属性需要使用原型对象名访问
    附图一张,进一步说明:
     看到这里,应该对 in 和 hasOwnProperty 的使用场景有所了解了吧?
最后,需要特别说明的一点是:
IE8及其更早的IE版本中,DOM对象并非继承自Object,因此,无法使用hasOwnProperty()方法,换句话说,如果你在调用DOM对象的hasOwnProperty()方法之前需要先检测器是否存在(假如你已经知道对象不是DOM,就可以省略此步骤)
//对于所有非DOM对象来说,这是好的写法
if(object.hasOwnProperty('related')){
……
}
//如果你不确定是否为DOM对象,则这样写是好的
if('hasOwnProperty' in object && object.hasOwnProperty('related')){
……
}
因为IE浏览器存在此问题,在判断实例对象是否存在时,我更倾向于使用 in运算符,只有在需要判断实例属性时才会用到hasOwnProperty()。

看到这里,说明你是个善良的人,非常感谢!如有错误之处,请留言讨论,共同进步……tks!

参考资料:

《编写可维护的JavaScript》

http://www.365mini.com/page/javascript-hasownproperty.htm

http://www.jb51.net/article/20236.htm

http://blog.sina.com.cn/s/blog_54d1f65b0101dfv3.html

JavaScript进阶内容笔记1:各种对象类型判断的更多相关文章

  1. JavaScript进阶内容1:各种对象类型判断

    该文章主要用来介绍JavaScript中常用的一些对象检测判断方法,整理资源来自书本和网络,如有错误或说明不详之处,望评论提出,本菜定提名感谢……(本文章知识比较基础,大牛请提些意见再绕道,三克油^_ ...

  2. JavaScript进阶内容——DOM详解

    JavaScript进阶内容--DOM详解 当我们已经熟练掌握JavaScript的语法之后,我们就该进入更深层次的学习了 首先我们思考一下:JavaScript是用来做什么的? JavaScript ...

  3. JavaScript进阶内容——BOM详解

    JavaScript进阶内容--BOM详解 在上一篇文章中我们学习了DOM,接下来让我们先通过和DOM的对比来简单了解一下BOM 首先我们先来复习一下DOM: 文档对象模型 DOM把文档当作一个对象来 ...

  4. JavaScript进阶内容——jQuery

    JavaScript进阶内容--jQuery 我们在前面的文章中已经掌握了JavaScript的全部内容,现在让我们了解一下JavaScript库 这篇文章主要是为了为大家大致讲解JavaScript ...

  5. js对象类型判断工具

    对象类型判断工具 /** *类功能:对象类型判断工具 **/ var TypeUtil = { /** *方法说明:是否是数组 **/ isArray: function (obj) {//是否是数组 ...

  6. JavaScript高级内容笔记:原型链、继承、执行上下文、作用域链、闭包

    最近在系统的学习JS深层次内容,并稍微整理了一下,作为备忘和后期复习,这里分享给大家,希望对大家有所帮助.如有错误请留言指正,tks. 了解这些问题,我先一步步来看,先从稍微浅显内容说起,然后引出这些 ...

  7. javascript高级编程笔记06(面相对象2)

    1)  构造函数模式 es中的构造函数可以用来创建特定类型的对象,像Object和Array这样的原生构造函数,在运行时会自动出现在执行环境中,此外,也可以创建自定义的构造函数,从而定义自定义对象类型 ...

  8. 【JavaScript】Object.prototype.toString.call()进行类型判断

    权声明:本文为博主原创文章,未经博主允许不得转载. op = Object.prototype, ostring = op.toString, ... function isFunction(it)  ...

  9. JS框架设计之对象类型判断一种子模块

    Javascript有两套数据类型,一套是基础数据类型,一套是对象数据类型.基础数据类型包括5种基本数据类型,分别是null,bool,undefined,number,string,也叫简单数据类型 ...

随机推荐

  1. 关于C#我今天的六个小时

    嘿嘿,今天周六啦,我们是自由学习啦,于是还记得前几天纠结的事情,还有好多不太熟悉的题目那,于是今天就找出来练习下拉,而且这些题目在老师给我们复习时间也给我们讲解过啦,这样一来应该做起来还是容易点的啦, ...

  2. iOS 录音功能的实现

    这两天也调了一下ios的录音,原文链接:http://www.iphoneam.com/blog/index.php?title=using-the-iphone-to-record-audio-a- ...

  3. cocos2dx游戏--欢欢英雄传说--添加动作

    添加完人物之后接着给人物添加上动作.我们为hero添加4个动作:attack(由3张图片构成),walk(由2张图片构成),hit(由1张图片构成),dead(由1张图片构成):同样,为enemy添加 ...

  4. pycharm激活地址

    http://elporfirio.com:1017 http://idea.iteblog.com/key.php

  5. c++中new/operator new/placement new

    1. new/delete c++中的new(和对应的delete)是对堆内存进行申请和释放,且两个都不能被重载. 2. operator new/operator delete c++中如果想要实现 ...

  6. 日记整理---->2016-11-23

    这里放一些jquery的学习知识.可能从一开始就是我一个人单枪匹马,来年不求并肩作战,只愿所向披靡. jquery的学习一 jquery关于ajax的一些学习博客 ajax方法的介绍:https:// ...

  7. MQTT的学习研究(二)moquette-mqtt 的使用之mqtt broker的启动

    在MQTT 官网 (http://mqtt.org/software)中有众多MQTT的实现方式.具体参看官网,Moquette是基于Apache Mina 的模型的一个Java MQTT broke ...

  8. [SCOI2008] 着色方案[高维dp]

    321. [SCOI2008] 着色方案 ★★★   输入文件:color.in   输出文件:color.out   简单对比时间限制:1 s   内存限制:64 MB 题目背景: 有n个木块排成一 ...

  9. chrome inspect 离线调试-工具包 怎么使用

    1.找到相关目录: C:\Users\当前用户\AppData\Local\Google\Chrome\User Data\Default 2.找到以下文件夹: 1.Application Cache ...

  10. java中的socket编程

    Socket,又称为套接字,Socket是计算机网络通信的基本的技术之一.如今大多数基于网络的软件,如浏览器,即时通讯工具甚至是P2P下载都是基于Socket实现的.本文会介绍一下基于TCP/IP的S ...