Giter Site home page Giter Site logo

ethanblog's Introduction

ethanblog's People

Stargazers

tangxiaolang avatar

Watchers

James Cloos avatar tangxiaolang avatar

ethanblog's Issues

JavaScript 字节单位换算函数【详解】

前言:我们在日常开发中,经常会遇到字节单位换算的场景。一般用简单的除法来计算时,都会遇到计算精度的问题。有关 JavaScript 浮点数陷阱 的问题,看一参考一下这篇不错的文章。下面,我们着重要将的是一种精确字节单位换算的详解:

1. 先看代码

const byteConvert = function(bytes) {
    if (isNaN(bytes)) {
        return '';
    }
    let symbols = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
    let exp = Math.floor(Math.log(bytes)/Math.log(2));
    if (exp < 1) {
        exp = 0;
    }
    let i = Math.floor(exp / 10);
    bytes = bytes / Math.pow(2, 10 * i);

    if (bytes.toString().length > bytes.toFixed(2).toString().length) {
        bytes = bytes.toFixed(2);
    }
    return bytes + ' ' + symbols[i];
};

// 函数调用
byteConvert(bytes);

这段代码很好用,而且也是网上普遍流传的一种方法,我们下面就详细了解一下,为什么这段代码可以实现这种效果呢?

我们可以看到,这个函数中的核心运算是对数运算和指数运算,JavaScript 中的 Math.log() 函数是对数运算,需要强调的一点是,它是自然对数运算(以 e 为底)。

我们都知道,1024 = 2^10,那么进行对数运算就会变为:

接下来就需要理解这行核心代码了:let exp = Math.floor(Math.log(bytes)/Math.log(2));。理解它之前,我们需要搬出来对数运算的一个重要推论——换底公式,如下:

现在是不是很明了了,Math.log(bytes)/Math.log(2) 其实就是再求 bytes 以 2 为底的指数,我们换算一下,如下:

最后的 exp 就是我们得到的指数了。exp 为 10 时,bytes 就是 1024。所以后面的运算都是依据 10 这个单位量来计算的。i 为 1 就是最起码有一个 KB 的量级了,i 为 2 就是最起码有一个 MB 的量级,等等类推,后续做了一些保留小数位的优化等等,就不再赘述了,欢迎大家共同交流类似有趣的代码~~

JavaScript closure的一个问题

function f1() {
    var n = 999;
    nAdd = function() {
        n += 1
    }
    function f2() {
        alert(n);
    }
    return f2;
}
var result1 = f1();
var result2 = f1();
var result3 = f1();
nAdd();
result1();  //999
result2(); //999
result3(); //1000

以上是困惑的问题?为什么nAdd()影响最近的闭包。
stackoverflow的两个答案,合起来能很好的理解这个问题。

1.进一步明白细节的回答


It has to do with when nAdd is assigned the function. Note that when you create a closure, a new “copy” (for lack of a better word) of the local variables are created. Thus, result1’s n is different from result2s n which is different from result3’s n. They are seperate, and each closure cannot access another closure’s n.

Look at this line:

nAdd = function() {
     n += 1;
}

This assigns nAdd a new closure each time. Each time, this closure will only affect the most recent “copy” of n.
So when you are doing.

var result1 = f1(); // assign nAdd for the first time, referring to result1's n.
var result2 = f1(); // re-assign nAdd, now it affects result2's n.
var result3 = f1(); // re-assign nAdd, now it affect result3's n.

nAdd got assigned a new closure each time. The last time, nAdd got assigned a closure with result3’s copy of n.
Thus, when you do nAdd(), you only increment result3’s n.
Here’s an example that might clear things up.

function f1() {
    var n = 999;
    nAdd = function() {
        n += 1
    }
    function f2() {
        alert(n);
    }
    return f2;
}
var result1 = f1();
var nAdd1 = nAdd;
var result2 = f1();
var nAdd2 = nAdd;
var result3 = f1();
var nAdd3 = nAdd;
nAdd3();
result1();  //999
result2(); //999
result3(); //1000
nAdd1();
result1(); // 1000
nAdd1();
result1(); // 1001
nAdd2();
result2(); // 1000
nAdd();
result3(); // 1001 (the most recent nAdd result3's n).

To further elaborate, consider what would happen if you did this instead:

var result1 = f1();
nAdd();
var result2 = f1();
var result3 = f1();
result1(); // 1000
result2(); // 999
result3(); //999

Or this:

var result1 = f1();
var result2 = f1();
nAdd();
var result3 = f1();
result1(); // 999
result2(); // 1000
result3(); // 999

It becomes obvious that nAdd updates only the most recent invocation’s n!

2.调用本质的回答


First, you need to be clear about the following thing:

nAdd is a global scoped function. But it is using a local scoped variable n.

Every time you re-create f1(), the pointer of nAdd function will change.

Finally it will changed to the closest f1() closure and the n variable inside nAdd function will also point to the closest f1() closure. So it can only change the value of the closest one.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.