`
zhkac
  • 浏览: 53963 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

深入Javascript对象比较

阅读更多
一 概述
 
1.1 类型
 
Javascript数据类型分为值类型引用类型 , 其中值类型包括字符串实体(例如:”string”),数值实体(例如:100)和布尔值实体(如:true)。而其他的复杂类型都属于引用类型,例如日 期型(new Date()),正则表达式(/a/gi, new RegExp(“a”, “gi”))数组([1,2,3], new Array())函数(function(){}, new Function())和对象({a:”a”, b:100}, new Object())。这些都是Javascript固有的数据类型,而用户自定义类型都属于引用类型(如:var Person = function(name){this.name=name;};),它们都只能使用new关键字实例化为具体对象(new Person(“hotoo”))。
 
为了理解Javascript对象的类型,我们来看一些如下代码:
// test instanceof and typeof:  
var instStr = [ '"string"' , '100' , 'true' , '/a/g' , '[1,2,3]' , 'function(){}' , '{}' , 'null' , 'undefined' ];  
var inst = [ "string" , 100 , true , /a/g , [ 1 , 2 , 3 ], function (){}, {}, null , undefined ]; 
var ObjsStr = [ "String" , "Number" , "Boolean" , "RegExp" , "Array" , "Function" , "Date" , "Object" ];  
var Objs = [ String , Number , Boolean , RegExp , Array , Function , Date , Object ];  
jsoutInst ( "instanceof" , ObjsStr, Objs , instStr , inst );  
 
 
 
function jsoutInst( methodName , tsStr , ts , osStr , os ){  
    document. write ( "<table border='1'><tr>" );  
    document. write ( "<td><strong>" + methodName + "</strong></td>" );  
    for ( var i = 0 ; i < tsStr . length ; i ++){  
       document. write ( "<td>" + tsStr [ i ]+ "</td>" );  
    } 
    document. write ( "</tr>" );  
    for ( var i = 0 ; i < os . length ; i ++){  
       document. write ( "<tr><td>" + osStr [ i ]+ "</td>" );  
       for ( var j = 0 ; j < ts . length ; j ++){  
           document. write ( "<td>" +( os [ i ] instanceof ts [ j ]? "<strong>true</strong>" : "false" )+ "</td>" );  
       } 
       document. write ( "</tr>" );  
    } 
    document. write ( "</table><br />" );  
}  
 
var typesStr = [ "string" , "number" , "boolean" , "array" , "function" , "date" , "object" , "undefined" ]; 
jsoutType ( "typeof" , typesStr, instStr , inst );  
function jsoutType( methodName , tsStr , osStr , os ){  
    document. write ( "<table border='1'><tr>" );  
    document. write ( "<td><strong>" + methodName + "</strong></td>" );  
    for ( var i = 0 ; i < tsStr . length ; i ++){  
       document. write ( "<td>" + tsStr [ i ]+ "</td>" );  
    } 
    document. write ( "</tr>" );  
    for ( var i = 0 ; i < os . length ; i ++){  
       document. write ( "<tr><td>" + osStr [ i ]+ "</td>" );  
       for ( var j = 0 ; j < tsStr . length ; j ++){  
           document. write ( "<td>" +( typeof os [ i ] == tsStr [ j ]? "<strong>true</strong>" : "false" )+ "</td>" );  
       } 
       document. write ( "</tr>" );  
    } 
    document. write ( "</table><br />" );  
}
上面的代码很简单,第一个函数判断对象实例是否是某个类的实例(instanceof),第二个函数对比对象实例是否与某类型(typeof)相等,他们将输出两个表格,我们来对比一下(为了方便阅读,这里将说明插在相应表格下。 )。

 

 

 

instanceof String Number Boolean RegExp Array Function Date Object
"string" false false false false false false false false
100 false false false false false false false false
true false false false false false false false false
/a/g false false false true false false false true
[1,2,3] false false false false true false false true
function(){} false false false false false true false true
{} false false false false false false false true
null false false false false false false false false
undefined false false false false false false false false
 

 

通 过(instanceof)这个表格可以看出,值类型(”string”, 100, true等)不是任何对象的实体(instance),而引用类型(/a/g, [1,2,3], function(){}和 {})既是本身类型的实体,又是其父类型的实体(所有类型都继承自Object类型)。
所有通过引用类型(包括值类型的wrapper类String, Number和 Boolean)new出来的对象,都是其对应类和其父类(这里是Object)的实例。
虽然值类型不是其对应wrapper类的实例,但是值类型却可以直接使用其wrapper类的属性和方法,就如同值类型是其wrapper类的实例一样。例如:”ABC”.toLowerCase()。
 

 

typeof string number boolean array function date object undefined
"string" true false false false false false false false
100 false true false false false false false false
true false false true false false false false false
/a/g false false false false false false true false
[1,2,3] false false false false false false true false
function(){} false false false false true false false false
{} false false false false false false true false
null false false false false false false true false
undefined false false false false false false false true
 
而 从(typeof)表可以看出,使用typeof关键字可以知道值类型对应的wrapper类,而奇怪的是,引用类型的type都是”object”,要 判断这些类型时,我们只能通过instanceof关键字。特殊的,function(){}是个例外,关于function的特殊性,在本文后面也会遇 到。
所有引用类型(包括值类型的wrapper类)new出来的对象的type都是”object”。
对比两个表中的null和undefined两个特殊值发现,null的类型(type)是”object”,但是它不是Object的实例。而undefined的类型(type)是undefined,不是Object的实例。
注:以上是 Microsoft Server 2003, Internet Explorer 6.0 中的输出结果,在其他浏览器中测试结果一致。  
1.2 比较
 
比较必须具有一下性质:对称性,传递性,自等性。关于自等性,Javascript的NaN比较特殊,它不等于自身,包括同一个引用。
在Javascript中有两个基本符号用来比较对象:==和===。
1.2.1 等于==
 
下面是对《深入学习Javascript开发与实例》的引用:
等于操作符比较操作符左右两边的值,如果相等则返回true;否则就返回false。
对于除了Javascript 1.2以外的所有版本,在比较值大小之前会将其类型转为同一种数据类型。在进行类型转换时候,Javascript遵循下列规则:
l   true转换为数组1,false转换为数字0;
l   若两边表达式均为NaN,等于操作符返回false;
l   空值(null)和没定义(undefined)相等;
l   空值和没定义不等于0(零)、""、或false;
l   若比较字符串和数字,将字符串转为数字,再检查是否相等;
l   若比较对象和字符串,将对象转为字符串,再检查是否相等;
l   若比较对象和数字,将对象转为数字,再检查是否相等;
l   若符号两边均为对象,检查其地址是否相等。
 
1.2.2 完全相同===
 
下面是对《深入学习Javascript开发与实例》的引用:
比较操作符左右两边的值,如果相等,运算中则返回true;否则就返回false。
在比较完成之前,不进行类型转换。
 
1.2.3 扩展方法equals
 
在Java中的==号与Javascript相似,比较对象的内存地址。对于比较两个对象来说,==和===两个符号似乎没有什么意义,它们只能比较处是否是同一个对象,而我们要比较的是两个对象的值是否相等。
在Java中,基类Object的equals方法也是比较两个对象的地址,所以为了方便对象间的比较,一般要求用户创建的类都实现(覆写)equals方法。
为 了方便Javascript对象比较,我扩展了Javascript核心值类型和引用类型的equals方法,并且建议用户在创建类时也实现(覆写)这个 方法。由于在实现上,我没有将Object对象的equals方法简单的用==号或者===号比较,所以如果用户不覆写equals方法,也同样可以用 equals方法比较两个对象的相等性。

 

二 实现代码
 
下 面是所有的equals.js的代码,它可以方便你对复杂的引用类型进行值比较。要说明的是,因为在Object对象的equals方法中也同样调用了 equals方法,它可能是引用类型的equals方法,也可能是值类型的equals方法,递归至调用其他核心类型的equals方法。
这里的方法最“核心”的就是Object和Array两个类的equals方法,他们用到了类似递归,但不是递归的方法,最终退出“递归”是在调用其他核心对象的非递归equals方法时返回。
 
/*<![CDATA[*/
/** equals
 * @description 比较两个对象是否相等时 ,
 * 需要穿插使用其他对象的 equals 方法 ,
 * 这里将 Javascript 核心对象的 equals 方法扩展集合于此 ,
 * 用于方便实现其他对象的 equals 方法 ,
 * 建议所有用户创建类中都实现 equals 方法 .
 * 该方法在比较数组等对象时尤为有用 .
 * @create 2007-10-2
 * @update
 * @author 闲耘 (hotoo.cn[ AT ] gmail.com)
 */
 
 
/** 比较当前对象与指定对象是否相等。
 * 覆写并扩展基类 (Object) ,方便子类 ( 如: Array) 扩展此方法。
 * 这个方法可能用到 string, number, function 等基本数据类型的 wapper (String, Number, Function) equals 方法。
 * @param obj, Object.
 * @return Boolean.
 */
Object . prototype . equals = function ( obj ){
    if (( this === obj )){ return true ;}
    if (!( obj instanceof Object ) || ( obj === null )){ return false ;} // null is not instanceof Object.
    var i = 0 ; // object property counter.
    for ( var k in this ){
        i++;
        var o1 = this [ k ];
        var o2 = obj [ k ];
       if (( o1 != null ) && !( o1 . equals ( o2 ))){ return false ;} // inner object.
    }
    for ( var k in obj ){ // compare object property counter.
        i--;
    }
    return i === 0 ;
};
 
 
/** 比较当前函数对象与指定对象的值是否完全相等(包括数据类型)。
 * 函数的比较比较复杂和怪异,两个构造完全一致的函数的 valueOf() 值并不相同,这个可以理解。
 * 而使用 toString() 方法,是否也应该先将他们的无效空格和换行去掉?似乎问题变得复杂了。
 * 最大的问题是, new Function() function() {} toString() 方法在不同浏览器中表现不同,详情附注。
 * 出于简单性,一致性和函数的特殊性考虑,函数仅且仅在和本身比较时才相等。
 * @param number, Number.
 * @return Boolean.
 */
Function . prototype . equals = function ( fun ){
    return ( fun instanceof Function )&&
       (this . valueOf ()=== fun . valueOf ()); // new Function().valueOf() is not equals new Function().valueOf().
};
// 附注:
//=========================================
//(this.toString()==fun.toString());
//!important:function(){} new Function() toString 方法在不同浏览器中具有不确定性:
//=========================================
// IE6:new Function().toString():
//   function anonymous() {
//  
//   }
//- - - - - - - - - - - - - - - - - - - - -
// IE6:function(){}.toString():
//   function(){}
//=========================================
// FF1:new Function().toString():
//   function anonynous() {
//   }
//- - - - - - - - - - - - - - - - - - - - -
// FF1:function(){}.toString():
//   function () {
//   }
//=========================================
//   Opera9:new Function().toString():
//   function ()
//   {
//     }
//- - - - - - - - - - - - - - - - - - - - -
//   Opera9:function(){}.toString():
//   function ()
//   {
//     }
//==========================================
 
 
 
/** 比较当前字符串对象与指定对象是否相等。
 * @param string, String, Object.
 * @return Boolean.
 */
String . prototype . equals = function ( string ){
    return (( string instanceof String ) ||
       (typeof ( string )=== "string" ))&&
       (this . valueOf ()=== string . valueOf ());
};
 
 
/** 比较当前数字对象与指定对象是否完全相等(包括数据类型)。
 * @param number, Number.
 * @return Boolean.
 */
Number . prototype . equals = function ( number ){
    return (( number instanceof Number ) ||
       (typeof ( number )=== "number" )) &&
       (this . valueOf ()=== number . valueOf ());
};
 
 
/** 比较当前布尔对象与指定对象的值是否完全相等(包括数据类型)。
 * @param bool, Boolean.
 * @return Boolean.
 */
Boolean . prototype . equals = function ( bool ){
    return (( bool instanceof Boolean ) ||
       (typeof ( bool )=== "boolean" )) &&
       (this . valueOf ()=== bool . valueOf ());
};
 
 
/** 当前日期对象与另一日期对象的值相比较。
 * @param date, Date. 相比较的日期对象。
 * @return Boolean. 两个日期值是否相等。
 * @create color
分享到:
评论

相关推荐

    深入浅出JavaScript对象模型

    ### 深入浅出JavaScript对象模型 #### JavaScript对象的本质 根据ECMA262规范,ECMAScript被定义为一种基于对象的语言而非传统的面向对象语言。这意味着在JavaScript中,对象被视为存储数据的一种大型数组形式,...

    JavaScript学习深入—面向对象编程

    - **原型链**:每个JavaScript对象都有一个原型对象,这个原型对象也有一个原型,以此类推,形成一个链状结构。当试图访问一个对象的属性时,JavaScript引擎会沿着这个原型链查找,直到找到该属性为止。 ```...

    深入理解JavaScript系列

    第3部分深入探索JavaScript,介绍了语法、值、运算符、布尔类型、数字、字符串、语句、异常捕获、函数、变量、对象与继承、数组、正则表达式、Date、Math、JSON、标准全局变量、编码和JavaScript、ECMAScript 5的新...

    javascript对象参考手册

    "JavaScript对象参考手册"涵盖了这一主题的广泛内容,旨在为开发者提供全面、深入的理解和实用指南。手册分为20个章节,不仅涉及基础概念,还深入探讨了如ActiveX技术这样的高级特性以及数据库访问等复杂话题。 ...

    Javascript面向对象编程.

    JavaScript是一种广泛应用于Web开发的脚本语言,尤其在前端领域占据着核心地位。面向对象编程(Object-Oriented Programming,OOP)是...学习这些材料将有助于深入理解JavaScript的面向对象编程,提升你的编程技能。

    面向对象JavaScript精要(英文原版pdf)

    作者深入浅出地介绍了面向对象编程的基本原理以及如何将这些原理应用于JavaScript中。 #### 二、面向对象编程基础 面向对象编程(OOP)是一种软件开发方法,它通过将数据和处理这些数据的方法捆绑在一起形成“对象”...

    深入理解JavaScript系列(.chm)

    深入理解JavaScript系列(9):根本没有“JSON对象”这回事 深入理解JavaScript系列(10):JavaScript核心(晋级高手必读篇) 深入理解JavaScript系列(11):执行上下文(Execution Contexts) 深入理解...

    JavaScript对象定义

    在本文中,我们将深入探讨JavaScript对象的定义、创建方法以及相关的工具和技术。 首先,我们要了解JavaScript对象的本质。对象是由键值对(key-value pairs)构成的集合,这些键可以是字符串或符号,而值可以是...

    JavaScript对象模型

    本文旨在深入解析JavaScript对象模型的关键概念,包括基本数据类型、对象、函数及其内部实现原理。 #### 二、基本数据类型 在JavaScript中,基本数据类型是最底层的实现形式。主要包括以下几种: - **Undefined**...

    JavaScript对象的特性与实践应用深入详解

    JavaScript对象是一种...通过上述对JavaScript对象的深入解析,我们可以看出对象在JavaScript编程中的灵活性和强大功能。掌握对象的特性与实践应用能够帮助我们更好地组织和管理数据,编写出更加高效、可维护的代码。

    面向对象JavaScript开发

    JavaScript,作为一种广泛应用...JavaScript 面向对象程序设计——继承与多态.pdf 和 JavaScript 面向对象程序设计——封装.pdf 这两个文档可能深入探讨了这些主题,帮助读者深入理解并掌握JavaScript的面向对象开发。

    《深入浅出JavaScript》PDF版本下载.txt

    根据提供的文件信息,我们可以推断出这是一篇关于获取《深入浅出JavaScript》电子书的信息。下面我们将基于这个前提,围绕“深入浅出JavaScript”这一主题进行知识点的展开。 ### 深入浅出JavaScript概览 #### 一...

    JavaScript对象经典小册 chm

    本小册"JavaScript对象经典小册 chm"深入探讨了JavaScript中的核心概念——对象和数组,旨在帮助开发者更好地理解和掌握这些基础知识。 一、JavaScript对象 1. 对象概述:JavaScript对象是一种数据结构,它由键值对...

    javascript面向对象之对象的深入理解.docx

    ### JavaScript面向对象之对象的深入理解 #### 一、引言 在JavaScript中,对象是其核心组成部分之一,几乎所有的操作都是围绕着对象来进行的。本文将深入探讨JavaScript中的对象概念,通过具体示例帮助读者更好地...

    深入理解javascript原型和闭包.pdf

    JavaScript原型和闭包是这门语言中两个比较难以理解且与其他面向对象语言区别较大的概念。理解这两个概念,不仅能让我们更深层次地理解JavaScript,而且有助于我们了解编程语言的设计思路,拓宽我们的视野。 首先,...

    深入浅出JavaScript源代码

    首先,我们要明白JavaScript的基础,包括变量、数据类型(如字符串、数字、布尔值、null、undefined、对象和数组)、操作符(如算术、比较、逻辑和赋值操作符)以及流程控制语句(如条件语句、循环语句)。...

Global site tag (gtag.js) - Google Analytics