/*
 我们要来判断两个对象是否相等:
      首先特殊的是+0和-0,我们知道这两个值是等同的,结果是true
 */
   console.log(+0==-0)//true
   // 表现2
   //(-0).toString() // '0'
   //(+0).toString() // '0'
   
   // 表现3
   -0 < +0 // false
   +0 < -0 // false
   /*
   但是也有其特殊的差异性
    1/+0=+lnfinit 正无穷大
        1/-0=-lnfinity  负无穷大
        
        这是因为 JavaScript 采用了IEEE_754 浮点数表示法(几乎所有现代编程语言所采用),这是一种二进制表示法,
        按照这个标准,最高位是符号位(0 代表正,1 代表负),剩下的用于表示大小。而对于零这个边界值 ,
        1000(-0) 和 0000(0)都是表示 0 ,这才有了正负零的区别。
      
      我们再使用 math.round(-0.1)四舍五入的时候得到这个-0
      那么我们如何去区分呢
      
   */
  
  function kio(a,b){
      if(a===b){
          //首先a和b是相等的  然后走进这里,如果a不等于0,那么a和b就不能判断,或者b不等于零也不能判读,,
           //而1/a和1/b的判断是核心,因为1/+0得到是正无穷大+lnfinity  而1/b得到是负无穷大 是不成里相等的,所有就区分了
           //+0和-0的区别
          return a!==0 || 1/a==1/b
      }
      return false
  }
   kio(0,-0)
   console.log( kio(-0,+0))
   
   
   /*
    上面说了+0和-0的区别  还有一个nan这个值 ,这个值有个特点就是nan不等于他自己nan
   */
  
  function kop(a,b){
      /*if(a!==b){
          return true
      }else{
          return false
      }*/
      
      if(a!==a){
          return b!==b
      }
  }
  kop(NaN,NaN)
   console.log(kop(NaN,NaN))
   
   /*
     根据上面的代码,我们写出来了+0和-0,NaN之间怎么去判断区别的,那么我们下面可以写一个总结的版本的
   */
  
    function kio(a,b){
        //首先我们先来区别+0和-0
        if(a===b) return a!==0 || 1/a==1/b;
        
        //然后我们阿里判断当a等于null和b等于null的情况
        if(a==null||b==null) return false;
        
        //这里是判断NaN的情况
        if(a!==a) return b!==b;
        
        //判断参数a的类型,如果是基本类型,这里可以直接返回false
        /*
        也许你会好奇是不是少了一个 `typeof b !== function`?
        试想如果我们添加上了这句,当 a 是基本类型,而 b 是函数的时候,就会进入 deepEq 函数,而去掉这一句,
        就会进入直接进入 false,实际上 基本类型和函数肯定是不会相等的,所以这样做代码又少,又可以让一种情况更早退出。  
        */
         var type=typeof a
         if(type!="function" && type!=="object" && typeof b!=="object" ) return false
         
        // 更复杂的对象使用 deepEq 函数进行深度比较
            return deepEq(a, b);
    }
  
  /* 
  
  下面我们如何比较: 
     "cur"和new String("cur")  据我们知道typeof是不能获得对象形式的数据类型的,因为最后都会的大object,而我们学的还有一种办法
     ,就是object.prototype.tostring,call()如果是data,match会获得“【object data】”,这种字符串,但是"cur"和new String("cur")返回
     的都是[object string] ,所以就没办法去比较了,其实还是有的,用隐式类型转换
     
      +" "这个是可以转换为字符串的方式的
      字符串的比较规则是,如果两边都是字符串,那么就一一对比字符编码,来判断是否相等
     
  */
 console.log("cur"+" "===new String("cur") +" ")
  /*
    那么下面可以封装一个判断函数
  */  var tostrign=Object.prototype.toString()
    function jio(a,b){
        var classaa=Object.prototype.toString.call(a)
        if(classaa!==Object.prototype.toString.call(b)) return false;
        
        switch(classaa){
            //case:'[Object object]':
               //return "aaaa"
            case '[Object string]':
               return " "+a===" "+b;
           case '[object Number]':
                       if (" "+a !== " "+a) return " "+b !== " "+b;
                       return +a === 0 ? 1 / +a === 1 / b : +a === +b;
                 //case '[object Date]':
                     //return "aaaa"
                 case '[object Boolean]':
                       return " "+a === " "+b;
               }
        }
    jio(true,false)
    console.log(jio(NaN,NaN))
     console.log(jio(true,new Boolean(true)))
     /*
      判断两个函数是否相等呢?
       function Person() {
           this.name = name;
       }
       
       function Animal() {
           this.name = name
       }
       
       var person = new Person('Kevin');
       var animal = new Animal('Kevin');
       
       eq(person, animal) 
       我们要判断,这两个函数,是否相等,我们能判断么???他俩相等么?
       
        虽然 `person` 和 `animal` 都是 `{name: 'Kevin'}`,但是 `person` 和 `animal` 属于不同构造函数的实例,
        为了做出区分,我们认为是不同的对象。
        
        ```js
        //Object.create() 方法会使用指定的原型对象及其属性去创建一个新的对象。
        var attrs = Object.create(null);
        attrs.name = "Bob";
        eq(attrs, {name: "Bob"}); // ???
        ```
        
        尽管 `attrs` 没有原型,`{name: "Bob"}` 的构造函数是 `Object`,但是在实际应用中,只要他们有着相同的键值对,
        我们依然认为是相等。
        
        从函数设计的角度来看,我们不应该让他们相等,但是从实践的角度,我们让他们相等,
        所以相等就是一件如此随意的事情吗?!对啊,我也在想:undersocre,你怎么能如此随意呢!!!
        
        哎,吐槽完了,我们还是要接着写这个相等函数,我们可以先做个判断,对于不同构造函数下的实例直接返回 false。
     
     */
    function isFunction(obj) {
        return toString.call(obj) === '[object Function]'
    }
    
    function deepEq(a, b) {
        // 接着上面的内容
        var areArrays = className === '[object Array]';
        // 不是数组
        if (!areArrays) {
            // 过滤掉两个函数的情况
            if (typeof a != 'object' || typeof b != 'object') return false;
    
            var aCtor = a.constructor, bCtor = b.constructor;
            // aCtor 和 bCtor 必须都存在并且都不是 Object 构造函数的情况下,aCtor 不等于 bCtor, 
   // 那这两个对象就真的不相等啦
            if (aCtor == bCtor && !(isFunction(aCtor) && aCtor instanceof aCtor && isFunction(bCtor) 
    && bCtor instanceof bCtor) && ('constructor' in a && 'constructor' in b)) {
                return false;
            }
        }
    
        // 下面还有好多判断
    }