zoukankan      html  css  js  c++  java
  • 关于JS相等比较算法(==)的原理

            /*        
            关于JS相等比较算法(==)的原理
            
            比较运算x==y, 其中x和 y是值,产生true或者false。这样的比较按如下方式进行:
            1.若Type(x)与Type(y)相同, 则
            a.若Type(x)为Undefined, 返回true。
            b.若Type(x)为Null, 返回true。
            c.若Type(x)为Number, 则
            i.  若x为NaN, 返回false。 
            ii. 若y为NaN, 返回false。 
            iii.若x与y为相等数值, 返回true。 
            iv. 若x 为 +0 且 y为−0, 返回true。 
            v.  若x 为 −0 且 y为+0, 返回true。 
            vi. 返回false。//出自http://www.cnblogs.com/ahjesus 尊重作者辛苦劳动成果,转载请注明出处,谢谢!
            d.若Type(x)为String, 则当x和y为完全相同的字符序列(长度相等且相同字符在相同位置)时返回true。 否则, 返回false。 
            e.若Type(x)为Boolean, 当x和y为同为true或者同为false时返回true。 否则, 返回false。 
            f.当x和y为引用同一对象时返回true。否则,返回false。
            2.若x为null且y为undefined, 返回true。 
            3.若x为undefined且y为null, 返回true。 //出自http://www.cnblogs.com/ahjesus 尊重作者辛苦劳动成果,转载请注明出处,谢谢!
            4.若Type(x) 为 Number 且 Type(y)为String, 返回comparison x == ToNumber(y)的结果。 
            5.若Type(x) 为 String 且 Type(y)为Number, 返回比较ToNumber(x) == y的结果。 
            6.若Type(x)为Boolean, 返回比较ToNumber(x) == y的结果。 
            7.若Type(y)为Boolean, 返回比较x == ToNumber(y)的结果。 
            8.若Type(x)为String或Number,且Type(y)为Object,返回比较x == ToPrimitive(y)的结果。 
            9. 若Type(x)为Object且Type(y)为String或Number, 返回比较ToPrimitive(x) == y的结果。 
            10. 返回false。 //出自http://www.cnblogs.com/ahjesus 尊重作者辛苦劳动成果,转载请注明出处,谢谢!
            */
    
            function Equals(x, y) {
                if (typeof (x) == typeof (y)) {//若Type(x)与Type(y)相同, 则
                    if (typeof (x) == "Undefined") {//若Type(x)为Undefined, 返回true
                        return true;
                    }
                    if (typeof (x) == "Null") {//若Type(x)为Null, 返回true
                        return true;
                    } //出自http://www.cnblogs.com/ahjesus 尊重作者辛苦劳动成果,转载请注明出处,谢谢!
                    if (typeof (x) == "Number") {//若Type(x)为Number, 则
                        if (x == NaN) {//若x为NaN, 返回false
                            return false;
                        }
                        if (y = NaN) {//若y为NaN, 返回false
                            return false;
                        }
                        if (x == y) {//若x与y为相等数值, 返回true
                            return true;
                        }
                        if (x == +0 && y == -0) {//若x 为 +0 且 y为−0, 返回true
                            return true;
                        }
                        if (x == -0 && y == +0) {//若x 为 −0 且 y为+0, 返回true
                            return true;
                        }
                        return false; //返回false
                    } //出自http://www.cnblogs.com/ahjesus 尊重作者辛苦劳动成果,转载请注明出处,谢谢!
                    if (typeof (x) == "String") {//若Type(x)为String, 则
                        var xChars = x.split('');
                        var yChars = y.split('');
                        var i = xChars.length;
                        while (i--) {
                            if (xChars[i] != yChars[i]) {//当x和y为完全相同的字符序列(长度相等且相同字符在相同位置)时返回true
                                return false;
                            }
                        }
                        return true; //否则, 返回false
                    }
                    if (typeof (x) == "Boolean") {//若Type(x)为Boolean, 则 
                        if (x && y) {//当x和y为同为true或者同为false时返回true
                            return true;
                        }
    
                        return false; //否则, 返回false
                    }
                    if (compare(a, b)) {//当x和y为引用同一对象时返回true
                        return true;
                    }
                    return false; //否则,返回false
                } //出自http://www.cnblogs.com/ahjesus 尊重作者辛苦劳动成果,转载请注明出处,谢谢!
                if (x == null && y == undefined) {//若x为null且y为undefined, 返回true
                    return true;
                }
                if (x == undefined && y == null) {//若x为undefined且y为null, 返回true
                    return true;
                }
                if (typeof (x) == "Number" && typeof (y) == "String") {//若Type(x) 为 Number 且 Type(y)为String, 返回comparison x == ToNumber(y)的结果
                    return x == Number(y);
                }
                if (typeof (x) == "String" && typeof (y) == "Number") {//若Type(x) 为 String 且 Type(y)为Number, 返回比较ToNumber(x) == y的结果
                    return Number(x) == y;
                }
                if (typeof (x) == "Boolean") {//若Type(x)为Boolean, 返回比较ToNumber(x) == y的结果
                    return Number(x) == y;
                }
                if (typeof (y) == "Boolean") {//若Type(y)为Boolean, 返回比较x == ToNumber(y)的结果
                    return x == Number(y);
                }
                if ((typeof (x) == "String" || typeof (x) == "Number") && typeof (y) == "Object") {//若Type(x)为String或Number,且Type(y)为Object,返回比较x == ToPrimitive(y)的结果
                    return x == y;
                }
                if (typeof (x) == "Object" && (typeof (y) == "String" || typeof (y) == "Number")) {//若Type(x)为Object且Type(y)为String或Number, 返回比较ToPrimitive(x) == y的结果
                    return x == y;
                } //出自http://www.cnblogs.com/ahjesus 尊重作者辛苦劳动成果,转载请注明出处,谢谢!
                return false; //返回false
            }
            function compare(a, b) {
                var pt = /undefined|number|string|boolean/,
                    fn = /^(function\s*)(\w*\b)/,
                    cr = "constructor",
                    cn = "childNodes",
                    pn = "parentNode",
                    ce = arguments.callee;
                if (pt.test(typeof a) || pt.test(typeof b) || a === null || b === null) {
                    return a === b || (isNaN(a) && isNaN(b)); //为了方便,此处假定NaN == NaN 
                }
                if (a[cr] !== b[cr]) {
                    return false;
                }
                switch (a[cr]) {
                    case Date:
                        {
                            return a.valueOf() === b.valueOf();
                        };
                    case Function:
                        {
                            return a.toString().replace(fn, '$1') === b.toString().replace(fn, '$1'); //硬编码中声明函数的方式会影响到toString的结果,因此用正则进行格式化 
                        };
                    case Array:
                        {
                            if (a.length !== b.length) {
                                return false;
                            }
                            for (var i = 0; i < a.length; i++) {
                                if (!ce(a[i], b[i])) {
                                    return false;
                                }
                            }
                            break;
                        };
                    default:
                        {
                            var alen = 0, blen = 0, d;
                            if (a === b) {
                                return true;
                            }
                            if (a[cn] || a[pn] || b[cn] || b[pn]) {
                                return a === b;
                            }
                            for (d in a) {
                                alen++;
                            }
                            for (d in b) {
                                blen++;
                            }
                            if (alen !== blen) {
                                return false;
                            }
                            for (d in a) {
                                if (!ce(a[d], b[d])) {
                                    return false;
                                }
                            }
                            break;
                        };
                }
                return true;
            }
            function ToPrimitive(value) {
                /*
                关于ToPrimitive()方法说明:
                ToPrimitive 运算符接受一个值,和一个可选的 期望类型 作参数。ToPrimitive 
                运算符把其值参数转换为非对象类型。如果对象有能力被转换为不止一种原语类
                型,可以使用可选的 期望类型 来暗示那个类型。根据下表完成转换:
    
                ToPrimitive转换 
                输入类型    结果
                Undefined   结果等于输入的参数(不转换)。
                Null        结果等于输入的参数(不转换)。
                Boolean     结果等于输入的参数(不转换)。
                Number      结果等于输入的参数(不转换)。
                String      结果等于输入的参数(不转换)。
                Object      返回该对象的默认值。(调用该对象的内部方法[[DefaultValue]]一樣)。
    
                [[DefaultValue]] :
                对象共有的内部属性,取值范围SpecOp (Hint) → primitive
                Hint 是一个字符串。返回对象的默认值
                //出自http://www.cnblogs.com/ahjesus 尊重作者辛苦劳动成果,转载请注明出处,谢谢!
                当用字符串 hint 调用 O 的 [[DefaultValue]] 内部方法,采用以下步骤:
                1.  令 toString 为用参数 "toString" 调用对象 O 的 [[Get]] 内部方法的结果。 
                2.  如果 IsCallable(toString) 是 true,则 
                    a.  令 str 为用 O 作为 this 值,空参数列表调用 toString 的 [[Call]] 内部方法的结果。 
                    b.  如果 str 是原始值,返回 str。 
                3.  令 valueOf 为用参数 "valueOf" 调用对象 O 的 [[Get]] 内部方法的结果。
                4.  如果 IsCallable(valueOf) 是 true,则 
                    a.  令 val 为用 O 作为 this 值,空参数列表调用 valueOf 的 [[Call]] 内部方法的结果。 
                    b.  如果 val 是原始值,返回 val。 
                5.  抛出一个 TypeError 异常。 
    
                当用数字 hint 调用 O 的 [[DefaultValue]] 内部方法,采用以下步骤:
                1.  令 valueOf 为用参数 "valueOf" 调用对象 O 的 [[Get]] 内部方法的结果。 
                2.  如果 IsCallable(valueOf) 是 true,则 
                    a.  令 val 为用 O 作为 this 值,空参数列表调用 valueOf 的 [[Call]] 内部方法的结果。 
                    b.  如果 val 是原始值,返回 val。 
                3.  令 toString 为用参数 "toString" 调用对象 O 的 [[Get]] 内部方法的结果。 
                4.  如果 IsCallable(toString) 是 true,则 
                    a.  令 str 为用 O 作为 this 值,空参数列表调用 toString 的 [[Call]] 内部方法的结果。 
                    b.  如果 str 是原始值,返回 str。 
                5.  抛出一个 TypeError 异常
    
                当不用 hint 调用 O 的 [[DefaultValue]]  内部方法,O 是 Date 对象的情况下
                仿佛 hint 是字符串一样解释它的行为,除此之外仿佛 hint 是数字一样解释它的行为。
                上面说明的 [[DefaultValue]] 在原生对象中只能返回原始值。如果一个宿主对象
                实现了它自身的 [[DefaultValue]] 内部方法,那么必须确保其 [[DefaultValue]] 
                内部方法只能返回原始值。
                */
            }
  • 相关阅读:
    [转载] 论C#与Java之异同
    MultiThread WebRequest : Timeout
    FCL(2) :: CollectionBase & Collection
    msn 81000306 无法登录,解决方法
    接口一个被我忽略的地方接口重定向技术
    <<Clr Via C#>> Key Points (1) (46章)
    FCL(3):: ArrayList & List (1)
    TCP保活机制
    子网划分
    freopen函数
  • 原文地址:https://www.cnblogs.com/ahjesus/p/3084186.html
Copyright © 2011-2022 走看看