44道JavaScript难题02

作者: Hello杨先生 | 来源:发表于2019-07-04 21:20 被阅读27次
  1. [typeof null, null instanceof Object]
    答案:["object", false]
    解析:null代表空对象指针,所以typeof判断成一个对象。可以说JS设计上的一个BUG
    instanceof 实际上判断的是对象上构造函数,null是空当然不可能有构造函数
    巩固:null == undefined //true null === undefined //flase
 <script>
        /**************************************分界线*********************************************/
        /**************************************分界线*********************************************/
        /**************************************分界线*********************************************/

        console.log(typeof null); //object

        //null代表空对象指针,所以typeof判断成一个对象。可以说JS设计上的一个BUG
        // 在 ECMAScript 规范中, 共定义了 7 种数据类型, 分为 基本类型 和 引用类型 两大类, 如下所示:
        // 基本类型: String、 Number、 Boolean、 Symbol、 Undefined、 Null
        // 引用类型: Object

        // typeof 是一个操作符, 其右侧跟一个一元表达式, 并返回这个表达式的数据类型。 
        // 返回的结果用该类型的字符串(全小写字母) 形式表示, 包括以下 7 种: 
        // number、 boolean、 symbol、 string、 object、 undefined、
        // function 等。

        console.log(typeof ''); // string 有效
        console.log(typeof 1); // number 有效
        console.log(typeof Symbol()); // symbol 有效
        console.log(typeof true); //boolean 有效
        console.log(typeof undefined); //undefined 有效
        console.log(typeof null); //object 无效
        console.log(typeof []); //object 无效
        console.log(typeof new Function()); // function 有效
        console.log(typeof new Date()); //object 无效
        console.log(typeof new RegExp()); //object 无效

        //JavaScript RegExp 对象
        // RegExp 对象
        // RegExp 对象表示正则表达式, 它是对字符串执行模式匹配的强大工具。

        // 有些时候, typeof 操作符会返回一些令人迷惑但技术上却正确的值
        // 对于基本类型, 除 null 以外, 均可以返回正确的结果。
        // 对于引用类型, 除
        // function 以外, 一律返回 object 类型。
        // 对于 null, 返回 object 类型。
        // 对于
        // function 返回
        // function 类型。
        // 其中, null 有属于自己的数据类型 Null, 
        // 引用类型中的 数组、 日期、 正则 也都有属于自己的具体类型, 
        // 而 typeof 对于这些类型的处理, 只返回了处于其原型链最顶端的 Object 类型, 
        // 没有错, 但不是我们想要的结果。


        /**************************************分界线*********************************************/
        /**************************************分界线*********************************************/
        /**************************************分界线*********************************************/

        console.log(null instanceof Object); //false

        // instanceof 实际上判断的是对象上构造函数,null是空当然不可能有构造函数

        // instanceof 是用来判断 A 是否为 B 的实例,
        // 表达式为: A instanceof B, 如果 A 是 B 的实例, 则返回 true, 否则返回 false。
        // 在这里需要特别注意的是: instanceof 检测的是原型, 我们用一段伪代码来模拟其内部执行过程:

        // instanceof(A, B) = {
        //     var L = A.__proto__;
        //     var R = B.prototype;
        //     if (L === R) {
        //         // A的内部属性 __proto__ 指向 B 的原型对象
        //         return true;
        //     }
        //     return false;
        // }
        // 从上述过程可以看出,
        // 当 A 的 __proto__ 指向 B 的 prototype 时,就认为 A 就是 B 的实例,
        // 我们再来看几个例子:

        console.log([] instanceof Array); // true         ***************
        console.log({}
            instanceof Object); // true
        console.log(new Date() instanceof Date); // true

        function Person() {};
        console.log(new Person() instanceof Person);

        console.log([] instanceof Object); // true          ******************
        console.log(new Date() instanceof Object); // true
        console.log(new Person instanceof Object); // true

        // 我们发现, 虽然 instanceof 能够判断出[] 是Array的实例, 但它认为[] 也是Object的实例, 为什么呢?

        // 我们来分析一下[]、 Array、 Object 三者之间的关系:
        // 从 instanceof 能够判断出[].__proto__ 指向 Array.prototype,
        // 而 Array.prototype.__proto__ 又指向了Object.prototype,
        // 最终 Object.prototype.__proto__ 指向了null,
        // 标志着原型链的结束。 因此,[]、 Array、 Object 就在内部形成了一条原型链:


        // 从原型链可以看出,[] 的 __proto__ 直接指向Array.prototype, 
        // 间接指向 Object.prototype, 
        // 所以按照 instanceof 的判断规则,[] 就是Object的实例。 
        // 依次类推, 类似的 new Date()、 new Person() 也会形成一条对应的原型链。 
        // 因此, instanceof 只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型。



        /**************************************分界线*********************************************/
        /**************************************分界线*********************************************/
        /**************************************分界线*********************************************/
        console.log(null == undefined); //true   
        // // ECMAScript认为undefined是从null派生出来的,所以把它们定义为相等的
        console.log(null === undefined); //false
        // // 使用typeof方法在前面已经讲过, null与undefined的类型是不一样的, 所以输出 "false"。
        // // 而 === 代表绝对等于, 在这里null === undefined输出false。

        console.log(typeof undefined); //undefined 
        console.log(typeof null); //object 

        // Undefined类型只有一个值, 即undefined。 当声明的变量还未被初始化时, 变量的默认值为undefined。
        // Null类型也只有一个值, 即null。 null用来表示尚未存在的对象, 常用来表示函数企图返回一个不存在的对象。

        // 一、“ === ”首先计算其操作数的值, 然后比较这两个值, 比较过程没有任何类型转换

        // 1、 如果两个值类型不相同, 则它们不相等。

        // 2、 如果两个值都是null或者都是undefined, 则它们不相等。

        // 3、 如果两个值都是布尔值true或false, 则它们相等。

        // 4、 如果其中一个值是NaN, 或者两个两个值都是NaN, 则它们不相等。 NaN和其他任何值都是不相等的, 包括它本身!!! 通过x !== x来判断x是否为NaN, 只有在x为NaN的时候, 这个表达式的值才为true。

        // 5、 如果两个值为数字, 且数值相等, 则它们相等。 如果一个为0, 另一个为 - 0, 则它们同样相等。

        // 6、 如果两个值为字符串, 且所含的对应位上的16位数完全相等, 则它们相等。 如果它们的长度或内容不同, 则它们不等。 两个字符串可能含义完全一样且所显示出手字符也一样, 但具有不同编码的16位值。 JavaScript并不对Unicode进行标准化的转换, 因此像这样的字符串通过
        //     "==="
        // 和 "=="
        // 运算符的比较结果也不相等。

        // 7、 如果两个引用值同一个对象、 数组或函数, 则它们是相等的。 如果指向不同的对象, 则它们是不等的。 尽管两个对象具有完全一样的属性。

        var param1 = ‘1’,
            param2 = ‘1’;
        param1 === param2; //类型和数值同时相等 true 
        var param3 = 1;
        param1 === param3; //类型不相等和数值相等false 
        var param4 = 2;
        param1 === param4; //类型和数值都不相等 false

        var param1 = null,
            param2 = undefined;
        param1 === param2; //false


        // 二、 相等运算符“ == ”如果两个操作数不是同一类型, 那么相等运算符会尝试一些类型转换, 然后进行比较

        // 1、 如果一个值是null, 另一个是undefined, 则它们相等。

        // 2、 如果一个值是数字, 另一个是字符串, 先将字符串转换为数字, 然后使用转换后的值比较。

        // 3、 如果其中一个值是true, 则将其转换为1再进行比较。 如果其中一个值是false, 则将基转换为0再进行比较。

        // 4、 如果一个值是对象, 另一个值是数字或字符串, 则将对象转换为原始值, 然后再进行比较。 对象通过toString
        // () 方法或valueOf() 方法转换为原始值。 JavaScript核心的内置类首先尝试使用valueOf(), 再尝试使用toString(), 除了日期类, 日期类只使用toString() 转换。 那些不是JavaScript语言核心中的对象则通过各自的实现中定义的方法转换为原始值。

        // 5、 其他不同类型之间的比较均不相等.

        var param1 = ‘1’,
            param2 = ‘1’;
        param1 == param2; //类型和数值同时相等true 
        var param3 = 1;
        param1 == param3; //类型不相等和数值相等true 
        var param4 = 2;
        param1 == param4; //类型和数值都不相等false

        var param1 = null,
            param2 = undefined;
        param1 === param2; //true
    </script>

相关文章

网友评论

    本文标题:44道JavaScript难题02

    本文链接:https://www.haomeiwen.com/subject/tmsdhctx.html