• 《你不知道的javaScript》中卷——第一部分——第一章——类型


    类型

    我们必须掌握 JavaScript 中的各个类型及其内在行为。几乎所有的 JavaScript 程序都会涉及某种形式的强制类型转换。

    let num = 3;
    let str = "3";
    console.log(str + num); // "33" num会被强制转换为string类型
    
    • 1
    • 2
    • 3

    内置类型

    基本类型:undefined,boolen,number,string,符号symbol(es6新增)
      >>假值类型:null
    复杂类型:对象object
      >>子类型Function,Array
    
    • 1
    • 2
    • 3
    • 4

    说明

    1. 使用typeof运算符来查看值的类型,只有null返回的是object类型,出了问题。正确的返回结果应该是 “null”,但这个 bug 由来已久,在 JavaScript 中已经存在了将近二十年,也许永远也不会修复,因为这牵涉到太多的 Web 系统,“修复”它会产生更多的bug,令许多系统无法正常工作。
    2. function(函数)也是 JavaScript 的一个内置类型。然而查阅规范就会知道,它实际上是 object 的一个“子类型”。具体来说,函数是“可调用对象”,它有一个内部属性 [[Call]],该属性使其可以被调用。而且函数还可以拥有属性length值为传入的参数
    3. 数组也是对象。确切地说,它也是 object 的一个“子类型”,数组的元素按数字顺序来进行索引(而非普通像对象那样通过键值对),其 length 属性是元素的个数。
    console.log(typeof 1 === "number");//true
    console.log(typeof "string" === "string");//true
    console.log(typeof undefined === "undefined");//true
    console.log(typeof true === "boolean");//true
    console.log(typeof {} === "object");//true
    console.log(typeof Symbol() === "symbol");//true
    console.log(typeof null === "null");//false
    console.log(typeof null === "object");//true
    const fn = function fn() {}
    console.log(typeof fn === "function");//true
    console.log(fn.length);//2
    console.log(typeof [1,2,3] === "object");//true
    console.log([1,2,3].length);//3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    判断值是否是null

    const nl = null;
    const fn = function fn(nl) {
        if (!nl && typeof nl === "object") {
            return true;
        }
        return false;
    }
    console.log(fn(nl)); // true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    值和类型

    javascript的变量名没有类型,变量的值才有类型

    let a = "str";
    console.log(typeof a); // "string"
    a = 1;
    console.log(typeof a); // "number"
    /* 
        同是变量名a,但是 typeof 的时候输出不同的值,输出的值与变量值的类型值一一对应
        说明javascript不检验变量名的值,检验的是变量值
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    undefined与undeclared

    在js中,当一个变量声明了但是还没有赋值的时候,此时这个变量的值默认会是undefined。
    但是我们也可以直接给它赋值一个undefined。

    let varl1;
    let varl2 = "str";
    varl2 = varl1;
    console.log(varl1, varl2); // undefined undefined
    console.log(typeof varl1); // undefined
    console.log(typeof varl2); // undefined
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    但是当我们typeof一个未声明的变量时,还是输出的undefined,按理来说应该输出undeclared或者报错。
    但是没有报错,因为typeof有安全防范机制,但是输出的值是undefined,还是会对我们造成一定的困扰。

    console.log(typeof a); // undefined
    
    • 1

    typeof与undeclared、typeof安全防范机制

    检测全局变量是否可用以及避免程序一部分报错

    多个脚本文件会在共享的全局命名空间中加载变量。理论上,全局命名空间中不应该有变量存在,所有东西都应该被封装到模块和私有或独立的命名空间中,然而不切实际。
    举个简单的例子,在程序中使用全局变量 DEBUG 作为“调试模式”的开关。在输出调试信息到控制台之前,我们会检查 DEBUG 变量是否已被声明。顶层的全局变量声明 var DEBUG =true 只在 debug.js 文件中才有,而该文件只在开发和测试时才被加载到浏览器,在生产环境中不予加载。问题是如何在程序中检查全局变量 DEBUG 才不会出现 ReferenceError 错误。这时 typeof 的安全防范机制就成了我们的好帮手:

    // 这样会抛出错误,浏览器报错DEBUG is not defined
    if (DEBUG) {
     console.log( "Debugging is starting" );
    }
    // 这样是安全的
    if (typeof DEBUG !== "undefined") {
     console.log( "Debugging is starting" );
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    不仅对用户定义的变量(比如 DEBUG)有用,对内建的 API 也有帮助:

    //判断这个变量名是否在当前作用域中能够使用
    if (typeof atob === "undefined") {
     atob = function() { /*..*/ };
    }
    
    • 1
    • 2
    • 3
    • 4

    还有一种不用通过 typeof 的安全防范机制的方法,就是检查所有全局变量是否是全局对象的属性,浏览器中的全局对象是 window。这种方法有一个缺点:当代码需要运行在多种 JavaScript环境中时(不仅仅是浏览器,还有服务器端,如 node.js 等),此时全局对象并非总是window。

    if (window.DEBUG) {
     // ..
    }
    if (!window.atob) {
     // ..
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    检测变量名在局部是否可用

    虽然很少见,但是如果想让自己写的代码可以被其他人复制使用,并且保证如果在别人的代码作用域中有同名变量就用别人的,否则就自己创建。

    const callback = function () {
        return "我的程序中已有了"
    }
    if (typeof callback !== 'undefined') {
        let varl = typeof callback !== 'undefined' ? callback : function () {
            return "typeof安全保护机制"
        };
        console.log(varl());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    9.1 C++ STL 排序、算数与集合
    Android系统启动之init进程启动+Zygote进程启动分析
    OpenAIGPT-4.5提前曝光?
    网络安全(黑客)自学
    推荐大学生考研党都来使用的白板笔记软件!上岸卷王必备!
    每天一道算法题:216. 组合总和 III
    19Linux基本使用和web程序部署
    力扣 138. 随机链表的复制
    C++新经典 | C++ 查漏补缺(并发与多线程)
    std::make_shared和new初始化智能指针的区别
  • 原文地址:https://blog.csdn.net/weixin_44242181/article/details/126118402