小工具知识网

当前位置: 首页 > 行业知识 > JavaScript 冷知识大赏:带你领略不一样的编程乐趣

行业知识

JavaScript 冷知识大赏:带你领略不一样的编程乐趣

2026-10-25 07:47:00 来源:互联网转载


个人专栏:JavaScript 精粹

本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结,欢迎大家在评论区交流讨论!

文章目录

  • JavaScript 中的小 tips
    • 1 严格模式
      • 1.1 "use strict" 严格模式
      • 1.2 开启严格模式
      • 1.3 全局变量显式声明
      • 1.4 静态绑定
      • 1.5 增强的安全措施
      • 1.6 禁止删除变量
      • 1.7 显式报错
      • 1.8 重名错误
      • 1.9 禁止八进制表示法
      • 1.10 arguments对象的限制
      • 1.11 函数必须声明在顶层
      • 1.12 保留字
      • 2 值在各种场景的转换规则
      • 3 错误类型
      • 4 空值合并运算符 '??'
        • 4.1 与 || 比较
        • 4.2 优先级
        • 4.3 注意:
        • 5 ===
        • 6 CONSOLE 控制台输入
          • 6.1 Console.assert()
          • 6.2 Console.clear()
          • 6.3 Console.count()
          • 6.4 Console.countReset()
          • 6.5 Console.debug()
          • 6.6 Console.dir()
          • 6.7 Console.dirxml()
          • 6.8 打印信息
          • 6.9 打印树状结构
          • 6.10 Console.table()
          • 6.11 定时器
          • 6.12 Console.trace()
          • 6.13 占位符

            JavaScript 中的小 tips

            1 严格模式

            严格模式是ES5引入

            严格模式主要有以下限制:

            1. 变量必须声明后再使用
            2. 函数的参数不能有同名属性,否则报错
            3. 不能使用with语句
            4. 不能对只读属性赋值,否则报错
            5. 不能使用前缀0表示八进制数,否则报错
            6. 不能删除不可删除的属性,否则报错
            7. 不能删除变量delete prop,会报错,只能删除属性delete global[prop]
            8. eval不会在它的外层作用域引入变量
            9. eval和arguments不能被重新赋值
            10. arguments不会自动反映函数参数的变化
            11. 不能使用arguments.callee
            12. 不能使用arguments.caller
            13. 禁止this指向全局对象
            14. 不能使用fn.caller和fn.arguments获取函数调用的堆栈
            15. 增加了保留字(比如protected、static和interface)

            1.1 “use strict” 严格模式

            “use strict” 是ES5 中的新指令(ECMAScript version 5)。

            "严格模式"体现了Javascript更合理、更安全、更严谨的发展方向,包括IE 10在内的主流浏览器,都已经支持它,许多大项目已经开始全面拥抱它。

            1.2 开启严格模式

            针对脚本

                "use strict";    console.log("这是严格模式。");

            针对函数

            function strict(){    "use strict";    return "这是严格模式。";}

            优化形式

            //因为第一种调用方法不利于文件合并,所以更好的做法是,借用第二种方法,将整个脚本文件放在一个立即执行的匿名函数之中。(function (){"use strict";// some code here})();

            1.3 全局变量显式声明

            在正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,全局变量必须显式声明。

            "use strict";v = 1; // 报错,v未声明for(i = 0; i  

            1.4 静态绑定

            Javascript语言的一个特点,就是允许"动态绑定",即某些属性和方法到底属于哪一个对象,不是在编译时确定的,而是在运行时(runtime)确定的。

            严格模式对动态绑定做了一些限制。某些情况下,只允许静态绑定。也就是说,属性和方法到底归属哪个对象,在编译阶段就确定。这样做有利于编译效率的提高,也使得代码更容易阅读,更少出现意外。

            具体来说,涉及以下几个方面。

            (1)禁止使用with语句

            因为with语句无法在编译时就确定,属性到底归属哪个对象。

            "use strict";var v = 1;with (o){ // 语法错误    v = 2;}

            (2)创设eval作用域

            正常模式下,Javascript语言有两种变量作用域(scope):全局作用域和函数作用域。严格模式创设了第三种作用域:eval作用域。

            正常模式下,eval语句的作用域,取决于它处于全局作用域,还是处于函数作用域。严格模式下,eval语句本身就是一个作用域,不再能够生成全局变量了,它所生成的变量只能用于eval内部。

            "use strict";var x = 2;console.info(eval("var x = 5; x")); // 5console.info(x); // 2

            1.5 增强的安全措施

            (1)禁止this关键字指向全局对象

             function f(){    return !this;  }  // 返回false,因为"this"指向全局对象,"!this"就是false  function f(){    "use strict";    return !this;  }  // 返回true,因为严格模式下,this的值为undefined,所以"!this"为true。

            因此,使用构造函数时,如果忘了加new,this不再指向全局对象,而是报错。

            function f(){    return !this;}// 返回false,因为"this"指向全局对象,"!this"就是falsefunction f(){    "use strict";    return !this;}// 返回true,因为严格模式下,this的值为undefined,所以"!this"为true。

            (2)禁止在函数内部遍历调用栈

            function f1(){    "use strict";    f1.caller; // 报错    f1.arguments; // 报错}f1();

            1.6 禁止删除变量

            严格模式下无法删除变量。只有configurable设置为true的对象属性,才能被删除。

            "use strict";var x;delete x; // 语法错误var o = Object.create(null, {'x': {    value: 1,    configurable: true}});delete o.x; // 删除成功

            1.7 显式报错

            正常模式下,对一个对象的只读属性进行赋值,不会报错,只会默默地失败。严格模式下,将报错。

              "use strict";  var o = {};  Object.defineProperty(o, "v", { value: 1, writable: false });  o.v = 2; // 报错

            严格模式下,对一个使用getter方法读取的属性进行赋值,会报错。

             "use strict";  var o = {    get v() { return 1; }  };  o.v = 2; // 报错

            严格模式下,对禁止扩展的对象添加新属性,会报错。

             "use strict";  var o = {};  Object.preventExtensions(o);  o.v = 1; // 报错

            严格模式下,删除一个不可删除的属性,会报错。

              "use strict";  delete Object.prototype; // 报错

            1.8 重名错误

            严格模式新增了一些语法错误。

            (1)对象不能有重名的属性

            正常模式下,如果对象有多个重名属性,最后赋值的那个属性会覆盖前面的值。严格模式下,这属于语法错误。

             "use strict";  var o = {    p: 1,    p: 2  }; // 语法错误

            (2)函数不能有重名的参数

            正常模式下,如果函数有多个重名的参数,可以用arguments[i]读取。严格模式下,这属于语法错误。

             "use strict";  function f(a, a, b) { // 语法错误    return ;  }

            1.9 禁止八进制表示法

            正常模式下,整数的第一位如果是0,表示这是八进制数,比如0100等于十进制的64。严格模式禁止这种表示法,整数第一位为0,将报错。

              "use strict";  var n = 0100; // 语法错误

            1.10 arguments对象的限制

            arguments是函数的参数对象,严格模式对它的使用做了限制。

            (1)不允许对arguments赋值

            "use strict";arguments++; // 语法错误var obj = { set p(arguments) { } }; // 语法错误try { } catch (arguments) { } // 语法错误function arguments() { } // 语法错误var f = new Function("arguments", "'use strict'; return 17;"); // 语法错误

            (2)arguments不再追踪参数的变化

             function f(a) {    a = 2;    return [a, arguments[0]];  }  f(1); // 正常模式为[2,2]  function f(a) {    "use strict";    a = 2;    return [a, arguments[0]];  }  f(1); // 严格模式为[2,1]

            (3)禁止使用arguments.callee

            这意味着,你无法在匿名函数内部调用自身了。

              "use strict";  var f = function() { return arguments.callee; };  f(); // 报错

            1.11 函数必须声明在顶层

            将来Javascript的新版本会引入"块级作用域"。为了与新版本接轨,严格模式只允许在全局作用域或函数作用域的顶层声明函数。也就是说,不允许在非函数的代码块内声明函数。

             "use strict";  if (true) {    function f() { } // 语法错误  }  for (var i = 0; i  

            1.12 保留字

            为了向将来Javascript的新版本过渡,严格模式新增了一些保留字:implements, interface, let, package, private, protected, public, static, yield。

            使用这些词作为变量名将会报错。

              function package(protected) { // 语法错误    "use strict";    var implements; // 语法错误  }

            此外,ECMAscript第五版本身还规定了另一些保留字(class, enum, export, extends, import, super),以及各大浏览器自行增加的const保留字,也是不能作为变量名的。

            2 值在各种场景的转换规则

            值字符串操作环境数字运算环境逻辑运算环境对象操作环境
            undefined“undefined”NaNfalseError
            null“null”0falseError
            非空字符串不转换字符串对应的数字值True
            空字符串不转换0falseString
            0“0”不转换falseNumber
            NaN“NaN”不转换falseNumber
            Infinity“Infinity”不转换trueNumber
            Number.POSITIVE_INFINITY“Infinity”不转换trueNumber
            Number.NEGATIVE_INFINITY“-Infinity”不转换trueNumber
            Number.MAX_VALUE“1.7976931348623157e+308”不转换trueNumber
            Number.MIN_VALUE“5e-324”不转换trueNumber
            其他所有数字“数字的字符串值”不转换trueNumber
            true“true”1不转换Boolean
            false“false”0不转换Boolean
            对象toString()value()或toString()或NaNtrue不转换

            3 错误类型

            ECMA-262规范指出了7种错误类型。当不同的错误条件发生时,这些类型在JavaScript引擎中都有用到,当然我们也可以手动创建它们。

            • Error

              所有错误的基本类型。实际上引擎从来不会抛出该类型的错误。

              • EvalError

                通过eval()函数执行代码发生错误时抛出。

                • RangError

                  一个数字超出他的边界时抛出,例如:试图创建一个长度为-20的数组( new Array(-20) )。该错误在正常代码执行中非常罕见。

                  • ReferenceError

                    期望的对象不存在时抛出,例如:试图在一个null对象引用上调用一个函数。

                    • SyntaxError

                      给eval()函数传递的代码中有语法错误时抛出。

                      • TypeError

                        变量不是期望的类型时抛出,例如:new 10或者"prop" in true。

                        • URIError

                          给encodeURI()、encodeURICommonent()、decodeURI()或者decodeURIComponent()等函数传递个是非法的URI字符串时抛出。

                          4 空值合并运算符 ‘??’

                          空值合并运算符 ?? 提供了一种简短的语法,用来获取列表中第一个“已定义”的变量(译注:即值不是 null 或 undefined 的变量)。

                          a ?? b 的结果是:

                          • a,如果 a 不是 null 或 undefined,
                          • b,其他情况。

                            所以,x = a ?? b 是下面这个表达式的简写:

                            x = (a !== null && a !== undefined) ? a : b;

                            下面是一个更长一点的例子。

                            假设,我们有一个用户,变量 firstName、lastName 和 nickName 分别对应用户的名字、姓氏和昵称。如果用户决定不输入任何值,那么这些变量都可能是未定义的。

                            我们想要显示用户的名称:显示这三个变量中的一个,如果都没有设置值,则显示 “Anonymous”。

                            让我们使用 ?? 运算符选择第一个已定义的变量:

                            let firstName = null;let lastName = null;let nickName = "Supercoder";// 显示第一个不是 null/undefined 的值alert(firstName ?? lastName ?? nickName ?? "Anonymous"); // Supercoder

                            4.1 与 || 比较

                            或运算符 || 可以与 ?? 运算符以同样的方式使用。正如 上一章 所讲的,我们可以用 || 替换上面示例中的 ??,也可以获得相同的结果。

                            重要的区别是:

                            • || 返回第一个 真 值。
                            • ?? 返回第一个 已定义的 值。

                              当我们想将 null/undefined 与 0 区别对待时,这个区别至关重要。

                              例如,考虑下面这种情况:

                              height = height ?? 100;

                              如果 height 未定义,则将其赋值为 100。

                              让我们将其与 || 进行比较:

                              let height = 0;alert(height || 100); // 100alert(height ?? 100); // 0

                              在这个例子中,height || 100 将值为 0 的 height 视为未设置的(unset),与 null、undefined 以及任何其他假(falsy)值同等对待。因此得到的结果是 100。

                              height ?? 100 仅当 height 确实是 null 或 undefined 时才返回 100。因此,alert 按原样显示了 height 值 0。

                              哪种行为更好取决于特定的使用场景。当高度 0 为有效值时,?? 运算符更适合。

                              4.2 优先级

                              优先级要在复杂表达式中使用 ?? 进行取值,需要考虑加括号:

                              因此,?? 在大多数其他运算之后,但在 = 和 ? 之前进行运算。

                              如果我们需要在复杂表达式中使用 ?? 进行取值,需要考虑加括号:

                              let height = null;let width = null;// 重要:使用括号let area = (height ?? 100) * (width ?? 50);alert(area); // 5000

                              否则,如果我们省略了括号,* 的优先级比 ?? 高,会优先执行。

                              运算过程将等同于下面这个表达式:

                              // 可能不正确的let area = height ?? (100 * width) ?? 50;

                              这里还有一个相关的语言级别的限制。

                              出于安全原因,禁止将 ?? 运算符与 && 和 || 运算符一起使用。

                              下面的代码会触发一个语法错误:

                              let x = 1 && 2 ?? 3; // Syntax error

                              这个限制无疑是值得商榷的,但是它被添加到语言规范中是为了避免编程错误,因为人们开始使用 ?? 替代 ||。

                              可以明确地使用括号来解决这个问题:

                              let x = (1 && 2) ?? 3; // 起作用alert(x); // 2

                              4.3 注意:

                              • 空值合并运算符 ?? 提供了一种简洁的方式获取列表中“已定义”的值。

                                它被用于为变量分配默认值:

                                // 当 height 的值为 null 或 undefined 时,将 height 的值设置为 100height = height ?? 100;
                              • ?? 运算符的优先级非常低,只略高于 ? 和 =。

                              • 如果没有明确添加括号,不能将其与 || 或 && 一起使用。

                                5 ===

                                在转换不同的数据类型时,相等和不相等操作符遵循下列基本规则:

                                • 如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值——false 转换为 0,而true 转换为 1;
                                • 如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值;
                                • 如果一个操作数是对象,另一个操作数不是,则调用对象的 valueOf()方法,用得到的基本类型值按照前面的规则进行比较;

                                  这两个操作符在进行比较时则要遵循下列规则。

                                  • null 和 undefined 是相等的。

                                  • 要比较相等性之前,不能将 null 和 undefined 转换成其他任何值。

                                  • 如果有一个操作数是 NaN,则相等操作符返回 false,而不相等操作符返回 true。 重要提示:即使两个操作数都是 NaN,相等操作符也返回 false;因为按照规则, NaN 不等于 NaN。

                                  • 如果两个操作数都是对象,则比较它们是不是同一个对象。如果两个操作数都指向同一个对象,

                                    则相等操作符返回 true;否则,返回 false。

                                    表达式值
                                    null==undefinedtrue
                                    “NaN”==NaNfalse
                                    5==NaNfalse
                                    NaN==NaNfalse
                                    false==0true
                                    true==1true
                                    true==2false
                                    undefined==0false
                                    null==0false

                                    null == undefined 会返回 true,因为它们是类似的值;但 null === undefined 会返回 false,因为它们是不同类型的值。

                                    6 CONSOLE 控制台输入

                                    Console对象提供浏览器控制台的接入,不同浏览器是不一样的,这里介绍普遍存在的

                                    6.1 Console.assert()

                                    判断第一个参数是否为真,false的话抛出异常并且在控制台输出相应信息

                                    6.2 Console.clear()

                                    清空控制台

                                    6.3 Console.count()

                                    非标准

                                    以参数为标记记录调用的次数,调用时在控制台打印标识以及调用次数

                                    可以带一个参数

                                    6.4 Console.countReset()

                                    重置指定标签的计数器,若没有参数,就重置defaul

                                    这里是接着上面的

                                    6.5 Console.debug()

                                    控制台打印“debug”级别的日志消息 注:chrome58之后,只有打开了Verbose才看得到

                                    6.6 Console.dir()

                                    非标准

                                    在控制台中显示指定JavaScript对象的属性,并通过类似文件树样式的交互列表显示。

                                    6.7 Console.dirxml()

                                    非标准

                                    显示一个明确的XML/HTML元素的包括所有后代元素的交互树.如果无法作为一个element被显示,那么会以JavaScript对象的形式作为替代

                                    6.8 打印信息

                                    1. console.log() 向控制台输出一条信息
                                    2. console.info() 向web控制台输出一个通知信息
                                    3. console.error() 向控制台输出一条错误信息
                                    4. console.warn() 向控制台输出一条警告信息

                                    这4种用法都是一样的

                                    • 打印多个对象 console.log({first:“Bob”},{last:“Tony”})
                                      • 使用字符串替换(有点像c语言一样)

                                        %o 或 %O 打印js对象 %d 或 %i 打印整数 %s 打印字符串 %f 打印浮点数 Chrome不支持精确格式化

                                        • %c 定义打印样式 这里的样式应该是按照,css来写的

                                          6.9 打印树状结构

                                          • Console.group()

                                            打印树状结构,配合groupCollapsed以及groupEnd方法;

                                          • Console.groupCollapsed()

                                            同Console.group(),但是默认是折叠的

                                          • Console.groupEnd()

                                            结束当前Tree

                                            6.10 Console.table()

                                            将数据以表格形式显示,数组,对象,类数组对象都可以打印; console.table(data[,columns]);

                                            6.11 定时器

                                            console.time(“name”),带参就是定时器的名字,开始计时,不带参就是默认的defaul console.timeEnd(“name”),结束“name”计时器

                                            注:该方法在使用时不会将输出的时间返回到js,它只能用于控制台调试.请勿将该方法作为普通计时器或性能数据收集器的一部分.

                                            6.12 Console.trace()

                                            向控制台输出堆栈跟踪

                                            6.13 占位符

                                            占位符,是用某种特定规则的符号替代真正的内容来占位,看代码。

                                              console.log('%d年%d月%d日',2020,03,30);  //  2020年3月30日

                                            这里的 %d(还有%i) 代表整数,它还支持字符串(%s)、浮点数(%f)和对象(%o)。

                                            let person = {  name:'idea',  age:18}console.log("%o可以用来创建人的类",person);  //  {name: "idea", age: 18}可以用来创建人的类

                                            占位符跟函数中的参数作用差不多,方便了数据的引用和操作。

                                            什么?你说的是那个样式吗?对,是那个样式~

                                            语法是:console.log("%c内容",样式)

                                            这里%c起到了关键作用,它的功能是根据提供的样式代码对输出内容进行格式化。

                                            console.log("%c3D Text"," text-shadow: 0 1px 0 #ccc,0 2px 0 #c9c9c9,0 3px 0 #bbb,0 4px 0 #b9b9b9,0 5px 0 #aaa,0 6px 1px rgba(0,0,0,.1),0 0 5px rgba(0,0,0,.1),0 1px 3px rgba(0,0,0,.3),0 3px 5px rgba(0,0,0,.2),0 5px 10px rgba(0,0,0,.25),0 10px 10px rgba(0,0,0,.2),0 20px 20px rgba(0,0,0,.15);font-size:5em");

                                            控制台里就能看到如下炫酷的效果:

                                            有点意思吧,不过这个效果是拿来做试验的,略显招摇,没有实际用途,如果你想自定义输出的字体,改个字号和颜色就好。



                                            参考 : http://bclary.com/log/2004/11/07/#a-11.9.3


上一篇:腾讯邮箱怎么公司职务?

下一篇:探寻规约源码的神秘之旅揭秘真相