汇总作者发布的 CS (主要是前端)学习博文,一起学习交流,欢迎 Star**~~
tangxiaolang101 / ethanblog Goto Github PK
View Code? Open in Web Editor NEW唐小狼(Ethan)的博客
唐小狼(Ethan)的博客
汇总作者发布的 CS (主要是前端)学习博文,一起学习交流,欢迎 Star**~~
前言:我们在日常开发中,经常会遇到字节单位换算的场景。一般用简单的除法来计算时,都会遇到计算精度的问题。有关 JavaScript 浮点数陷阱 的问题,看一参考一下这篇不错的文章。下面,我们着重要将的是一种精确字节单位换算的详解:
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 的量级,等等类推,后续做了一些保留小数位的优化等等,就不再赘述了,欢迎大家共同交流类似有趣的代码~~
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的两个答案,合起来能很好的理解这个问题。
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!
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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.