Javascript概述

  • JavaScript在1995年由Netscape公司的[Brendan Eich](https://baike.baidu.com/item/Brendan Eich),在网景导航者浏览器上首次设计实现而成。因为Netscape与Sun合作,Netscape管理层希望它外观看起来像Java,因此取名为JavaScript。
  • JavaScript的标准是ECMAScript 。截至 2012 年,所有浏览器都完整的支持ECMAScript 5.1,旧版本的浏览器至少支持ECMAScript 3 标准。2015年6月17日,ECMA国际组织发布了ECMAScript的第六版,该版本正式名称为 ECMAScript 2015,但通常被称为ECMAScript 6 或者ES6。
  • JavaScript(简称“JS”) 是一种具有函数优先的轻量级,解释型或即时编译型的高级编程语言。虽然它是作为开发Web页面的脚本语言而出名的,但是它也被用到了很多非浏览器环境中,JavaScript 基于原型编程、多范式的动态脚本语言,并且支持面向对象、命令式和声明式(如函数式编程)风格。

JavaScript变量的定义

<script type="text/javascript">
        'use strict' //设置严格检查模式,可以检查语法,更加严谨,推荐使用,必须写在第一行,首先需要检查IDEA中是否默认设置ES6语法
        //全局变量的定义
        //变量名定义规范和Java一样,可以用汉字命名,不推荐
		var a = 6;
        var b = "hello world";
        var flag = true;
		i = 0; //直接这样写,默认也是全局变量

        //局部变量的定义
        let num = 6;
        let bool = false;
        let str = "hello world";

        //常量的定义
        const tt = 8;
        const yy = "hello world";
        const zz = false;
 </script>

JavaScript的数据类型与运算符

  • Javascript中所有的键都是字符串,值是任意对象!
  • 数值类型:number(不区分小数,整数,负数)
123 //整数
123.23//小数
123.3e2 // 科学计数法
-99 //负数
NaN  // not a Number
Infinity //表示无限大
  • 字符串
  • 转义字符
//正常的字符串我们使用单引号或双引号包裹
var str1 = 'abc'; var str2 = "abc";
//注意转义字符
\` //可以输出一个点
\n //换行
\t //缩进
\u4e2d //u#### Unicode字符
\x41 //Ascall字符
  • 多行字符串(ES6新增语法)
<script>
	//多行字符串
    var msg =` nihao
        	hello  
        world
`;
</script>
  • 模板字符串
<script>
	let name = 'lucy';
	let age = 5;
	let msg = `我的名字叫,${name}`;
</script>
  • 字符串常用方法
var str = "student";
console.log(str.length);//输出字符串的长度 7
console.log(str[0]);//输出s
console.log(str.toUpperCase());//输出STUDENT,转换为大写
console.log(str.toLowerCase());//输出student,转换为小写
console.log(str.indexOf('t'));//输出1,获取字符下标
console.log(str.substring(1));//输出tudent,截取下标1之后所有的字符
console.log(str.substring(1,3));//输出tu,包前不包后,[)
  • 字符串的不可变性,跟Java一样
var str = "student";
str[0] = 1;
console.log(str);//输出student ,说明字符串没有被改变
  • 布尔值
true false
  • 逻辑运算(与或非)
&&  //两个都为真,结果才为真
||  //一个为真,结果为真
!   //真即假,假即真
  • 比较运算符与赋值运算符
=  //表示赋值符号
==  //等于(类型不一样,值一样,结果为True)
===  //绝对等于(必须类型和值都一样,结果才为True),推荐使用
    须知:NaN === NaN ,这个与所有的数值都不相等,包括自己
	只能通过isNaN()这个函数来判断当前变量是否是一个NaN
同时尽量避免使用小数进行运算,存在精度的问题
  • null和undefined(未定义)
  • 数组(Java的数组定义必须是相同类型的元素,而JavaScript不需要)
//数组的定义
var arr1 = [1,2,"hello",true,9.4,-1,null];
var arr2 = new Array(1,2,"hello",true,9.4,-1,null);
console.log(arr1[0]); //输出1
console.log(arr1[8]); //输出undefined,超过下标或小于0的输出undefined
  • 数组的长度
var arr = [1,2,3,4,5,6];
console.log(arr.length); //输出6
arr.length = 10;//假如给arr.length赋值,数组长度会发生变化
//在浏览器中测试
var arr = [1,2,3,4,5];
console.log(arr)
VM507:1 (5) [1, 2, 3, 4, 5]
undefined
arr.length=10
10
console.log(arr)
VM626:1 (10) [1, 2, 3, 4, 5, empty × 5]
console.log(arr[6])
VM700:1 undefined
//当赋值的长度小于数组长度时,则会造成数据丢失
arr.length = 3
3
console.log(arr)
VM849:1 (3) [1, 2, 3]
  • 常用方法
//定义数组
//indexOf() 方法
var arr = [1,2,3,4,5,6]; 
console.log(arr)
VM1161:1 (6) [1, 2, 3, 4, 5, 6]
console.log(arr.indexOf(1)) //获取元素所在下标
VM1243:1 0
console.log(arr.indexOf("rr")) //当元素不存在时,下标为 -1
VM1258:1 -1

//slice() 方法 截取数组的一部分,返回一个新数组,原数组不受影响
arr.slice(3)
(3) [4, 5, 6]
console.log(arr)
VM1377:1 (6) [1, 2, 3, 4, 5, 6]

//往数组中添加值,弹出值 头部
//push()  往数组尾部追加值
arr.push("a","b")
8
console.log(arr)
VM1469:1 (8) [1, 2, 3, 4, 5, 6, "a", "b"]
//pop()  弹出尾部某个值,弹出后,数组中就没了
arr.pop("b")
"b"
console.log(arr)
VM1518:1 (7) [1, 2, 3, 4, 5, 6, "a"]

//往数组中添加值,弹出值 尾部
//unshift()  往数组头部追加值
arr.unshift("q","w")
9
console.log(arr)
VM1613:1 (9) ["q", "w", 1, 2, 3, 4, 5, 6, "a"]
//shift()  弹出头部某个值,弹出后,数组中就没了
arr.shift("q")
"q"
console.log(arr)
VM1648:1 (8) ["w", 1, 2, 3, 4, 5, 6, "a"]

//排序 sort()
var str = ["d","a","c","b"];
console.log(str)
VM1830:1 (4) ["d", "a", "c", "b"]
str.sort()
(4) ["a", "b", "c", "d"]

//元素反转 reverse()
console.log(str)
VM1878:1 (4) ["a", "b", "c", "d"]
str.reverse()
(4) ["d", "c", "b", "a"]

//拼接 concat()
str.concat(1,2,3)
(7) ["d", "c", "b", "a", 1, 2, 3] 
console.log(str)
VM2012:1 (4) ["d", "c", "b", "a"] //只是返回一个新数组,原数组并未发生变化

//连接符 join()
str.join("-")
"d-c-b-a"

//多维数组
var arr = [[1,2],[3,4],["5","6"]]
undefined
console.log(arr)
VM2188:1 (3) [Array(2), Array(2), Array(2)]0: (2) [1, 2]1: (2) [3, 4]2: (2) ["5", "6"]length: 3__proto__: Array(0)
undefined
console.log(arr[1][1])
VM2215:1 4

//遍历数组
 // for循环
 let arr=[2,4,6,10];
    for(let i=0;i<arr.length;i++){
        console.log(arr[i]);
    }

 //for-in 循环
    let arr=[2,4,6,10];
    for (let index in arr){
        console.log(index); //输出索引
        console.log(arr[index]); //输出对应值
    }
 //for-of 循环(ES6新增)  不支持普通对象遍历,如果想要遍历普通对象,使用for-in
	let arr=[3,7,9];
    for (let key of arr){
        consol.log(arr[key]);
    }

 //forEach遍历
    let arr=[1,2,3,4,5,6];
    arr.forEach(function(result){
        console.log(result);
    })
  • 对象(若干个键值对)
//JS中的对象,{.....}表示一个对象,使用键值对描述属性 xxx:xxx,多个属性之间使用逗号隔开,最后一个不用加
//定义对象 
var person={
    name: "lucy",
    age: 18,
    sex: "女",
    tags: ['js','java','html']
}

 console.log(person.name);//输出lucy
 console.log(person.xxx);//使用一个不存在的对象属性,不会报错,输出undefined
//动态的删减属性,通过delete删除对象属性
var person ={name:"zs",age:10,sex:"男"}
person
{name: "zs", age: 10, sex: "男"}
delete person.sex
true
person
{name: "zs", age: 10}
//动态添加属性,直接给新属性赋值即可
person.score = 100
100
person
{name: "zs", age: 10, score: 100}

//判断属性值是否存在这个对象中 xxx in 对象名  返回true和false
person
{name: "zs", age: 10, score: 100}
"name" in person
true
"toString" in person //继承性,找到父类的方法
true

//判断一个属性是否是这个对象自身拥有的 hasOwnProperty()
person.hasOwnProperty("name")
true
  • Map和Set(ES6新增)
//Map
var map = new Map[['tom',100],['jack',90],['lucy',80]];
console.log(map.get('tom')); //通过key获取value,输出100
map.set('admin',88); //新增一条数据
set.delete('tom'); //删除数组中的一个数值

//Set 无序不重复
var set = new Set([1,2,3,4,4,4,4]);
console.log(set); //输出1,2,3,4,重复的排除掉了
set.has(2)//输出 true,判断是否包含某个元素
set.add()5; //新增一个值,添加重复的添加不进去
set.delete(1); //删除数组中的一个数值
  • iterator(遍历迭代集合)
//通过for of  遍历  for  in 输出下标
var arr = [3,4,5];
for(let x of arr){
    console.log(x); //输出3,4,5
}

//遍历map
var map = new Map[['tom',100],['jack',90],['lucy',80]];
for(let x of arr){
    console.log(x); //输出['tom',100],['jack',90],['lucy',80]
}

//遍历set
var set = new Set([5,6,7]);
for(let x of set){
    console.log(x); //输出5,6,7
}

函数

  • 方法:在对象中(属性,方法)
  • 函数的定义
//绝对值函数 ,如果不输入,则输出NaN
//定义方式一
function abs(x){
    if(x > 0){
       return x;
    }else{
        return -x;
    }
}
//定义方式二,这是个匿名函数,但可以把结果赋值给abs,通过abs调用
var abs = function(x){
    if(x > 0){
       return x;
    }else{
        return -x;
    }
}

//调用
abs(10);//输出10
abs(20,40,10);//输出20,JavaScript中可以传递任意个参数,也可以不传递
//因此我们可以通过判断,手动抛出异常
var abs = function(x){
    if(typeof x!== 'number'){
    	throw 'Not a Number';  //手动抛出异常 
    }
    if(x > 0){
       return x;
    }else{
        return -x;
    }
}

//arguments关键字,代表所有传递进来的参数,是一个数组
var abs = function(x){
   for(let i=0;i<arguments.length;i++){
       console.log(arguments[i]);//输出每个输入的元素,可以通过length判断输入参数的个数
   }
    if(x > 0){
       return x;
    }else{
        return -x;
    }
}
	问题:arguments包含所有的参数,我们有时候想使用多余的参数来进行其他操作,需要排除已有参数,可以使用rest(ES6新特性)
// rest ,获取除了已经定义参数之外的所有参数
function aaa(a,b,...rest){
     console.log("a=>"+a);
    console.log("b=>"+b);
    console.log(rest);
}
//调用aaa()
aaa(1,2);//输出 a=> 1,b=> 2,[]
aaa(1,2,3,4,5,6);//输出 a=> 1,b=> 2,[3,4,5,6]
	注意:rest参数只能写在最后面,必须用...标识
  • 变量的作用域
//在函数体声明,则在函数体外不能使用(但是可以通过闭包解决)
function aa(){
    var x = 1;
    x = x + 1;
}
x = x + 2;//Uncaught ReferenceError:x is not defined  

//如果两个函数使用了相同的变量名,只要在函数内部,就不冲突
function aa1(){
    var x = 1;
    x = x + 1;
}
function aa2(){
    var x = 4;
    x = x + 4;
}

//内部函数可以访问外部函数的成员,反之则不行
function xx(){
    var x = 4;
   function aa2(){
        var y = 4 + x;//可以调用到
	}
    var z = y + 1; //不能调用到,Uncaught ReferenceError:x is not defined  
}

//内部函数变量名和外部函数的变量名 重名,函数会从自身开始查找,由内向外查找,假设外部存在,内部会屏蔽外部的变量
function aa1(){
    var x = A;
   function aa2(){
        var x = 'B';
       console.log(x);
	}
   console.log(x); 
    aa2();//调用函数,输出B
}
aa1();//调用函数,输出A

//提升变量的作用域
 function xx(){
     var x = 'x' + y;
     console.log(x); //输出xundefined,说明JS执行引擎自动提升了y的声明,但是不会提升y的赋值,所以我们要将所有的变量定义都放在函数头部,不要乱放,方便维护
     var y = 'y'; 
 }
  • 全局对象window
var x = 'xxx';
alert(x); //输出xxx
alert(window.x); //输出xxx,默认所有的全局变量都会自动绑定在window对象下,alter()本身也是window的一个变量 
var new_alert = window.alert();
new_alert(123);//输出123
window.alert = function(){
    
}
window.alert(123); //发现alert()失效了,因为被前面的覆盖了
//恢复
window.alert = new_alert;
window.alert(123);//正常输出

//由于我们所有的全局变量都会绑定到我们的window上,如果有多个不同的js文件,使用了相同的全局变量,则会造成冲突,如何解决?
//我们可以定义一个唯一全局对象,把自己的代码全部放入自己定义的唯一空间名字中,降低命名冲突
var myApp={};
//定义全局变量
myApp.name = 'lucy';
//定义全局方法
myApp.add = function(a,b){
    return a + b;
}
  • 局部作用域 let
function aa(){
    for(var i = 0;i<100;i++){
        console.log(i);
    }
     console.log(i+1); //输出101,出了这个作用域还可以使用?有问题
}

//使用let关键字解决
function aa(){
    for(let i = 0;i<100;i++){
        console.log(i);
    }
     console.log(i+1); //Uncaught ReferenceError:x is not defined
}
  • 常量 const
//在ES6之前,怎么定义常量:只要全部用大写字母命名的变量就是常量,建议不要修改值
//ES6后,使用const
const PI = '3.14'; //只读变量,不能修改

方法

  • 方法的定义
//方式一
var zs = {
    name: 'zs',
    birth: 2020,
    //方法的定义
    age:function(){
        //今年 - 出生的年
        var now = new Date().getFullYear();
        return now - this.birth;
    }
}

//调用时一定要带括号
zs.age(); 

//方式二
function getAge(){
    //今年 - 出生的年
    var now = new Date().getFullYear();
    return now - this.birth;
}

var zs = {
    name: 'zs',
    birth: 2020,
    //方法的定义
    age:getAge
}
//调用
zs.age();
//getAge() NaN  不能单独调用
//this是无法指向的,是默认指向调用它的那个对象,我们可以使用apply关键字控制this指向
getAge.apply(zs,[]);//可以调用,这时this指向了zs这个对象,参数为空
  • 内部对象
  • 标准对象
typeof 123
"number"
typeof '123'
"string"
typeof true
"boolean"
typeof NaN
"number"
typeof {}
"object"
typeof []
"object"
typeof Math.abs()
"number"
typeof Math.abs
"function"
typeof undefined
"undefined"
  • Date时间日期对象
var now = new Date();
console.log(now);//Wed Sep 23 2020 11:17:09 GMT+0800 (中国标准时间)
now.getFullYear();//年
now.getMonth();//月 0~11 使用时 +1
now.getDate();//日
now.getDay();//星期几
now.getHours();// 时
now.getMinutes();//分
now.getSeconds();//秒
now.getTime();// 时间戳 全世界统一  从1970 01.01 00:00:00 到现在的毫秒数

new Date(1600831029703); //时间戳转时间 Wed Sep 23 2020 11:26:53 GMT+0800 (中国标准时间)

//查看当前时间 年月日  时分秒
now.toLocaleString();//"2020/9/23 上午11:17:09"
now.toLocaleDateString();//"2020/9/23"
now.toLocaleTimeString();//"上午11:17:09"

JSON

  • JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。
  • 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。
  • 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
//定义一个用户对象
var user ={
 	name: 'zs',
    age: 18,
    sex: '男'
}
console.log(user);
VM1926:1 {name: "zs", age: 18, sex: "男"}
//将对象转化为json字符串
var json_user = JSON.stringify(user);
console.log(json_user);
VM1969:1 {"name":"zs","age":18,"sex":"男"}

//将Json字符串转换为对象,参数为字符串
JSON.parse(json_user); 或者 JSON.parse('{"name":"zs","age":18,"sex":"男"}');//输出{name: "zs", age: 18, sex: "男"}

//JSON和JS对象的区别
var obj ={name: "zs", age: 18, sex: "男"};
var json = '{"name": "zs", "age": "18", "sex": "男"}';

面向对象编程

  • 原型
//定义一个原型,类似于Java中的父类
var person ={
    name:'',
    age:'',
    run:function(){
        console.log(this.name+"runing...");
    }
}

//创建zs对象
var zs = {
    name:'zs',
    age:18
}

//创建ls对象
var ls = {
    name:'ls',
    age:20
}
//指定zs的原型是person 类似于Java中的继承
zs.__proto__ =person;
//指定ls的原型是person
ls.__proto__ =person;
zs.run(); //输出 zsrunning...
ls.run(); //输出 lsrunning...
  • class 继承(ES6引入,但是其本质还是原型__ proto__)
//定义一个学生类
class Student{
    constructor(name){
        this.name = name;
    }
    hello(){
        alert('hello');
    }
}

//实例化一个对象
var zs = new Student('zs');
zs.name //输出zs
zs.hello() //弹出hello

//继承
class wb extends Student{
     constructor(name,grade){
         super(name);
        this.grade = grade;
    }
    study(){
       console.log('study...');
    }
}
  • 原型链

javascriptz javascript中文名称_javascriptz

操作BOM对象

  • BOM(Browser Object Model),浏览器对象模型
  • Window对象,代表浏览器窗口
//浏览器窗口大小
window.innerWidth
768
window.innerHeight
160
window.outerWidth
784
window.outerHeight
840
  • Navigator,封装了浏览器的信息
//浏览器的信息,不建议使用这些属性来判断和编写代码
navigator.appName
"Netscape"
navigator.appVersion
"5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36"
navigator.userAgent
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36"
navigator.platform
"Win32"
  • screen,屏幕尺寸信息 ,单位像素px
//屏幕信息
screen.width
1536
screen.height
864
  • location,代表当前页面的URL信息
location.reload();//重新加载
location.assign('https://.....');//设置新的地址
  • document,代表当前的页面,HTML DOM文档树
//显示当前页面的标题
document.title
"百度翻译_百度搜索"

//可以获取具体的文档树节点
document.getElementById(); //通过id获取,返回一个
document.getElementsByClassName(); //通过class获取,返回数组
document.getElementsByTagName(); //通过标签名获取,返回伪数组,如果想调用数组的方法,方式一:console.log(Array.prototype.slice.call(divObjs));  方式二(ES6语法):console.log(Array.from(divObjs));  //此方法IE不支持

//document 得到cookie
document.cookie

//劫持cookie原理,某些恶意的网站中有一段js用来获取你的cookie,然后上传到他的服务器
//解决方式:服务器端可以设置cookie:httpOnly
  • history
history.back(); //后退
history.go(-1);//后退
history.go(1);//前进
history.forward();//前进

操作DOM对象

  • DOM(Document Object Model),文档对象模型
1.通过关系查找:
	a、父子关系:
		父节点:parentNode
		子节点:firstChild 第一个子节点
			lastChild  最后一个子节点
			childNodes.length 所有子节点的长度
			childNodes[0]
			childNodes[childNodes.length-1]
		表格有默认的 tbody节点
	b、兄弟关系:
		上一个兄弟:previousSibling
		下一个兄弟:nextSibling
2.在DOM中最大的节点叫做document(window不属于dom的范畴)
3.节点的使用:
	查看标签名
			document.getElementsByTagName
			对象.tagName
    查看节点名
            节点 -- node
            对象.nodeName
4.节点操作
		a).获得对象下所有的子节点
			child: 子
			node: 节点
			对象.childNodes

		注意:
			table标签下即使没有编写tbody系统会默认加上tbody标签
			所有的tr将自动存放在tbody中
		
		b).获得对象的父节点
			parent: 父
			node: 节点
			对象.parentNode

		注意:
			一个节点只有唯一的一个父节点

		c).删除节点
		
		注意:
			DOM为删除子节点编写了方法,但是没有删除父节点的方法,也没有删除自己这个节点的方法.
			删除多个节点的时候,children节点的下标是在时刻变化的

		remove: 移除
		child: 子

		父节点对象.removeChild(子节点对象);

		body.removeChild(html); --不能大逆不道删除父节点
		body.removeChild(head); --不能手足相残删除兄弟(平级标签)
		body.removeChild(body); --不能自杀
		body.removeChild(table);
		table.removeChild(tbody);
innerText  //不会转义
innerHTML //会将其中的标签转义

节点对象.style.属性名 = 'xxx'; //可以通过节点对象操作节点的CSS样式,注意属性使用驼峰命名
		d).创建节点
		    创建新的子节点
				document.createElement("标签名");
			I.追加节点
				append: 追加/拼接
				父节点.appendChild(新的子节点);

			II.插入节点
				Before--之前
				父节点.insertBefore(新的子节点,目标子节点);
			III.替换节点
				替换: replace
				父节点.replaceChild(新的子节点,旧的子节点)
			IV.克隆节点
				克隆: clone (复制一份一毛一样的节点)
				1).只克隆自己本身节点
					节点.cloneNode(false)
					cloneNode方法有返回值,返回一个和节点一模一样的新的节点

				2).克隆字节节点和自己的所有子节点
					节点.cloneNode(true)

操作表单(验证)

  • 普通验证,对一些字符判断不能为空
<form action="#" method="post" onsubmit="return check()"></form>
<script>
	function check(){
        //验证表单操作....
        return true;//true提交表单 反之false不提交表单
    }
</script>
  • 密码框使用MD5加密
<!--导入MD5的js -->
<script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.js"></script>

<!-- 前台获取到密码进行加密 -->
var pwd = document.getElementById("pwd");
pwd.value = md5(pwd.value);  //这种情况会导致提交表单的一瞬间密码框的显示很多字符
	解决:可以使用一个隐藏框来用作MD5加密操作
密码:<input id="pwd" type="password"/>
    <input type="hidden" id="md5-passrword"/>

<!-- 获取和加密的时候-->
<script>
    var pwd = document.getElementById("pwd");
    var md5pwd = document.getElementById("md5-passrword");
    md5pwd.value = md5(pwd.value);
</script>
  • 小数计算的问题
  • 示例
// 加法 =====================
// 0.1 + 0.2 = 0.30000000000000004
// 0.7 + 0.1 = 0.7999999999999999
// 0.2 + 0.4 = 0.6000000000000001
// 2.22 + 0.1 = 2.3200000000000003
 
// 减法 =====================
// 1.5 - 1.2 = 0.30000000000000004
// 0.3 - 0.2 = 0.09999999999999998
 
// 乘法 =====================
// 19.9 * 100 = 1989.9999999999998
// 19.9 * 10 * 10 = 1990
// 1306377.64 * 100 = 130637763.99999999
// 1306377.64 * 10 * 10 = 130637763.99999999
// 0.7 * 180 = 125.99999999999999
// 9.7 * 100 = 969.9999999999999
// 39.7 * 100 = 3970.0000000000005
 
// 除法 =====================
// 0.3 / 0.1 = 2.9999999999999996
// 0.69 / 10 = 0.06899999999999999
  • 问题原因
  • JavaScript 里的数字是采用 IEEE 754 标准的 64 位双精度浮点数。该规范定义了浮点数的格式,对于64位的浮点数在内存中的表示,最高的1位是符号位,接着的11位是指数,剩下的52位为有效数字,具体:
  • 第0位:符号位, s 表示 ,0表示正数,1表示负数;
  • 第1位到第11位:储存指数部分, e 表示 ;
  • 第12位到第63位:储存小数部分(即有效数字),f 表示;
  • 解决方案
  • 一般像这种对精度要求比较高的数据 都会交由后端进行计算,因为后端有成熟的库来解决这种计算问题。
  • 前端常用toFixed()方法,该方法使用定点表示法来格式化一个数,会对结果进行四舍五入
num.toFixed(digits)
  • 参数 digits 表示小数点后数字的个数;介于 0 到 20 (包括)之间,实现环境可能支持更大范围。如果忽略该参数,则默认为 0。
  • 特别注意:返回一个数值的字符串表现形式,不使用指数记数法,而是在小数点后有 digits 位数字。该数值在必要时进行四舍五入,另外在必要时会用 0 来填充小数部分,以便小数部分有指定的位数。 如果数值大于 1e+21,该方法会简单调用 Number.prototype.toString()并返回一个指数记数法格式的字符串。