• 同事读不懂我的代码了,全因我读了这篇文章


    1 0.1 + 0.2 不是等于 0.3 么?为什么 JavaScript 里不是这样的?

    同样根据浮点数的定义,非整数的 Number 类型无法用 = 也不行) 来比较,console.log( 0.1 + 0.2 == 0.3)输出的结果是 false,这是由于浮点数运算的精度问题导致的。

    比较0.1+0.2 == 0.3的正确方式是使用 JavaScript 提供的最小精度值:

    console.log( Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON)
    
    • 1

    这段代码结果就是 true 了。

    2 救命!他的 for of 和我的不一样!

    for of 实质执行的是对象中key为Symbol.iterator的方法,该方法返回一个含有next方法的对象,next方法返回一个含有value和done的对象。

    for of会重复执行next函数,返回value的值,done是next函数终止的条件。

    下面是一个示范。

    var o = new Object
    
    o[Symbol.iterator] = function() {
        var v = 0
        return {
        next: function() {
                return { value: v++, done: v > 10 }
            }
        }        
    };
    
    for(var v of o) 
        console.log(v); // 0 1 2 3 ... 9
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    使用这种方法,for of 能做到的事情更多了,需要注意的是,你的同事可能会说:救命!他的 for of 怎么和我的不一样!。

    3 已知 b = { a: 5 },求 b > 3 为 true ?

    同事一段代码中,b = { a: 5 },后面在b > 3的比较中却为true,我的代码中却为false,这不科学。

    对象怎能与数字比较?

    实际是,这涉及到js的比较机制,js在比较前会进行类型的转换,而在对象到number、对象到string的转换时,会进行拆箱操作。

    简单的说,就是访问对象中的valueOf方法和toString方法,将其返回值用作对比。

    在对象到number的转换中优先使用valueOf方法,而在对象到string的转换时优先使用toString方法。

    重回问题,b = { a: 5 }得情况下,如何使 b > 3 呢?

    首先我们确定它的执行流程,先将b替换成b.valueOf(),然后做比较。

    那我们是不是修改valueOf()的返回值就可以了呢。

    我们为b对象添加一个valueOf函数,覆盖原生的valueOf。再进行比较。

    b.valueOf = function() {
        return this.a
    }
    
    console.log(b, b > 3)
    // {a: 5, valueOf: ƒ} true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    可以看到 b = { a: 5 }时, b > 3 为 true 了。

    4 a.num = 1 后,console.log(a.num) 输出为3 ?

    接下来的诡异事件是,当我将一个对象的属性赋值后,该对象属性却发生了和赋值不同的变化。

    a.num = 1
    console.log(a.num) // 3
    
    • 1
    • 2

    要清楚这一点,首先要清楚对象的属性分两种,数据属性和访问器属性,数据属性就是常用的属性。

    访问器属性可以通过两个函数来定义,get函数取属性值时被调用,set函数在设置属性值时被调用。

    get和set函数的返回值就是读或取得值,它允许使用者在写和读属性时,得到完全不同的值。

    回到刚才得问题,我写入了1,取到了3,可能是num属性实际为访问器属性。

    var a = { 
        _num: null,
        set num(val) {
            this._num = val + 2
        },
        get num() {
            return this._num
        }
    }
    
    a.num = 1
    console.log(a.num) // 3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    5 当promise遇上定时器,这代码让人挠头

    代码的执行顺序会影响执行结果,看看下面这段代码的执行结果是什么呢?

    new Promise(resolve => {
        console.log(1);
        setTimeout(() => console.log(2),0)
        Promise.resolve().then(() => console.log(3))
        resolve();
    }).then(() => console.log(4))
    console.log(5)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    promise用来实现异步操作,也就是操纵代码执行顺序的一种方式。

    promise接受一个回调函数,该回调函数会立刻执行,它是同步的。

    回调函数中接受一个参数res,res()意味着代码结束,可以进行接下来的异步逻辑了,异步逻辑通过then绑定。

    其中setTimeout会提交一个任务到等待队列,等代码全部执行完后,去执行等待队列可执行的逻辑。

    上面的代码中,执行结果为1、5、3、4、2,你猜对了吗?

    6 with:混乱的变量

    with实际上是不被推荐的使用,尤其是内部包含变量定义的时候。

    举个栗子。

    如果你要更改下面这段代码,代码当前的执行结果应该比较明了。

    var b = 1;
    void function(){ 
        var env = {b:1}; 
        b = 2; 
        console.log("In function b:", b); // 2
    }();
    console.log("Global b:", b); // 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    你在此基础上加了一段代码,猜一猜这次的执行结果是什么?

    var b = 1;
    void function(){ 
        var env = {b:1}; 
        b = 2; 
        console.log("In function b:", b); 
        with(env) { 
            var b = 3; 
            console.log("In with b:", b); 
        }
    }();
    console.log("Global b:", b);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    with中,创建b=3实际上是为env对象的b赋值,读取b是读取env对象的b属性,with创建了一个以env对象为基础的环境。

    但是with中声明的var变量也会被提升到function中,这意味着function中有了一个b。

    执行结果:
    In function b: 2
    In with b: 3
    Global b: 1

    7 用箭头定义函数后,代码崩了?

    函数定义方式有很多种。

    如果你看到下面的代码。

    var a = 1
    function showThis() {
        console.log(a);
    }
    showThis()
    
    • 1
    • 2
    • 3
    • 4
    • 5

    你一时觉得这样定义函数太麻烦了,顺手给改了。

    var a = 1
    var showThis = () => {
        console.log(a);
        ...
    }
    showThis()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    一运行,代码却崩了,这是为啥?

    仔细一看,下面还有一行。

    var o = {  
        b: 1,  
        showThis: showThis
    }
    o.showThis();
    
    • 1
    • 2
    • 3
    • 4
    • 5

    原来,箭头函数和普通函数不同的是,普通函数的this是指向调用者的,箭头函数的this的执向定义时的外界环境。

    将普通函数换为箭头的定义方式,该取的值取不到了,代码就崩了。

    在o.showThis()中,如果我们使用this.b去取值,使用箭头函数定义的showThis方法会到全局中找b,自然找不到。

  • 相关阅读:
    linux证书生成详解
    好用且强大——JNPF永远的神
    yolov1 论文精读 - You Only Look Once
    Redisson—分布式集合详述
    elementUI el-collapse 自定义折叠面板icon 和 样式 或文字展开收起
    Linux 基金会执行董事 Jim Zemlin:开源如何成为创新的关键推动力
    Excel VLOOKUP实用教程之 08 VLOOKUP如果实现区分大小写的查找?(教程含数据excel)
    Android问题笔记 - 关于Error type 3
    SherlockChain:基于高级AI实现的智能合约安全分析框架
    ThreadLocal使用及原理
  • 原文地址:https://blog.csdn.net/weixin_45809580/article/details/126933176