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

Posted 前端呆头鹅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了同事读不懂我的代码了,全因我读了这篇文章相关的知识,希望对你有一定的参考价值。

文章目录

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)

这段代码结果就是 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

使用这种方法,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

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

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

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

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

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

访问器属性可以通过两个函数来定义,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

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)

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

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

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);

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()

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

var a = 1
var showThis = () => 
    console.log(a);
    ...

showThis()

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

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

var o =   
    b: 1,  
    showThis: showThis

o.showThis();

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

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

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

以上是关于同事读不懂我的代码了,全因我读了这篇文章的主要内容,如果未能解决你的问题,请参考以下文章

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

读了这一篇,让你少踩 ArrayList 的那些坑

读了这一篇,让你少踩 ArrayList 的那些坑

作为一个程序员,读不懂Spring就像读不懂对象的心?

拼图数量增加,拼图游戏中拼图大小增加

程序员修炼之道第一章读后感