JS中的计算只能取到合理近似值(误差很小),请理性看待,合理使用
.1+.2;//0.30000000000000004
Math是一个JavaScript内置对象,在window对象下的一个属性
Math === window.Math
数学中我们常用的计算以及参数都会保存在Math对象中。
圆周率π和自然常数e
Math.PI;//3.1415926...
//计算面积,概率都会用到
Math.E;//2.71828182...
//计算指数对数都会用到
计算开方结果
Math.sqrt(2)*Math.sqrt(2);//2.0000000000000004约等于2
Math.pow(2,3);//2的3次方
计算相对位置,角度,游戏中常用到的边界碰撞判断等。
弧度制:弧度是一个角的张开程度,单位rad通常省略。有正负。
规定平面内一条线段绕端点旋转一周回到初始位置所扫过的角度为Math.PI*2,对应360deg,逆时针为正,顺时针为负数。
正弦:Math.sin
某一角度的计算值。此角度(0,Math.PI/2)形成直角三角形对边除以斜边的值
Math.sin(Math.PI/6);//0.49999999999999994约等于0.5
余弦:Math.cos
某一角度的计算值。此角度(0,Math.PI/2)形成直角三角形邻边比斜边的值
Math.cos(Math.PI/3);//0.5000000000000001约等于0.5
正切:Math.tan
某一角度的计算值。此角度(0,Math.PI/2)形成直角三角形对边比邻的边的值
Math.tan(Math.PI/4);//0.9999999999999999约等于0.5
let rdm = Math.random();//
rdm = Math.random();
rdm = Math.random();
自行封装的随机数生成大于n小于m的随机数
let myRandom = (n = 0,m = 1)=>(Math.random()*(m-n)+n)
思考: 投出一个色子,6的概率为50%,1的概率3%,怎么实现?
Math.floor(3.15);//3
Math.floor(-2.3);//-3
let arr = [1,3,4,99,0]
Math.max(...arr);//0
Math.min(...arr);//99
Math.max.apply(null, arr)
parseInt和parseFloat
解析传入的字符串,返回一个符合要求的10进制数,解析不出来返回NaN
paseInt 返回整数
传入两个参数: 第一个是需要解析的字符串,必填
第二个是进制基数2-36(0-9,a-z),当前传入的字符串的进制是多少,不填默认是10
parseInt("1123.asdasd");//1123
parseInt("a123");//NaN
parseInt("Infinity");//NaN
parseInt("123",16);//以16进制识别123,值为1*16*16+2*16^1+3
parseInt("zzz",36);//以36进制识别zzz,值为35*36*16+35*36+35
parseInt(123,2);//123转字符串"123",2进制识别1 转2进制 1*Math.pow(2,0)
paseFloat返回带小数点的浮点类型
返回整数或者小数,支持科学记数法,解析不出来返回NaN
parseFloat("123.231");//123.231
parseFloat({toString(){return 1}});//1 底层是对传入的参数使用toString方法,或者valueOf方法
parseFloat([1,23,5])// 1
parseFloat("asd");//NaN
parseFloat("2e-3");//0.003
parseFloat("2.32E3");//2320
parseFloat("0x13");//0
保留小数点: (num).toFixed(n)
或者用正则: (num).toString().match(/.*…{3}/)
指数运算公式 ** :(es6新出,支持赋值)
Math.pow(3,4);//81
3**4;//81
let a = 2;
a**=3;//8
//等同于 a=a**3;
JS的代码是什么时候执行的?除了触发执行,代码都是在页面加载的时候瞬间执行完了。
我们需要控制在某个固定的时刻往进程中添加代码执行。
setTimeout执行之后返回一个正整数,是定时器的编号,可以用这个编号清除定时器,不同的定时器编号会累加
第一个参数是需要执行的代码或者回调函数,必须,
第二个参数是延时,不写默认为0,单位毫秒(1s = 1000ms)
第三个以后是需要执行的代码传入的参数
let foo = (x,y) =>console.log(x+y)
setTimeout(foo,1000,2,3)//返回一个正整数定时器编号
//1s之后打印出5
setTimeout(foo,1000,...[2,3])
setTimeout(()=>foo(2,3),1000)
因为
window.setTimeout === setTimeout;//true
这里不管在哪调用setTimeout的主体是window
let o = {a:1}
function foo(){
setTimeout(function(){
console.log(this);
},1000)
}
foo.call(o);//这里指向window
因为是window调用的setTimeout所以不可以修改。定时器永远是浏览器调用
解决方法:
let o = {a:1}
function foo(){
setTimeout(function(){
console.log(this);
}.bind(o),1000)//强行修改回调函数的this,返回的函数和原函数已经不是同一个了
}
foo();//这里指向o
或者:
let o = {a:1}
function foo(){
setTimeout(()=>{//硬绑定到foo上下文的this中
console.log(this);
},1000)
}
foo.call(o);//这里指向o
清除定时器:clearInterval传入一个参数,就是定时器的序号。页面唯一。
let timer = setTimeout(function(){},5000);
clearInterval(timer);//上面那个定时器就删掉了。
运行代码后每隔一段时间执行相应代码:setInterval,和setTimeout有相似性质
第一个参数是需要执行的代码或者回调函数,必须,
第二个参数是延时,不写默认为0,单位毫秒(1s = 1000ms)
第三个以后是需要执行的代码传入的参数
let timer = setInterval(function(a,b){
console.log(a+b);
},1000,2,3);//每隔1000ms打印依次5
clearInterval(timer);//通过定时器序号清除定时器
console.time()
console.timeEnd()//计时功能
首先说一下进程和线程的概念
计算机(不止)有两个东西:cpu和内存,cpu是计算资源(能进行多少的计算),内存是运行过程中的存储数据。维持电脑正常运行cpu(或者gpu)需要分配给不同软件不同的计算资源,就是通过进程控制的。
进程:浏览器这个软件打开的时候有多个进程的,不同的进程有不同的作用(比如:插件,界面,GPU等)。单独打开一个新页面的时候是单独分配了一个进程。(单页面崩溃)
线程: 一个进程里面有多个线程运行(异步线程,JS引擎,GUI渲染等)。其中有一个js引擎,掌控了所有的JS代码运行。
所以JS是单线程运行的,换句话说,同一时刻只能做一件事情。
for(let i = 0;i < 900000000;i++){}//页面卡死一小会,无法操作
虽然JS执行和浏览器渲染虽然不是同一个线程,但是JS涉及页面元素操作,修改操作完成之前渲染会被锁死,JS完成之后才会渲染。这就是单线程的性质。
什么是同步?
当读取到JS代码的时候:代码会从上往下执行,当前面的代码执行完成返回之前,后面的代码是不会执行的。其余操作也是不会执行的。
console.log(1);
console.log(2);
for(let i = 0;i < 900000000;i++){}//页面卡死一小会,无法操作
console.log(3);//在上行代码执行完成之前是不会打印的
//1 2 等一会儿 3
什么是异步?
异步的含义是相对于同步的,某行代码的执行单独开辟线程处理,与主线程无关,返回结果传递到主线程。但是JS运行是单线程的,所以不存在真正的异步
那么
console.log(1);
setTimeout(console.log,1000,2);
console.log(3);
//1 3 等一会儿 2
3明明在2之前执行并且定时器等了1000ms打印出了2,这不就是异步吗?
这是JS的魔法,它用了一些神奇操作实现了上述代码
这里要说一个东西:执行队列。
JS运行是单线程的,JS执行的时候会依照一个顺序执行:
先执行完同步队列----->再执行异步队列
浏览器执行同步队列里的代码,
当遇到setTimeout或者setInterval或者点击事件等,会在必要的时刻将代码标识扔到异步队列中,异步代码会返回结果表示代码执行完成,实际代码没有执行。
同步执行完成会处于空闲状态。
处于空闲状态(执行间隙)才会不停扫描异步队列,将扫描到的标识为需要执行的异步代码执行