ECMAScript数据类型、数据类型转换、各种操作符、运算符及运算符优先级

掌握ECMAScript数据类型划分;掌握typeof运算符运算规则;掌握强制类型转化规则(parseInt(),parseFloat(),Number(),String(),Boolean())

JS三大核心:

  • ECMAScript : js的核心语法,数据类型,运算符,运算过程等。
  • DOM:文档对象模型,对页面元素进行的相关操作
  • BOM:浏览器对象模型。对浏览器的相关操作

1.数据类型

为什么要划分数据类型(不同类型的数据会有相关的不同特征及不同的操作方法,使用的地方也不一样)

ECMAScript数据类型划分(**):

  • 原始类型(基础类型,简单类型):
  1. Number:数字,可进行运算
  2. String:字符串,JS中一对引号之间的0到多个字符串
  3. Boolean:布尔值(true,false),可作为判断条件等
  4. null:空值,获取不到元素时就会返回null。对空值进行任何属性操作都会报错
  5. undefined:未定义,声明了变量但是未赋值
  6. symbol:ES6新增类型,代表唯一值
  • 复合类型(复杂类型):
  1. Object对象:Array数组,function函数,element元素,elements元素组,obj { key:val,key1:val1 }对象。对象可以存储任意、多种类型的值。

注:json本身是字符串,json不是对象,只是对象格式的字符串

对象写法:obj{

    key: 'val',

    key1:val1

}

对象获取:obj.key

注意:

  • 定义时值必须使用引号引起来,如果是数字,如年龄就不需要引号。
  • 将对象转为JSON使用JSON.stringify(obj)方法
var obj = {
            name : 'lmf',
            age : 26
        };
        console.info(obj.name+"年龄为:"+obj.age);//lmf年龄为:26
        console.info(JSON.stringify(obj));//将对象转为字符串 {"name":"lmf","age":26}

2.typeof 运算符

typeof运算符的六类数据类型:number、string、boolean、function、undefined、symbol、object

作用:用于检测数据的类型(注意:typeof检测的结果和标准规定略有差异

用法:typeof使用时不需要括号,typeof (nub);是为了提升运算优先级,而不是typeof本身有括号

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>typeof运算符</title>
</head>
<body>
    <div class="boxs"></div>
    <div class="ele"></div>
<script>
    // typeof运算符用于检测数据的类型(注意:typeof的检测结果和标准规定略有差异)
    var num = 100;
    console.log("num的类型是:"+typeof num);//Number 数字
    
    var str = 'abc';
    console.log("str的类型是:"+typeof str);//String 字符串

    var b = true;
    console.log("b的类型是:"+typeof b);//Boolean 布尔值

    var a;
    console.log("a的类型是:"+typeof a);//undefined 未定义(定义了未赋值)

    var s = Symbol();
    console.log("s的类型是:"+typeof s);//Symbol 唯一值

    var obj = {};
    console.log("obj对象的类型是:"+typeof obj);//Object对象:object对象

    var arr = ['a','b'];
    console.log("arr数组的类型是:"+typeof arr);//Object对象:数组

    var ele = document.querySelector(".ele");
    console.log("ele一个元素的类型是:"+typeof arr);//Object对象:一个元素

    var boxs = document.querySelectorAll(".boxs");
    console.log("boxs一组元素的类型是:"+typeof boxs);//Object对象:一组元素

    //typeof检测的数据类型和标准规定的差异
    console.log("---------------typeof检测的数据类型和标准规定的差异--------------");
    var box = document.querySelector(".box");
    console.log("没有box元素时的类型是:"+typeof box);//Object:标准定义中获取不到元素属于null类型,但是typeof是object类型

    var func = function (){};
    console.log("func函数的类型是:"+typeof func);//function:标准定义中函数时Object对象类型,但typeof是function类型
</script>
</body>
</html>

typeof检测的结果和标准规定差异:

  • 标准定义中获取不到元素属于null类型,但是typeof是object类型
  • 标准定义中函数是Object对象类型,但typeof是function类型

结果:

3.typeof案例

点击div让整个div往后移100px

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>typeof 小例子</title>
</head>
<body>
<div class="box" style="width: 100px; height: 100px; background: red; position: absolute; left:0; top:0; transition: .5s;"></div>
<script>
    //每次点击div,整个div往右移动100px(将div的left+100)
    var box = document.querySelector("div");
    //元素的with必须通过元素.offsetWidth进行获取,直接使用元素.style.width是获取不到的
    // var w = box.offsetWidth;
    box.onclick = function(){
        //如果样式写在style标签中,或者css样式文件中,是不能通过style.left获取到的
        var l = this.style.left;
        console.log(typeof l);//String
        console.log(typeof parseInt(l));

        //需要将其转为Number才能进行计算
        this.style.left = parseInt(l) + 100 + 'px';
    };
</script>
</body>
</html>

结果:通过元素获取到的值都是字符串,必须转换为Number才能进行计算

4.数据类型转换:把一种类型的数据,转换成另一种

数据转换为数字:parseInt(),parseFloat(),Number()

4.1Number parseInt(data[,radix]):

  • 返回值为Number 方法名(参数1[,可选参数2]),此处可选参数为进制。将数据转换成一个整数,数据类型是数字,data为要转换或者取整的数据;可选参数:radix data的进制;返回值为取整之后的结果

parseInt(data, radix) 将数据转换为整数返回(直接去掉小数点,不进行四舍五入):

- 第一个参数接受的是个字符串也就是我们要转换的数据

- 第二个参数 基数,也可以理解为 标注出我们要转换的这个字符串是几进制的数字

parseInt转换规律:

  1. 从左向右一位一位进行转换,遇到非数字就停止,然后将之前的数字提取出来,转换成数字;
  2. 如果从0位开始就不是数字,返回NaN(Not a numer这不是一个数字)
  3. 进制转换:0x是十六进制的标识,0-f。parseInt进行进制转换,不能定义转换成几进制,只是告诉parseInt方法定义的数据是几进制
  4. parseInt如果接收的是一个数字类型的数据,就只做取整,不去做进制转换
  5. parseInt转换的是其他类型的数据(字符串以外类型),会先转换成字符串,再执行parseInt。数组:直接去掉[],如果是空数组直接返回NaN,如果数组第一位不是合法数字也返回NaN
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>parseInt()测试</title>
</head>
<body>
    <script>
    //parseInt从左向右一位一位进行转换,遇到非数字就停止,然后把之前的数字提取出来,转成一个完成的数字
    var str = "10.1";
    console.log("10.1在 parseInt后的结果为:"+parseInt(str)); //10

    //遇到非数字就停止,然后把之前的数字提取出来,转成一个完成的数字
    var str1 = "111abc";
    console.log("111abc在 parseInt后的结果为:"+parseInt(str1));//111 

    //parseInt如果从第0位开始就不是数字,就直接返回NaN(不是一个数字)
    var str2 = "abc11";
    console.log("abc11在 parseInt后的结果为:"+parseInt(str2));//NaN 

    //parseInt进行进制转换,不能定义转换成几机制,只是告诉parseInt方法定义的数据是几进制
    //如此处,0xf是16进制,第二个参数只能写16(用于告诉parseInt方法定义的数据是几进制),写成其他的进制,都会返回0
    var str3 = "0xf";
    console.log("0xf在 parseInt后的结果为:"+parseInt(str3));//15

    //parseInt如果接受的是一个数字类型的数据,就只做取整,不去做进制转换
    var str4 = 0xf;
    console.log("0xf直接是数字类型时,在 parseInt转换后的结果为:"+parseInt(str4));//15

    //parseInt如果接收的是其他类型的数据(字符串以外类型),会先转换成字符串,再执行parseInt。
    //如果是数组,会直接去掉[],返回里面的数据;如果是空数组[],返回NaN;如果数组的第一位就不是合法数字,['a','1'],返回NaN
    var arr1 = ['1','1'];
    console.log("数组['1','1']parseInt后返回的数据为:"+parseInt(arr1));
    //如果是空数组[],返回NaN
    var arr2 = [];
    console.log("空数组[]parseInt后返回的数据为:"+parseInt(arr2));
    //如果数组的第一位就不是合法数字,['a','1'],返回NaN
    var arr3 = [];
    console.log("数组的第一位就不是合法数字,['a','1']parseInt后返回的数据为:"+parseInt(arr3));
    </script>
</body>
</html>

结果:

4.2parseFloat():parseFloat(string) 转换成浮点数(也就是小数)

  1. 转换规则参考parseInt(),比parseInt()可以多转换一个小数点,如果有多个小数点也只会转一位,parseFloat()不能进行精度计算(保留所有位数的小数,不进行四舍五入);
  2. parseFloat()不能转进制(因为小数不能进行进制转换);
  3. JS中小数的计算会有精度问题,需要使用toFixed(位数)方法进行解决,toFixed方法会进行四舍五入;
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>parseFloat()测试</title>
</head>
<body>
<script>
    // 转换规则参考parseInt(),比parseInt()可以多转换一个小数点,如果有多个小数点也只会转一位,parseFloat()不能进行精度计算(保留小数);
    var num1 = "10.0092";
    console.log("10.0092进行parseFloat()后的数据为:"+parseFloat(num1));//10.0092
    //如果有多个小数点也只会转一位
    var num2 = "10.009.3452";
    console.log("10.009.3452进行parseFloat()后的数据为:"+parseFloat(num2));//10.009
    // parseFloat()不能转进制(因为小数不能进行进制转换);
    // JS中小数的计算会有精度问题,需要使用toFixed(位数)方法进行解决;
    var a = "0.1";
    var b = "0.2";
    console.log("a*b为:"+parseFloat(a*b));//0.020000000000000004
    console.log("a*b toFixed后为:"+parseFloat(a*b).toFixed(2));//0.020000000000000004 toFixed方法会进行四舍五入
    // 小数不能进行进制转换
</script>  
</body>
</html>

结果:

 

4.3Number():将数据转换成数字

  • - 字符串类型,使用 Number() 转换时,规则如下:
  1. - 当整段字符串都符合数字规则时,转换为数字返回
  2. - 空字符串,直接返回 0
  3. - 其余情况,有一项不为数字,直接返回 NaN
  • - 布尔值类型,使用 Number() 转换时,true 返回 1,false 返回 0(除0以外的任何数字都返回true)
  • - null,使用 Number() 转换时 返回 0
  • - undefined,使用 Number() 转换时 返回 NaN
  • - 对象类型,使用 Number() 转换时,调用的对象的toString()方法,然后再依照前面字符串的转换规则进行转换
  • -Symbol类型不能使用Number()进行转换,会报错。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Number类型转换</title>
</head>
<body>
    <script>
        //字符串类型使用Number进行类型转换时:
        //1.当整段字符串都符合数字规则时,转换为数字进行返回
        var str = "1245";
        console.log("字符串类型,1245整个字符串都符合数字规则时,使用Number进行转换后:"+Number(str));//1245

        //2.当使用Number()转换空字符串时,直接返回0
        var str2 = "";
        console.log("使用Number()转换空字符串后:"+Number(str2));//0

        //3.其余情况,有一项不为数字,直接返回 NaN
        var str3 = "asd22";
        console.log("asd22使用Number()转换空字符串后:"+Number(str3));//NaN
        var str4 = "33re";
        console.log("33re使用Number()转换空字符串后:"+Number(str4));//NaN
        var str5 = NaN;
        console.log("NaN使用Number()转换空字符串后:"+Number(str5));//NaN

        //布尔值类型使用Number进行转换类型时:转换true返回1,转换false返回0(布尔值中,除了0以外的任何数字都是返回1)
        var b = true;
        console.log("b为true布尔值类型使用Number进行转换类型后:"+Number(b));//1
        var b1 = false;
        console.log("b1为false布尔值类型使用Number进行转换类型后:"+Number(b1));//0

        //null使用Number进行转换类型时,直接返回0
        console.log("null使用Number进行类型转换后:"+Number(null));//0

        //undefined使用number进行转换类型时,直接返回NaN
        console.log("undefined使用Number进行类型转换后:"+Number(undefined));//NaN

        //对象类型使用Number进行转换类型时,调用对象的toString()方法,然后再依照字符串的转换规则进行转换
        var arr = [];
        var arr1 = ['a','b'];
        var arr2 = ['1'];
        var arr3 = ['1','2'];
        console.log("空数组[]进行Number类型转换后:"+Number(arr));//0
        console.log("非数字类型数组进行Number类型转换后:"+Number(arr1));//NaN
        console.log("数字类型数组(只有一个元素)进行Number类型转换后:"+Number(arr2));//1
        console.log("数字类型数组(多个元素)进行Number类型转换后:"+Number(arr3));//1,2 -> NaN

        //对象类型函数使用Number进行类型转换时:
        var f = function(){};
        console.log("对象类型函数f使用Number进行类型转换后:"+Number(f));

        //object对象使用Number进行类型转换时:
        var obj = { name:'lmf',age:20};
        console.log("object对象{ name:'lmf',age:20}使用Number进行类型转换后:"+Number(obj));

        //一个元素使用Number进行类型转换时:
        var body = document.querySelector("body");
        console.log("一个元素document.querySelector('body')使用Number进行类型转换后:"+Number(body));

         //一组元素使用Number进行类型转换时:
         var bodys = document.querySelectorAll("body");
        console.log("一组元素document.querySelectorAll('body')使用Number进行类型转换后:"+Number(bodys));

        //Symbol类型不能进行Number类型转换
        var s = Symbol();
        console.log("Symbol使用Number进行类型转换后:"+Number(s));
    </script>
</body>
</html>

结果:

5.NaN和isNaN()

  • NaN是Number中的一个特殊值,NaN不是一个数字,但是NaN通过typeof后的数据类型是数字类型Number。
  • 使用 NaN 时,要注意 NaN 不等于任何值,包括它自己,也就是 NaN 不等于 NaN。
  • isNaN(val)如果val可以转成合法数字,就返回false,如果不能转化为合法数字,返回true;
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>NaN理解</title>
</head>
<body>
    <script>
        //NaN是Number中的一个特殊值,NaN不是一个数字,但是其typeof后的类型是数字(Number)
        console.log("NaN通过typeof的数据类型是"+ typeof NaN);//number

        //NaN 和 isNaN
        // - 在使用 NaN 时,要注意 NaN 不等于任何值,包括它自己,也就是 NaN 不等于 NaN。
        var a = NaN;
        console.log("检测a是否等于NaN:"+(a == NaN));//false
        console.log("检测a是否等于NaN:"+(a === NaN));//false

        // - 当我们要检测一条数据是否是 NaN 时,可以使用 isNaN(val) 来进行检测,
        //在 isNaN 方法中,传入的数据 能被转换成 合法数字时,就会返回 false,当传入的数据不能被转换成 合法数字( 也就是NaN) 时,isNaN 就会返回 true
        var b = "123";
        var c = "a123";
        var d = "123b";
        console.log("123被isNaN检测后:"+isNaN(b));//false
        console.log("a123被isNaN检测后:"+isNaN(c));//true
        console.log("123b被isNaN检测后:"+isNaN(d));//true
    </script>
</body>
</html>

结果:

6.Boolean转换为布尔值

  • - 数字类型:非零的合法数字转换为 true, 零代表 false, NaN 代表 false
  • - 字符串类型:空字符串转换为false,非空字符串转换为true
  • - null:转换为false
  • - 对象:转换为true。object空对象,空数组,空函数,空一组元素(未获得一组元素返回NodeList []),空Symbol都为true。但没有获取到一个元素返回的是null,Boolean转换后为false
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Boolean(val)转换成布尔值</title>
</head>
<body>
    <script>
        //  - 数字类型:非零的合法数字转换为 true, 零代表 false, NaN 代表 false
        var b = 1;
        console.log("1使用Boolean转换类型后为:"+Boolean(b));//true
        var b2 = -1;
        console.log("-1使用Boolean转换类型后为:"+Boolean(b2));//true
        var b3 = 0;
        console.log("0使用Boolean转换类型后为:"+Boolean(b3));//false
        var b4 = NaN;
        console.log("NaN使用Boolean转换类型后为:"+Boolean(b4));//false

        // - 字符串类型:空字符串转换为false,非空字符串转换为true
        var str1 = "";
        console.log("空字符串使用Boolean转换类型后为:"+Boolean(str1));//false
        var str2 = "abcd";
        console.log("非空字符串使用Boolean转换类型后为:"+Boolean(str2));//true

        // - null:转换为false
        console.log("null使用Boolean转换类型后为:"+Boolean(null));//false

        // - 对象:转换为true,即使是空的,如object空对象,空数组,空函数,一组元素(未获得一组元素返回NodeList []),Symbol都为true,但没有获取到一个元素是null,Boolean转换后为false
        var obj = {};
        console.log("对象object使用Boolean转换类型后为:"+Boolean(obj));//true
        var arr = [];
        console.log("arr数组使用Boolean转换类型后为:"+Boolean(arr));//true
        var box = document.querySelector(".box");
        console.log("box未获取到一个元素:"+box);
        console.log("一个元素使用Boolean转换类型后为:"+Boolean(box));//元素box不存在返回false
        var boxs = document.querySelectorAll(".box");
        console.log("box未获取到一组元素:"+boxs);//NodeList []
        console.log("一组元素使用Boolean转换类型后为:"+Boolean(boxs));//true
        var f = function(){};//true
        console.log("函数使用Boolean转换类型后为:"+Boolean(f));//true
        var s = Symbol();
        console.log("唯一值Symbol使用Boolean转换类型后为:"+Boolean(s));//true


    </script>
</body>
</html>

结果:

7.String(val) 转换成字符串

  • - 数字类型,直接转换数据类型原样返回
  • - undefined ,直接返回字符串 undefined。字符串undefined和类型undefined在控制台显示的颜色不一样
  • - null,直接返回字符串 null
  • - 布尔值,直接返回字符串 true 或者 false
  • - 函数,直接把整个函数变成字符串 返回
  • - 对象,直接调用对象的 toString 方法
  1. 对象1-{} [object,object]

  2. 对象2-元素对象 [object HTMLDivElement]

  3. 对象3-一组元素 [object NodeList]

  4. 对象4-数组:直接去掉方括号,把里面的值转为字符串。空数组,直接返回空字符串;一个元素,直接返回该元素;多个元素去掉[],返回所有元素且带有逗号“,”

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div class="box"></div>
    <div class="boxs"></div>
    <div class="boxs"></div>
    <script>
        // - 数字类型,直接转换数据类型原样返回
        var num = 11.02;
        console.log("数字类型11.02通过String类型转换后为:"+String(num)); //11.02
               
        // - undefined ,直接返回字符串 undefined
        console.log("undefined通过String类型转换后为:"+String(undefined)); //undefined

        // - null,直接返回字符串 null
        console.log("null通过String类型转换后为:"+String(null)); //null

        // - 布尔值,直接返回字符串 true 或者 false
        console.log("布尔值通过String类型转换后为:"+String(true)); //true
        console.log("布尔值通过String类型转换后为:"+String(false)); //false

        // - 函数,直接把整个函数变成字符串 返回
        var f = function(){ var a=1; alert(a);};
        console.log("函数通过String类型转换后为:"+String(f));//function(){ var a=1; alert(a);}

        // - 对象,直接调用对象的 toString 方法
        //  对象1-{} [object,object]  
        var obj = {};
        console.log("空对象obj通过String类型转换后为:"+String(obj));//[object Object]

        //  对象2-元素对象 [object HTMLDivElement]
        var box = document.querySelector(".box");
        console.log("单个元素对象box通过String类型转换后为:"+String(box));//[object HTMLDivElement]

        //  对象3-一组元素 [object NodeList]
        var boxs = document.querySelectorAll(".box");
        console.log("一组元素对象boxs通过String类型转换后为:"+String(boxs));//[object NodeList]

        //  对象4-数组:直接去掉方括号,把里面的值转为字符串。空数组,直接返回空字符串;一个元素,直接返回该元素;多个元素去掉[],返回所有元素且带有逗号“,”
        var arr1 = [];
        var arr2 = [1];
        var arr3 = ['1'];
        var arr4 = ['1','2'];
        var arr5 = ['a','2'];
        console.log("空数组对象[]通过String类型转换后为:"+String(arr1));
        console.log("数组对象[1]通过String类型转换后为:"+String(arr2));
        console.log("数组对象['1']通过String类型转换后为:"+String(arr3));
        console.log("数组对象['1','2']通过String类型转换后为:"+String(arr4));
        console.log("数组对象['a','2']通过String类型转换后为:"+String(arr5));
    </script>
</body>
</html>

 结果:

8.QQ号验证

要求:

  1. 不能为空;
  2. 只能输入5-10位;
  3. 必须是一个合法的整数;
  4. 不能以0开始;
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>QQ号验证</title>
    <style>
        body { margin: 0; padding: 0; }
        .wrap { width: 764px; height: 265px; background: url('img/bg.png') no-repeat; margin: 30px auto; position: relative;}
        .txt, .btn { height: 40px; line-height: 40px; border-radius: 4px; outline: none; border:none; position: absolute; top:114px; }
        .txt { width: 180px; background: #ffffff; left:310px; text-indent: 20px; }
        .btn { width: 70px; background:none; background: #000000; color: #ffffff; left:500px; }
    </style>
</head>
<body>
    <div class="wrap">
        <input type="text" class="txt">
        <input type="button" class="btn" value="验证">
    </div>
    <script>
        var txt = document.querySelector(".txt");
        var btn = document.querySelector(".btn");
        btn.onclick = function(){
            var txtVal = txt.value;
            // 不能为空;
            if(txtVal == ''){
                alert("QQ号不能为空");

            // 只能输入5-10位;
            //注意:不能获取txt元素的length而是获取txt.value的length
            }else if(txtVal.length < 5 || txtVal.length > 10){

                alert("QQ号必须在5-10位之间");

            // isNaN 方法中,传入的数据 能被转换成 合法数字时,就会返回 false,当传入的数据不能被转换成 合法数字( 也就是NaN) 时,isNaN 就会返回 true
            }else if(isNaN(txtVal)
                    || txtVal != String(parseInt(txtVal)) //**代表txtVal本身有小数点,将数据转换成String,再进行比较。此时它会一位一位进行比较
                    || txtVal<0){
                alert("QQ号必须是一个合法的正整数");

            // 不能以0开始;
            }else if(txtVal[0]=='0'){
                alert("QQ号首位不能为0");
            }else{
                alert("您输入的QQ正确");
            }
        };
    </script>
</body>
</html>

结果:

检测小数:

当数据为10.22类似时,使用parseInt(num1) == parseFloat(num1)检测结果为false可行,但是小数位上全部为0时,如10.0,10.00等时,使用parseInt(num1) == parseFloat(num1)出来的结果为true结果不正确:

解决:转换成字符成再比较:String(num2) == String(parseFloat(num2)),如果num2本身是字符串就不用再转,但是后面都需要转

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>检测是否为小数</title>
</head>
<body>
    <script>
        //当小数为10.88类似时
        var num1 = "10.88";
        console.log("parseInt(num1) == parseFloat(num1)结果为:"+(parseInt(num1) == parseFloat(num1)));//返回false,代表有小数

        //但当小数为10.0,小数位上全部为0时
        var num2 = "10.00";
        console.log("parseInt(num2) == parseFloat(num2)结果为:"+(parseInt(num2) == parseFloat(num2)));//返回true,此时小数没有被检测出来

        //将数据转换成String,再进行比较。此时它会一位一位进行比较
        console.log("num2 == String(parseInt(num2))结果为:"+(num2 == String(parseInt(num2))));//false
    </script>
</body>
</html>

结果:

9.!=/==和!==/===区别:

!=/==会进行隐式类型转换,!==/===不会进行类型转换,类型不一样,直接返回不相等

10.数据筛选案例

  • 所有的数字:-98765,34,-2,0,5
  • 可以转数字的是:100px,-98765,34,-2,0,300,23.45元,5
  • 最大值是:300
  • NaN的位置是:1,14,17,19

注意点:

  • Infinity 数字中的特殊值 Infinity无穷大 -Infinity 无穷小
  • arr[i] === arr[i] NaN 不等于自己 如果自己等于自己说明不是NaN
  • if(parseFloat(arr[i]))直接这样判断的话,值为0的项返回false,不会打印
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>数据筛选</title>
    <link rel="stylesheet" href="./index.css" />
  </head>
  <body>
    <div class="box">
      <div class="arrs">
        var arr = [ '100px', 'abc'-6, [], -98765, 34, -2, 0, '300', ,
        function(){alert(1);}, null, document, [], true, '200px'-30,'23.45元',
        5, Number('abc'), function(){ alert(3); }, 'xyz'-90 ];
      </div>
      <!-- 
          所有的数字:-98765,34,-2,0,5
          可以转数字的是:100px,-98765,34,-2,0,300,23.45元,5
          最大值是:300
          NaN的位置是:1,14,17,19
       -->
      <div class="screen">
        <p id="p1"></p>
        <p id="p2"></p>
        <p id="p3"></p>
        <p id="p4"></p>
      </div>
    </div>

    <script>
            var arr = [
              "100px",
              "abc" - 6,
              [],
              -98765,
              34,
              -2,
              0,
              "300",
              ,
              function() {
                alert(1);
              },
              null,
              document,
              [],
              true,
              "200px" - 30,
              "23.45元",
              5,
              Number("abc"),
              function() {
                alert(3);
              },
              "xyz" - 90
            ];
            var p1 = document.getElementById("p1");
            var p2 = document.getElementById("p2");
            var p3 = document.getElementById("p3");
            var p4 = document.getElementById("p4");
            var p1Str = '所有的数字:';
            var p2Str = '可以转数字的是:';
            var p3Str = '最大值是:';
            var p4Str = 'NaN的位置是:';
            var maxVal = -Infinity;//**(记录标识,声明maxVal为无穷小,用到大于maxVal的就将其值赋到maxVal上)Infinity 数字中的特殊值 Infinity无穷大 -Infinity 无穷小 
            
            for(var i=0;i<arr.length;i++){
              // 所有的数字:-98765,34,-2,0,5
              //typeof 找到所有为number类型的数据,NaN也为数字类型,再通过!isNaN()去掉所有为NaN的数据
              if(typeof arr[i] == 'number' && !isNaN(arr[i])){//// arr[i] === arr[i] NaN 不等于自己 如果自己等于自己说明不是NaN 
                p1Str += arr[i] + ',';
              }
              p1.innerHTML = p1Str.substring(0,p1Str.length-1);

              // 可以转数字的是:100px,-98765,34,-2,0,300,23.45元,5
              if(!isNaN(parseFloat(arr[i]))){//if(parseFloat(arr[i]))直接这样判断的话,值为0的项返回false,不会打印
                p2Str += arr[i] + ',';
              }
              p2.innerHTML = p2Str.substring(0,p2Str.length-1);


              // 最大值是:300
              var curnum = parseFloat(arr[i]);
              if(!isNaN(curnum) && curnum > maxVal){
                //**用 maxVal 和数字中的每一位去比较,如果 nub 比 maxNub 大,就把 nub 的值 存入 maxNub 中,最后maxNub 和数组中每一位比较过后 maxNub 中保留就是 数组中的最大值
                maxVal = curnum;
              }
              p3.innerHTML = p3Str + maxVal;

              // NaN的位置是:1,14,17,19
              if(typeof arr[i] == 'number' && isNaN(arr[i])){
                p4Str += i + ',';
              }
              p4.innerHTML = p4Str.substring(0,p4Str.length-1);;
            }

    </script>
  </body>
</html>

结果:

11.传值和传址(存值和存址)

  • 基本类型在赋值过程中,传递的是具体的值;
  • 对象在赋值过程中,传递的是在内存中的引用地址;
  • 对象尽量不要使用=赋值,而使用拷贝
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>传值和传址</title>
</head>
<body>
    <script>
        //对象在赋值过程中,传递的是在内存中的引用地址
        //arr传给arr2的是其在堆内存中的地址,因此,更改arr2的同时arr也改变了
        //对象不要使用=赋值,需要使用拷贝
        var arr = [1,2,3];
        var arr2 = arr;
        arr2[1] = 'b';
        console.log(arr);//[1, "b", 3]

        //基本类型在赋值过程中,传递的是具体的值
        //b的值传给a后,b本身的值不会变
        var b = 0;
        var a = b;
        a = 1;
        console.log(b);//0
    </script>
</body>
</html>

结果:

12.加性操作符

加法和减法都属于加性操作符。

加法运算符:

  • 当左右两侧操作数,任意一侧为字符串,则另一侧非字符串的类型转为字符串类型,进行字符串拼接;
  • 当左右两侧操作数都为Number,按如下规则返回结果:
  1. 左右两侧均为数值,执行常规加法计算;
  2. 任何数与NaN进行运算,返回结果都是NaN;
  • 如果操作数是布尔值(转为0/1)、undefined(转为NaN)、null(转为0),则会使用Number将其转为数字类型,再进行计算,如果转换结果为NaN,则结果为NaN
  • 加性操作符是从左至右进行计算的
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>加性操作符之加法运算符</title>
</head>
<body>
    <script>
        //当左右两侧任意一侧为字符串时,进行拼接字符串操作
        var str = '1' + 1;
        console.log("'1' + 1 结果为:"+str);//11

        //当左右两侧均为Number类型数据时:
        //1.当左右两侧均为数值,进行正常加法运算
        var num = 1 + 1;
        console.log("1 + 1 结果为:"+num);//1
        //2.任何数与NaN计算返回结果都是NaN
        var num1 = NaN + 1;
        console.log("NaN + 1 结果为:"+num1);//NaN

        //如果操作数是布尔值(转为0/1)、undefined(转为NaN)、null(转为0),则会使用Number将其转为数字类型,再进行计算,如果转换结果为NaN,则结果为NaN
        var num3 = true + 1;
        console.log("true + 1 结果为:"+num3);//2

        var num4 = undefined + 1;//Number(undefined)结果为NaN,任何数字和NaN进行计算结果都为NaN
        console.log("undefined + 1 结果为:"+num4);//NaN

        var num5 = null + 1;//Number(null)结果为0
        console.log("null + 1 结果为:"+num5);//1

        //加性操作符是从左至右进行计算的,所以会先将字符串1和数字2进行拼接即 '1' + String(2)->'12';再将'12' + String(3) ->123
        var num6 = '1' + 2 + 3;
        console.log("'1' + 2 + 3 结果为:"+num6);//123
    </script>
</body>
</html>

结果:

减法运算符:

  • 当左右两侧都为Number类型时,按照如下规则返回结果:
  1. 若左右两侧均为数值,执行常规的减法计算;
  2. 若其中一个操作数为NaN,则返回NaN;
  3. 若减法运算符的减数为负数,会转为加法运算符进行计算

  4. 减法运算符中没有字符串拼接,所以当其中一个数为字符串时会转为Number类型再进行计算

  5. 如果左右两侧都是负数,正常进行负数运算

  • 如果任意一侧不为Number类型,如布尔值、字符串、undefined、null,则会先通过Number将其转为数字类型,然后再进行计算,如果其中转换结果为NaN,则结果为NaN
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>加性操作符之减法运算符</title>
</head>
<body>
    <script>
        // 当左右两侧都为Number类型时,按照如下规则返回结果:
            // 若左右两侧均为数值,执行常规的减法计算;
            var num1 = 3 - 2;
            console.log("3 - 2 结果为:"+num1);//1

            // 若其中一个操作数为NaN,则返回NaN;
            var num2 = 3 - NaN;
            console.log("3 - NaN 结果为:"+num2);//NaN

            //若减法运算符的减数为负数,会转为加法运算符进行计算
            var num3 = 3 - (-2);
            console.log("3 - (-2) 结果为:"+num3);//5

            //减法运算符没有字符串拼接,所以当其中一个数为字符串时会转为Number类型再进行计算
            var num4 = '3' - (-2);
            console.log("'3' - (-2) 结果为:"+num4);//5
            var num5 = 3 - (-'2');
            console.log("3 - (-'2') 结果为:"+num5);//5

            //如果左右两侧都是负数,正常进行负数运算
            var num6 = -5 - 6;
            console.log("-5 - 6 结果为:"+num6);//5

        // 如果操作数是Boolean、String、undefined、null,则会先通过Number将其转为数字类型,然后再进行计算,如果其中转换结果为NaN,则结果为NaN。
            var num7 = 4 - true;
            console.log("4 - true 结果为:"+num7);//3

            var num8 = 4 - undefined;
            console.log("4 - undefined 结果为:"+num8);//NaN   Number(undefined)结果为NaN,如果其中转换结果为NaN,则结果为NaN

            var num9 = 4 - null;
            console.log("4 - null 结果为:"+num9);//4  Number(null)结果为0

            var num10 = 4 - '3';
            console.log("4 - '3' 结果为:"+num10);//3 String进行减法运算,会将其转为Number类型
    </script>
</body>
</html>

结果:

 减法为什么是加性操作符?

减号运算符作用于两个数字类型时表示减法,产生两个操作数之差,左边操作数是被减数左右是减数。给定操作符a和b,总是有a-b产生于a+(-b)产生相同结果。

13.隐式类型转换

 隐式类型转换:我们没有主动对值进行转换,但因为我们的某些操作引起JS自动帮我们进行转换,这样的转换是在JS内部自己实现的。+/=等很多运算符都会进行隐式类型转换。

ECMAScript官网规则文档:

英文官方文档:http://www.ecma-international.org/ecma-262/5.1/#

中文 :http://www.fengfly.com/document/ECMAScript5.1/

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>隐式类型转换测试</title>
</head>
<body>
    <script>
        //隐式类型转换参考ECMAScript规则
        //隐式类型转换:本身v和v1不是同一类型,应该不相等,但是JS会自动将其进行类型转换,因此最终结果为true
        var v = 100;
        var v1 = "100";
        console.log("v == v1结果为:"+(v == v1));//true
        console.log("v + v1结果为:"+(v+v1));//true

        console.log("'1'+1 结果为:"+('1'+1));
        console.log("null+1 结果为:"+(null+1));
        console.log("undefined+1 结果为:"+(undefined+1));
        console.log("true+false+1 结果为:"+(true+false+1));
    </script>
</body>
</html>

结果:

14.乘性操作符

乘法运算符、除法运算符、取模运算符都属于乘性操作符

14.1乘法运算符:

  • 左右两侧都是Nubmer类型时:
  1. 左右两侧都为数值,进行正常的乘法运算
  2. 任何一侧为NaN,则结算结果都为NaN
  • 左右两侧其中一侧不为Number类型(布尔型、null、undefined、字符串)时,则根据对应规则(Number)转为数字类型,然后进行计算。
<script>
        // 左右两侧都是Nubmer类型时:
            // 左右两侧都为数值,进行正常的乘法运算
            console.log("2 * 3 结果为:"+(2 * 3));//6
            // 任何一侧为NaN,则结算结果都为NaN
            console.log("NaN * 3 结果为:"+(NaN * 3));//NaN

        // 左右两侧其中一侧不为Number类型(布尔型、null、undefined、字符串)时,则根据对应规则(Number)转为数字类型,然后进行计算。
            console.log("true * 3 结果为:"+(true * 3));//3
            console.log("false * 3 结果为:"+(false * 3));//0

            console.log("null * 3 结果为:"+(null * 3));//Number(null)*3 = 0*3 = 0
            console.log("undefined * 3 结果为:"+(undefined * 3));//Number(undefined)*3 = NaN * 3 = NaN
            console.log("'1' * 3 结果为:"+('1' * 3));//Number('1')*3 = 1*3 = 3
    </script>

结果:

14.2除法运算符:

  • 当左右两侧都为Number类型时,按如下规则返回结果:
  1. 如果左右两侧均为数值,则按照正常除法计算;
  2. 如果是非零的优先数被零除,则结果返回Infinity或-Infinity;(数学中不允许零作为除数)
  3. 如果是零被零除,则返回NaN;
  4. 如果有一个操作数是NaN,则结果返回NaN;
  • 如果任意一侧不是Number类型,则(根据对应的规则)转为数字类型,然后进行计算
<script>
        // 当左右两侧都为Number类型时,按如下规则返回结果:
            // 如果左右两侧均为数值,则按照正常除法计算;
            console.log("6/3 结果为:"+(6/3));//2

            // 如果是非零的优先数被零除,则结果返回Infinity或-Infinity;(数学中不允许零作为除数)
            console.log("6/0 结果为:"+(6/0));//Infinity
            console.log("-6/0 结果为:"+(-6/0));//-Infinity

            // 如果是零被零除,则返回NaN;
            console.log("0/0 结果为:"+(0/0));//NaN

            // 如果有一个操作数是NaN,则结果返回NaN;
            console.log("0/NaN 结果为:"+(0/NaN));//NaN
            console.log("NaN/2 结果为:"+(NaN/2));//NaN

        // 如果任意一侧不是Number类型,则(根据对应的规则)转为数字类型,然后进行计算
            console.log("true / 3 结果为:"+(true / 3));//0.3333333333333333
            console.log("false / 3 结果为:"+(false / 3));//0

            console.log("null / 3 结果为:"+(null / 3));//Number(null)/3 = 0/3 = 0
            console.log("undefined / 3 结果为:"+(undefined / 3));//Number(undefined)/3 = NaN / 3 = NaN
            console.log("'1' / 3 结果为:"+('1' / 3));//Number('1')/3 = 1/3 = 0.3333333333333333
    </script>

结果:

14.3取模操作符:

进行除法计算,但是目的是为了得到余数,而不再是得到结果。

  • 如果左右两侧均为Number类型时,按照如下规则返回结果:
  1. 如果左右两侧均为数值,按照常规除法进行计算,返回余数;
  2. 如果有一侧是NaN,则返回NaN;
  3. 如果除数是0,则结果返回NaN;
  4. 如果被除数是0,则结果返回0;
  • 如果任意一侧不是Number类型(String,Boolean,null,undefined等),则(根据对应的规则Number)转为数字类型,然后再进行计算。
<script>
        // 如果左右两侧均为Number类型时,按照如下规则返回结果:
            // 如果左右两侧均为数值,按照常规除法进行计算,返回余数;
            console.log("12%7 结果为:"+(12%7));//5

            // 如果有一侧是NaN,则返回NaN;
            console.log("12%NaN 结果为:"+(12%NaN));//NaN
            console.log("NaN%7 结果为:"+(NaN%7));//NaN

            // 如果除数是0,则结果返回NaN;
            console.log("7%0 结果为:"+(7%0));//NaN

            //如果被除数是0,则结果返回0;
            console.log("0%7 结果为:"+(0%7));//0

        // 如果任意一侧不是Number类型(String,Boolean,null,undefined等),则(根据对应的规则Number)转为数字类型,然后再进行计算。
            console.log("'1'%7 结果为:"+('1'%7));//Number('1')%7 = 1
            console.log("true%7 结果为:"+(true%7));//Number(true)%7 = 1
            console.log("false%7 结果为:"+(false%7));//Number(false)%7 = 0
            console.log("null%7 结果为:"+(null%7));//Number(null)%7 = 0
            console.log("undefined%7 结果为:"+(undefined%7));//Number(undefined)%7 = NaN
    </script>

结果:

14.4取模案例

<script>
        //判断一个数字的奇偶数,如果能被2整除即为偶数,不能被2整除即为奇数,可以用于各行变色
        var num = 21;
        if(num%2){
            alert("num为奇数");
        }else{
            alert("num为偶数");
}

15.一元操作符(一元加、减运算符)

一元操作符即正号和负号(+、-),只能操作一个值的操作符叫做一元操作符。

15.1一元加运算符:

  • 如果操作数是Number类型时,正号放在数值前面,对其没有任何影响;
  • 如果操作数是非Number类型即String,true,false,null,undefined,则(根据对应规则Number)将其转为数字类型(隐式类型转换),再进行运算。(Number转换非数字类型字符串返回NaN)
  • 无论正号还是负号对NaN,都是没有影响的,结果都为NaN;
<script>
        // 如果操作数是Number类型时,正号放在数值前面,对其没有任何影响;
        console.log("+5的结果是:"+(+5));//5
        // 如果操作数是非Number类型即String,true,false,null,undefined,则(根据对应规则Number)将其转为数字类型(隐式类型转换),再进行运算。
        console.log("+'5'的结果是:"+(+'5'));//5
        //如果String里不是数值类型,使用+会直接转为NaN
        console.log("+'abc'的结果是:"+(+'abc'));//NaN

        console.log("+true的结果是:"+(+true));//1
        console.log("+false的结果是:"+(+false));//0
        console.log("+null的结果是:"+(+null));//0
        console.log("+undefined的结果是:"+(+undefined));//0

        // 无论正号还是负号对NaN,都是没有影响的,结果都为NaN;
        console.log("+NaN的结果是:"+(+NaN));//NaN
        console.log("-NaN的结果是:"+(-NaN));//NaN
    </script>

 结果:

15.2一元减运算符

  • 如果操作数是Number类型时,负号放在数值前,表示负数;
  • 如果操作数不是Number类型,即String,true,false,null,undefined,则(根据对应规则Number)转为数字类型(隐式类型转换),再进行运算;
  • 无论正号还是负号对NaN,都是没有影响的,结果都为NaN;
<script>
        // 如果操作数是Number类型时,负号放在数值前,表示负数;
        console.log("-5的结果为:"+(-5));
        // 如果操作数不是Number类型,即String,true,false,null,undefined,则(根据对应规则Number)转为数字类型(隐式类型转换),再进行运算;
        console.log("-'5'的结果为:"+(-'5'));//Number('-5')=-5
        console.log("-'abc'的结果为:"+(-'abc'));//NaN
        console.log("-true的结果为:"+(-true));//-1
        console.log("-false的结果为:"+(-false));//0
        console.log("-null的结果为:"+(-null));//0
        console.log("-undefined的结果为:"+(-undefined));//NaN

        // 无论正号还是负号对NaN,都是没有影响的,结果都为NaN;
        console.log("-NaN的结果为:"+(-NaN));//NaN
    </script>

结果: 

16.巧妙利用运算符进行隐式类型转换

巧妙利用运算符进行隐式类型转换:偶尔可通过隐式类型转换来达到想要把数据转为另一种数据的目的。

总结:

“+”号的三种用法:

  1. 左右两侧都是数字类型时,进行加法运算;
  2. 左右两侧任意一侧为字符串时,进行字符串拼接;
  3. 只有一个数字使用+号时(一元运算符),如+10,可用作隐式类型转换;
<script>
        //想要进行运算,但是有变量是字符串时
        var num1 = "123";
        var num2 = 2;
        //如果直接num1+num2会进行字符串拼接 得到1232
        console.log("num1+num2直接相加后结果为:"+(num1+num2));//1232
        //传统方法:要想让其以数字类型进行计算需要使用Number()进行转换(注意:不能使用Number(num1+num2),这样会先进行字符串拼接,再转换)
        console.log("Number(num1)+num2使用Number进行转换类型后结果为:"+(Number(num1)+num2));//125

        //巧妙利用运算符进行隐式类型转换:可以直接使用+号一元运算符进行隐式类型转换
        console.log("(+num1)+num2使用+号隐式类型转换后结果为:"+((+num1)+num2));//125

        //想要进行字符串拼接但是变量都是数字类型时
        var num3 = 10;
        var num4 = 20;
        // 两个数字类型直接相加,得到的是两个数之和
        console.log("num3+num4两个数字类型直接相加后结果:"+(num3+num4));//30

        //传统方法:通过String()方法让其转换为字符串,再进行拼接
        console.log("String(num3)+String(num4)两个数字类型直接相加后结果:"+(String(num3)+String(num4)));//1020

        //使用隐式类型转换:注意此处+ ''必须在两个变量中间,因为加法运算是从左到右依次进行计算,如果+''在最后,会先进行和计算再转为字符串
        console.log("num3+ '' +num4两个数字类型直接相加后结果:"+(num3 + '' + num4));//1020
    </script>

结果:

 17.递增/递减运算符

  1. 单独对一个操作数进行递增/递减操作,不和其他数值进行计算时,结果是一样的,都只是进行相应的递增递减;
  2. 但是,当递增/递减操作和其他数值进行了计算时:(计算后的结果result会不一样,但是两个自增/自减的变量(num1和num2)在计算后值依然相等
  • 前置型递增/递减运算符:变量的值在语句被求值之前发生改变;
  • 后置型递增/递减运算符:变量的值在语句被求值之后发生改变;

如下:num1和num2初始值都为0,分别对num1和num2进行了num1++和++num2操作,发现两种操作后num1和num2的结果都是一样的,值为1。所以,如果同样只单独对某一个操作数进行递增或递减操作,那么前置或后置递增/递减后的结果是相同的。

var num1 = 0;
var num2 = 0;

num1++;
++num2;
console.log("num1++后的结果为:"+num1);
console.log("++num2后的结果为:"+num2);

结果:

但是,当num1和num2进行了num1++和++num2操作,并且和其它数值进行计算后,使用前置递增/递减操作符的变量的值在语句被求值之前会发生改变;而后置递增/递减操作符的变量的值在语句被求值之后才会发生改变。计算后的结果result会不一样,但是两个自增/自减的变量(num1和num2)在计算后值依然相等。如下:

        //单独对一个操作数进行递增/递减操作,不和其他数值进行计算时,结果是一样的,都只是进行相应的递增递减;
        // 但是,当递增/递减操作和其他数值进行了计算时:
            // 前置型递增/递减运算符:变量的值在语句被求值之前发生改变;
            // 后置型递增/递减运算符:变量的值在语句被求值之后发生改变;
        var num1 = 0;
        var num2 = 0;

        // num1++;
        // ++num2;
        // console.log("num1++后的结果为:"+num1);
        // console.log("++num2后的结果为:"+num2);

        var result = num1++ + 1;
        var result2 = ++num2 + 1;
        console.log("2+num1++后result的结果为:"+result);
        console.log("2+(++num2)后result2的结果为:"+result2);

        console.log("2+num1++后num1的结果为:"+num1);
        console.log("2+(++num2)后num2的结果为:"+num2);

结果:

18.小数的计算失精度问题

这个问题主要是由于JS是基于IEEE754数值的浮点计算,ECMAScript并不是独此一家。很多其他的语言也存在这一问题。

解决方法:将小数转换成整数之后,进行计算,然后再转回会对应的小数即可。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>小数计算问题</title>
</head>
<body>
    <input type="text" id="input1" value="0.1">
    +
    <input type="text" id="input2" value="0.2">
    <button id="btn"> = </button>
    <span id="result"></span>
    <script>
        var input1 = document.getElementById("input1");
        var input2 = document.getElementById("input2");
        var btn = document.getElementById("btn");
        var result = document.getElementById("result");
        btn.onclick = function(){
            var txt1Val = input1.value;
            var txt2Val = input2.value;
            //直接使用小数计算(通过元素获取的内容都是字符串,所以会进行字符串拼接0.10.2)
            //result.innerHTML = txt1Val + txt2Val;//0.10.2

            //使用Number()转换成数字类型后,发现结果为0.30000000000000004
            //result.innerHTML = Number(txt1Val) + Number(txt2Val);//0.30000000000000004

            //解决:将txt1Val,txt2Val两个数都乘以小数位数的数十倍,将其转为整数再进行计算,得到计算结果后,再除以对应的数十倍即可
            result.innerHTML = (Number(txt1Val) * 10 + Number(txt2Val) * 10) / 10; //0.3
        };
    </script>
</body>
</html>

 结果:

直接转为数字类型进行计算(结果失去精度):

转为数字类型后,再乘以小数位数的数十倍,得到计算结果后再除以数十倍(结果正确):

19.赋值运算符

  • 赋值运算符:=,+=,-=,*=,/=,%=;
  • =等号:用于将右侧的值,赋给左侧的变量;
  • +=,-=,*=,/=,%=:大部分的数学运算符和=号结合使用就可以完成复合赋值运算;要求:左侧变量必须和右侧变量一致
  • 赋值运算符的隐式类型转换:+=,-=,*=,/=,%=赋值运算符只是对各种运算的简写,因此赋值运算符的隐式类型用法和其原本的隐式类型转换是一致的;
<script>
        //=,+=,-=,*=,/=,%=
        var num = 10;
        //+=
        num = num + 5;
        console.log("num = num + 5后的结果为:"+num);//15
        num = 10;
        num += 5;
        console.log("num += 5后的结果为:"+num);//15

        //-=
        var num2 = 10;
        num2 = num2 - 5;
        console.log("num2 = num2 - 5后的结果为:"+num2);//5
        num2 = 10;
        num2 -= 5;
        console.log("num2 -= 5后的结果为:"+num2);//5

        //*=
        var num4 = 10;
        num4 = num4 * 5;
        console.log("num4 = num4 * 5后的结果为:"+num4);//50
        num4 = 10;
        num4 *= 5;
        console.log("num4 *= 5后的结果为:"+num4);//50

        // /=
        var num6 = 10;
        num6 = num6 / 5;
        console.log("num6 = num6 / 5后的结果为:"+num6);//2
        num6 = 10;
        num6 /= 5;
        console.log("num6 /= 5后的结果为:"+num6);//2

        // %=
        var num8 = 10;
        num8 = num8 % 5;
        console.log("num8 = num8 % 5后的结果为:"+num8);//0
        num8 = 10;
        num8 %= 5;
        console.log("num8 %= 5后的结果为:"+num8);//0

        //=,+=,-=,*=,/=,%=的隐式类型转换(和所有+-*/%的隐式类型转换一致)
        var b = '2';
        b += 2;
        console.log("b = '2' +=后的结果为:"+b);//22
    </script>

结果:

20.比较操作符

20.1比较操作符之关系操作符

<, <= ,>, >=用于比较大小,返回的结果可为="", true,false或 undefined(这说明 x、y 中最少有一个操作数是 NaN)。

  • 左右两侧都是数字类型,就比较数值的大小;
  • 如果不是数字的情况:
  1. 字符串的比较:即使字符串里面是数字,也不进行数值比较,而是会按字符编码ASCII码顺序进行比较;字符串的比较是逐位比较的;
  2. 如果比较运算符的其中一侧为NaN,则结果返回false;
  3. 如果其中一侧为null,undefined,true,false,最终会根据对应的规则进行转换,然后再进行比较;
  4. >=,<=,>和<,如果任意一侧为undefined(Number(undefined)=NaN),则返回false,否则返回true;
  5. 字符串和布尔值比较:如果左侧值小于右侧值的结果为true或undefined,则返回false,否则返回true

<script>
        //字符串比较,比较的是字符串的ASCII字符编码中的大小;且从左往右一位一位的比较;
        var str1 = 'A0';//A对应的编码为65
        var str2 = '34';//3对应的编码为51
        console.log("字符串A0和34比较的结果为:"+(str1>=str2));//true

        //如果比较运算符的其中一侧为NaN,则结果返回false
        console.log("NaN和34比较的结果为:"+(NaN>=str2));
        console.log("A0和NaN比较的结果为:"+(str1>=NaN));

        //如果其中一侧为null,undefined,true,false最终会根据对应的规则进行转换
        // console.log(String(null));//110
        // console.log(Number(null));// 0 对应的编码为48
        console.log("如果其中一侧为null和34比较的结果为:"+(null>=str2));//此处结果为false

        //  >=,<=,>和<,如果任意一侧为undefined(Number(undefined)=NaN),则返回false,否则返回true
        console.log("str2>=undefined比较的结果为:"+(str2>=undefined));//false
        console.log("undefined>=str2比较的结果为:"+(undefined>=str2));//false
        console.log("str2>undefined比较的结果为:"+(str2>undefined));//false
        console.log("undefined>str2比较的结果为:"+(undefined>str2));//false

        console.log("undefined<=str2比较的结果为:"+(undefined<=str2));//false
        console.log("str2<=undefined比较的结果为:"+(str2<=undefined));//false
        console.log("undefined<str2比较的结果为:"+(undefined<str2));//false
        console.log("str2<undefined比较的结果为:"+(str2<undefined));//false

        //字符串和布尔值比较:如果左侧值小于右侧值的结果为true或undefined,则返回false,否则返回true
        console.log("str2>=true比较的结果为:"+(str2>=true));//true 34 1 
        console.log("true>=str2比较的结果为:"+(true>=str2));//false 1 34
        console.log("-----------------------------");
        console.log("str1>=true比较的结果为:"+(str1>=true));//false  A0 1
        console.log("true>=1比较的结果为:"+(true>=1));//true 1 1
    </script>

结果:

20.2相等操作符

==相等 !=不等 ===全等 !==全部等,用于确认两个变量之间是否相等。

相等和全等:虽然都是比较两个值是否相等,但是在比较时,需遵循不一样的规则。

20.2.1相等:

比较两个操作数之间是否相等,如果相等会返回true,如果不相等返回false,比较时会进行隐式类型转换。

隐式转换规则:

  • NaN不等于任何类型的数值,包括其本身,所以一定返回false;
  • 如果都是String类型,比较字符编码值,如果完全一致,返回true,否则返回false;
  • 如果两侧都是Number数值类型,比较值是否相同;
  • 如果两边都是Object类型,比较地址是否相同;
  • null==undefined返回true;(不会进行隐式类型转换)
  • 如果一侧为String,一侧是Number,将String(String不可以转成数字类型的字符串)转换NaN之后,再进行比较;
  • 如果一侧是Boolean,则把布尔值转为Number类型后,再根据上述规则进行比较;
  • 具体参照ECMAScript规则;
<script>
        //==会进行隐式类型转换,本身数据类型不同,但是JS会对其进行隐式类型转换,就可以比较了
        console.info("1==1结果为:"+(1==1));//true

        // NaN不等于任何类型的数值,包括其本身,所以一定返回false;
        console.info("NaN==1结果为:"+(NaN==1));//false
        console.info("NaN==NaN结果为:"+(NaN==NaN));//false

        // 如果都是String类型,比较字符编码值,如果完全一致,返回true,否则返回false;
        console.info("'abc'=='123'结果为:"+('abc'=='123'));//false
        console.info("'abc'=='abc'结果为:"+('abc'=='abc'));//true

        // 如果两侧都是Number数值类型,比较值是否相同;
        console.info("1==1结果为:"+(1==1));//true

        // 如果两边都是Object类型,比较地址是否相同;
        var a = {name:'lmf'};
        var b = {name:'lmf'};
        console.info("a==b结果为:"+(a==b));//false
        var c = b;
        console.info("c==b结果为:"+(c==b));//true

        // null==undefined返回true;
        console.info("null==undefined结果为:"+(null==undefined));//true

        // 如果一侧为String,一侧是Number,将String(String不可以转成数字类型)转换NaN之后,再进行比较;
        console.info("'1'==1结果为:"+('1'==1));//true
        console.info("'abc'==1结果为:"+('abc'==1));//false String("abc")=NaN  Nan==1返回false

        // 如果一侧是Boolean,则把布尔值转为Number类型后,再根据上述规则进行比较;
        console.info("true==1结果为:"+(true==1));//true
    </script>

结果:

 

20.2.2全等:

全等===也是比较两个操作数之间是否相等,但是与==不同,它从两个点进行考虑:

  1. 值是否相等;
  2. 类型是否相等

因为会判断类型,所有全等不会进行隐式类型转换

  • 一旦两个操作数的数据类型不同,直接返回false;
  • 一旦出现NaN,直接返回false;
  • 当类型一致时,比较值是否相同(为字符串时比较其字符编码是否相等),不同返回false,相同返回true;
<script>
        //全等:首先必须类型一致,其次必须值一致,才会返回true;一旦出现NaN,返回false
        //类型不一致
        console.log("null==undefined结果为:"+(null==undefined));//true
        console.log("null===undefined结果为:"+(null===undefined));//false

        //当类型一致时,比较值是否相等
        console.log("2===3结果为:"+(2===3));
        console.log("'abc'==='abd'结果为:"+('abc'==='abd'));
    </script>  

结果:

 

20.2.3不等和全不等:

和相等和全等一样,不等和全部等在比较时:

  • 前者只注重值,并且会进行隐式类型转换,转换规则与相等一致,只是返回的结果正好相反;
  • 后者在注重值的同时,还是注重类型是否相同,转换规则和全等一致,只是返回结果正好相反;

21.逻辑运算符

&&,||,!最终的结果不一定是返回布尔值,而在if()里最终返回boolean值,是因为if会最终将其转为布尔值再进行后续操作。

21.1 &&与:如,alert(1 && 2)

  • 作用在两个操作数之间,首先去看左侧的操作数,将其1进行隐式类型转换,转为boolean。true/false
  • false,会直接返回左侧的操作数;
  • true,会直接返回右侧的操作数;

21.2 || 或:如,alert(0 || 1)

  • 作用在两个操作数之间,首先去看左侧的操作数,将其1进行隐式类型转换,转为boolean。true/false
  • 如果为true,会直接返回左侧操作数;
  • false,会直接返回右侧操作数;

21.3 !非:alert(!true)

  • 取反,作用于一个操作数,得到的一定是布尔值。
  • 会对这个操作数进行隐式类型转换,转换为Boolean
  • !非也是一元运算符
  • 使用!!num,两个!!就可以对numnum进行强制类型转换。
console.log("Boolean(1)转为布尔值:"+Boolean(1));
console.log("!!1转为布尔值:"+!!1);

结果:

 

非 :作用在一个操作符上,也是一元运算符之一,表示对该操作进行取反,所以会对数据进行隐式类型转换,转为布尔值,然后取反,最后返回一个布尔值。

非的隐式类型转换规则:(和其本身进行Boolean值转换后的结果相反)

  • 如果操作数是Object类型,结果返回false(所有对象经过Boolean转换后均为true);
  • 如果操作数是控制串,返回true;
  • 如果是费控字符串,返回false;
  • 如果是Number数值0,返回true;
  • 如果是NaN,返回true;
  • 如果是非0数值,返回false;
  • 如果是null或undefined,返回false

!非运算符,不止可以写一个:

  • !!!0 表示对0进行布尔值转换,再取反,结果为true。
  • !!true表示对true进行取反,结果为false;

22.运算符优先级

<script>
        var result1 = 2 + 3;
        console.log("2 + 3 :"+result1);

        var result2 = 2 + 3 * 2;
        console.log("2 + 3 * 2: "+result2)

        var result3 = 1 + 2 == 5 % 0;
        console.log("1 + 2 == 5 % 0 : "+result3);//false 取模运算符> 赋值运算符>加法运算符
    </script>

结果:

尽管我们之前说,计算是从左往右的,但是这只是在运算符优先级相同的情况下。一旦运算符的优先级不一致,则会先执行优先级高的,然后再执行低的。

运算符优先级查看地址:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Operator_Precedence

猜你喜欢

转载自blog.csdn.net/qq_34569497/article/details/94896438