`
zhkac
  • 浏览: 52695 次
  • 性别: 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中的对象 ECMA262规范一直在强调,“ECMAScript是一种基于对 象(Object—Based)的语言,而不是传统的面向对象(Object— Oriented)的语言”。相信绝大多数人不会清楚这句话是什么意 思。我想我们可以把它...

    深入理解JavaScript系列

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

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

    JavaScript学习深入—面向对象编程,很不错的一本书。

    深入理解JavaScript系列(.chm)

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

    深入浅出JavaScript(中文版)

    为了启发你的思考,《深入浅出JavaScript(中文版)》覆盖了所有的javascript基本知识,从基本网络编程技巧,如变量、函数和循环语句,到高级一些的专题,如表单验证、dom操作、客户端对象、脚本程序调试——甚至是...

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

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

    javascript面向对象编程.pdf

    javascript面向对象编程, 适用于javascript入门后, 希望进一步深入研究这门技术的人员!

    JavaScript征途

    JavaScript对象,数组,字符串,使用正则表达式操纵字符串,客户端,控制文档结构的模型,JavaScript事件驱动模型,CSS,Cookie,XML和JSON,Ajax,深入JavaScript面向对象编程,深入JavaScript函数式编程,深入...

    JavaScript面向对象编程案例

    文档中初步讲解javascript面向对象编程思想,example.html是JavaScript面向对象编程思想案例,层层深入,希望给广大同胞一些帮助。

    深入浅出JavaScript (中文版) (Michael Morrison) PDF扫描版

    为了启发你的思考,《深入浅出javascript(中文版)》覆盖了所有的java script基本知识,从基本网络编程技巧,如变量、函数和循环语句,到高级一些的专题,如表单验证、dom操作、客户端对象、脚本程序调试——甚至是...

    深入理解javascript原型和闭包

    深入理解javascript原型和闭包(01)——一切都是对象 深入理解javascript原型和闭包(02)——函数和对象的关系

    JavaScript深入编程网页收集

    _filesjavascript如何避免内存泄露 - - JavaEye技术网站_filesprototype_js深入研究_files从 prototype_js 深入学习 javascript 的面向对象特性 - - AJAX - JavaEye论坛_files带参数的闭包函数的巧妙应用 - ...

    xiangxiong#blog#JavaScript深入之类数组对象与arguments1

    JavaScript深入之类数组对象与argumentsJavaScript深入系列第十三篇,讲解类数组对象与对象的相似与差异以及arguments的注意要点类

    javascript面向对象

    面向对象的javascript,深入了解javascript

    深入浅出javascript-head first javascript 中文版

    为了启发你的思考,《深入浅出JavaScript(中文版)》覆盖了所有的javascript基本知识,从基本网络编程技巧,如变量、函数和循环语句,到高级一些的专题,如表单验证、dom操作、客户端对象、脚本程序调试——甚至是...

    JavaScript 对象深入学习总结(经典)

    JavaScript对象也可以称作一种数据结构,正如我们经常听说的“散列(hash)”、“散列表(hashtable)”、“字典 (dictionary)”、“关联数组(associative array)”。 JavaScript中对象可以分为三类: ①内置...

Global site tag (gtag.js) - Google Analytics