JS中的数据类型

700 阅读20分钟

一、Number数字类型:

  • 正数/负数/零/小数
  • Infinity 代指无穷大的值,-Infinity 代指负无穷大的值
  • NaN(not a number)不是一个有效数字,但它却属于number类型
     var num = 10-'A';//NaN
     NaN == NaN;//false  NaN和NaN本身都不相等(它和谁都不相等)
isNaN([value]) : 检测一个值[value]是否为"非有效数字",如果不是有效数字返回true,反之返回false.
  • 在使用isNaN进行检测的时候,如果[value]是非数字类型的值,则浏览器默认会把 [value]转换为数字类型,然后再进行检测, "隐式转换":浏览器默认私下处理的.

  • 在"隐式转换"中,浏览器是基于Number([value])实现数据类型转换的.

   //需求:验证一个值是否为有效数字?
   //这样处理不行,因为num==NaN永远不会成立
   /* if(num==NaN){
           alert('num不是有效数字!');
          } */
   //这样处理才是正确的
   if(isNaN(num)){
             alert('num不是有效数字!')
        }
把其它数据类型转换为number数字类型
  • Number([value]) : 而isNaN在检测的时候,使用的就是这种方式转换为数字类型的。 Number是JS内置的转换方法,可以把其他数据类型"强制"转换为数字类型。
    • 字符串转换为数字:空字符串转换为0,如果字符串中出现任意一个非有效数字字符,结果都是转换为NaN。
    • 布尔转换为数字:true->1,false->0.
    • null->0,undefined->NaN.
    • symbol值不能转换为数字(Uncaught TypeError:Cannot convert a Symbol value to a number)
    • bigint 可以转换为数字.
    • 引用数据类型(对象或者函数)转换为数字.
      1. 首先获取它的[Symbol.toPrimitive]属性值.
      2. 如果没有[Symbol.toPrimitive]这个属性,其次获取它的valueOf值(原始值)
      3. 如果还是没有valueOf值(原始值),最后把其转换为字符串toString(),然后再转换为数字 Number().
      • 对象转换为数字:先把对象转化为字符串,再把字符串转化为数字.
        • 普通对象
        • 数组对象
        • 其余对象格式基本都会变为数字NaN.
      • 函数转化为数字,结果都是NaN.

%95S1CNA}IQL@%Q4)84FV2O.png


         console.log(Number('12'));//=>12
         console.log(Number('12.5'));//=>12.5
         console.log(Number('12px'));//=>NaN
         console.log(Number('12.5.0'));//=>NaN
         console.log(Number(true));//=>1
         console.log(Number(false));//=>0
         console.log(Number(null));//=>0
         console.log(Number(undefined));//=>NaN
         console.log(Number(symbol(13)));//=>报错
         console.log(Number(function func(){}));//=>NaN
              
        //1.先把obj转化为字符串"[object Object]"
        //2.再把字符串转化为数字 Number("[object Object]")
        let obj = {x:100}
        console.log(Number(obj));//=>NaN

        //1.先把arr转化为字符串"10"
        //2.再把"10"转化为数字:10
        let arr = ["10"]
        console.log(Number(arr));=>10

        //1.先把arr转化为字符串"10,20"
        //2.再把"10"转化为数字:NaN
        arr=["10","20"];
        console.log(Number(arr));=>NaN

        console.log(isNaN('AA'));//=>true
        console.log(isNaN('12.5'));//=>false
        console.log(isNaN('12.5px'));//=>true
        console.log(isNaN([]));//=>false
        console.log(isNaN([10]));//=>false
        console.log(isNaN([10,20]));//=>true
        console.log(isNaN({}));//=>true
        console.log(isNaN(null));//=>false
        console.log(isNaN(undefined));//=>true
        console.log(isNaN(Symbol(1)));//报错
  • parseInt([value])/parseFloat([value])
    • 需要保证[value]是一个字符串,如果不是则首先"隐式"的把其转换为字符串[value].toString().
    • 从字符串左侧第一个字符开始向右查找,把找到的有效数字字符,最后转换为数字(遇到一个非有效数字字符则停止查找,不论后面是否还有有效数字字符,都不再往后查找了)
    • 如果一个有效数字字符都没有找到,结果还是NaN.
    • parseFloat比parseInt多识别一个小数点.

image.png

<script>
    console.log(Number('12px')); //=>NaN
    console.log(parseInt('12px')); //=>12
    console.log(parseInt('12px24')); //=>12
    console.log(parseInt('width:12px')); //=>NaN
    console.log(parseInt('12.5px')); //=>12
    console.log(parseFloat('12.5px')); //=>12.5  parseFloat比parseInt多识别一个小数点
    console.log(Number(true)); //=>1
    console.log(parseInt(true)); //=>先把true转换为字符串"true"  parseInt('true') =>NaN
    console.log(parseInt(NaN)); //=>NaN
    console.log(Number(null)); //=>0
    console.log(parseInt(null)); //=> parseInt('null') =>NaN
    console.log(isNaN(Number(parseInt("0.8")))); //=>parseInt("0.8")->0   Number(0)->0  isNaN(0)->false
    console.log(Number('')); //=>0
    console.log(parseInt('')); //=>NaN
</script>

结果为:

image.png [number value].toFixed([N]):保留小数点后面N位.

<script>
    //toFixed(N):保留小数点后面N位(最后的结果是一个字符串)
    let n = 3.1415926;
    console.log(n.toFixed(2)); //=>"3.14"
    console.log(Number.MAX_SAFE_INTEGER); //=>9007199254740991 最大安全数(JS能够有效识别的最大整数)
    console.log(9007199254740992 == 9007199254740993); //=>true  应该是false,但是超过了最大数值,JS无法精准计算.
    //ES6中提供了一个新的数据类型 BigInt:管理超过安全数值的数字
    console.log(BigInt(9007199254740992), BigInt(9007199254740993));
</script>

结果为: image.png

二、字符串string数据类型

  1. 在JS中用单引号''/双引号""/反引号`` 包起来的都是字符串.
  2. 一个字符串是由零到多个字符组成的,每一个字符都有一个自己的位置"索引",有一个length存储字符串长度.
  3. 在字符串中每一个字符都有一个代表自己位置的"索引"(数字)
    • 从0开始,逐级递增.
    • 索引0:第一个字符,索引1:第二个字符.
    • str[索引]获取指定索引位置的字符.
            var str = "xiaoyunduo2021";
            console.log(str.length); //=>14
            console.log(str[0]); //=>'x'
            console.log(str[str.length-1]); //=>'1'
  1. 字符串有很多自己能调用的方法: - chartAt - charCodeAt - substr - substring - slice - split - replace - indexOf/lastIndexOf - includes - trim - match - ...

        //str.substr(n,m):从索引n开始截取"m"个字符,
        //str.substring(n,m):从索引n开始找到"索引m"处(不含m),截取索引n和索引m(不含m)之间的字符
        //m不写都是截取到字符串末尾,都不支持负索引,而slice是支持的(剩下的语法和substring一样)
        var str = "xiaoyunduo";
        console.log(str.substr(2,4)); // "aoyu"
        console.log(str.substring(2,4)); //"ao"   
  1. 把其它数据类型转换为字符串类型
    • String([value])
    • [value].toString()
    • 字符串拼接
    • 把对象转换为数字之前,先转化为字符串
    • alert/confirm/prompt等.
    • ...
  • 特点:
    • 基本上都是用双引号或单引号包起来即可.
    • 普通对象转换为字符串不论对象中包括哪些信息,都是转化为 "[object Object]".
    • 数组对象转换为字符串是 "第一项,第二项..."(逗号分隔数组中的每一项),[]转化为空字符串 ""
  1. 在JS中常用的数学运算
  • 数学运算:+ - * / 加减乘除

  • %(膜)取余数

  • 除了加法以外,其余的情况都是数学运算(如果遇到非数字类型,需要基于Number把其强制转换为数字类型,然后再进行运算);

  • 加号在JS中既有数学运算,也有字符串拼接的意思(只要加号两边的任意一边出现字符串,则变为字符串拼接);

    "+"加号的字符串拼接

    • 加号的左右两边,有一边出现字符串,结果都是字符串拼接.
    • 加号的左右两边,有一边出现对象(把对象转化为数字,进行数学运算)
      • 首先获取对象的[Symbol.toPrimitive]/valueOf.

      • 如果上述都没有获取原始值,则基于toString把对象转化为字符串.

      • 此时出现问题"加号左右两边,有一边出现字符串了",这时就不再是数学运算,而是字符串拼接了.

      • 加号出现一边,这样这一边即使是字符串/对象,也是数学运算.

      • 如果是一个"{}"加内容,"{}"不参与运算,只是相对于一个代码块.

     
     console.log(10+[10,20]);//=>[10,20][][Symbol.toPrimitive] undefined
                               //=>[10,20].valueOf() [10,20]不是原始值
                               //=> 此时10+"10,20"  这是字符串拼接了 => "1010,20"

     console.log(10+new Number(10));//=>new Number(10)也是一个对象
                                    //=> new Number(10)[Symbol.toPrimitive] undefined
                                    //=> new Number(10).valueOf()  10
                                    //=> 10+10 => 20

                 
      var s = "10";
      console.log(+s); //=>10
      console.log(+[10]); //=>10
      console.log(s++); //=>10
      console.log(s); //=>11
      
      console.log(3 - "3px"); //=>NaN
      console.log(3 + "3px"); //=>"33px"  字符串拼接
      console.log(1 + "1"); //=>"11" 字符串拼接
      console.log(1 + {}); //=>"1[object Object]"  在把{}转换为数字过程中,先把它转换为字符串"[object Object]",
                                                        此时右侧出现了字符串,则不再是数学运算,而是字符串拼接了.
      console.log(1 + []); //=>'1'  在把[]转换为数字过程中,先把[]转化为空字符串,此时进行了字符串拼接,结果为'1'.
      console.log([10] + true); //=>"10true"  在把[10]转换为数字的过程中,先把其转换为字符串"10",
                                                    此时操作变为字符串拼接(和数学运算没关系了).
      console.log(true + [10]); //=>"true10"
      console.log(1 + true); //=>2   */

      console.log(4 / 2); //=>除  2
      console.log(7 / 3); //=>除  2.3333333333333335
      console.log(7 % 3); //=>取余  1

      console.log(10 - null); //=>10
      console.log(3 * undefined); //=>NaN
      console.log(true - "12"); //=>1-12  =>-11

      console.log(100 + true + 21.2 + null + undefined + "Tencent" + [] + null + 9 + false); 
        /*
         100 + true => 101
         101 + 21.2 => 122.2
         122.2 + null => 122.2
         122.2 + undefined => NaN
         NaN + "Tencent" => "NaNTencent"   字符串拼接(以后都是字符串拼接)
         "NaNTencent" + [] => "NaNTencent"
         "NaNTencent" + null => "NaNTencentnull"
         "NaNTencentnull" + 9 => "NaNTencentnull9"
         "NaNTencentnull9" + false => "NaNTencentnull9false"
         */


三、布尔数据类型及其它基本数据类型

1、布尔boolean数据类型: true/flase

  • 如何把其它数据类型转换为布尔类型

    • Boolean([value])
    • !![value] 取反再取反,相当于没有取反,只是把它转换为布尔类型值
    • 规则:只有 “0/NaN/null/undefined/空字符串” 结果是false,其余的都是true

    ![value] 把指定的值转换为布尔类型后取反

   console.log(!!1); //=>true
   console.log(!1); //=>false
   console.log(!!-1); //=>true
   console.log(!!0); //=>false
   console.log(!!undefined); //=>false
   console.log(!!Number('12px')); //=>Number('12px')->NaN  false
   console.log(!![]); //=>true
   console.log(!!''); //=>false
   console.log(!!{}); //=>true

/* 条件判断中,每一个条件最后一定是true/false */
if (1) {}  //=>写一个值,也是要把这个值转换为布尔,然后校验程序的真假
if (3 + '3px') {}  //=> 3 + '3px' =>'33px'true
if (3 - '3px') {}  //=> 3 - '3px' => NaN   假false
if(10){}  //首先会把10转换为布尔类型,然后验证真假,决定条件是否成立


2、symbol唯一值数据类型

console.log(Symbol() == Symbol()); //false 创建了两个唯一值
var n = Symbol();
console.log(n==n); //true 创建了一个唯一值
console.log(Symbol('AA') == Symbol('AA')); //false 加标识只是为了方便调试,依然是创建了两个唯一值

       

3、BigInt 大数数据类型

BigInt:字后面加个n即大数类型

  • 真实场景:从服务器获取数据,服务器端存储数据的时候,如果用的计算大数存储的,返回到客户端的信息,很有可能超过最大安全数字,这样导致后续计算可能不准确。
Number.MAX_SAFE_INTEGER; //最大安全数 9007199254740991(16位)
Number.MIN_SAFE_INTEGER; //最小安全数 -9007199254740991


//超过最大安全数,再进行计算,结果是不准确的
    console.log(9007199254740991+2); //9007199254740992
    console.log(9007199254740992+3); //9007199254740996
    BigInt("9007199254740992"); //=>9007199254740992n

image.png

四、对象数据类型

对象数据类型

  • 普通对象 {} 「类数组、实例、原型对象...」

  • 数组对象 []

  • 正则对象 /^$/

  • 日期对象

  • Set/Map

  • ...

普通对象

1. 对象是由零到多组“键值对”(属性名:属性值)组成的

  • 属性名(键)不是变量,它是对象的一个属性(特征)
  • 属性名一般都是一个字符串(当然也可以是数字或者Symbol等基本类型的值)
  • 属性名不能是对象或函数,对象或者函数作为属性名,浏览器会把其转换为字符串
        var x = {
            xx: 'xxx'
        };
        var y = {
        //name叫做属性名,此处本身也是一个字符串 "name"
        // "云朵"是当前name属性的属性值
        name: "云朵",
        age: 11,
        0: 100,
        // 对于Symbol类型的属性名,需要基于[]包裹起来,保证语法正确性
        [Symbol('AA')]: 200,
        // 属性名不是这个对象,而是变为最后的字符串 ({xx:'xxx'}).toString() => "[object Object]"
        [{xx:'xxx'}]:300,
        // x->"x"  这个x和上面的x没有关系,它是一个字符串x
        x: 300
        };
        console.log(y); 

        let n = {
	   x: 100
	};
	let m = [100, 200];
	let obj = {};
	obj[n] = "云朵"; //=>obj[{x:100}] 但是对象不能作为属性名,需要把其转换为字符串 =>{"[object Object]":"云朵" }
	obj[m] = "云朵"; //=>obj[[100,200]] =>{ "100,200":"云朵" }
	console.log(obj); 

2. 获取一个对象中某个属性名对应的属性值,也称“对象的成员访问”.

  - 对象.属性名 :这种方式不适用于“数字或Symbol的类型”的属性名,这样的情况只能基于 对象[属性名] 来访问.
  - 对象[属性名] :这种方式必须指定好属性的类型,若是字符串,必须加"" ,而 “obj[name] 和 obj["name"] 不是一个情况”.
          
         let obj = {
	     sex: 0
		 };
         // 1.获取指定属性名的属性值.
	 console.log(obj.sex); //=>0
	 console.log(obj['sex']); //=>0
         //2.如果指定的属性不存在,获取到的属性值是undefined(不会报错)
         console.log(obj['age']); //=>undefined
        // 3.获取当前对象中所有的属性名:返回结果是包含所有属性名的数组.
         console.log(Object.keys(obj)); // =>["sex"]
  
        var obj = {
        name: '云朵',
            0: 100
        };
        console.log(obj.name); //'云朵'
        console.log(obj["name"]); //'云朵'
        console.log(obj[0]); //100
        console.log(obj.0); //Uncaught SyntaxError: missing ) after argument list 
        console.log(obj.age); //访问对象的某个成员,如果当前成员没有在对象中,不会报错,访问到的结果是undefined而已
        console.log(age); //如果是访问一个不存在变量,则会报错 Uncaught ReferenceError: age is not defined

obj['x']和obj[x]的区别

  • 'x' 字符串类型的值.

  • x 它不是值,它是一个变量,代表变量x存储的值10.

  • obj[值] 直接是对象的成员访问.

  • obj[变量] 首先获取变量x值,然后把变量x存储的值作为属性名,再进行对象的成员访问.

        ar x = 10;
        var obj = {
            x: "云朵",
            10: 100
        };
        console.log(obj.x); //访问当前对象属性名是"x"对应的属性值 ->"云朵"
        console.log(obj['x']); //和上面操作是一个意思,也是访问"x"的属性值 ->"云朵"
        console.log(obj[x]); //首先获取x变量存储的值,把存储的值10作为属性名,进行对象的成员访问  => obj[10] ->100
           
        let n = 100;
	let obj = {
	    1: 100
	};
	console.log(obj[1]);
	console.log(obj.1); //=>Uncaught SyntaxError: missing ) after argument list 基于点的方式操作有自己的局限性,属性名不能是数字的,不能 对象.数字属性,此时只能用 对象[数字属性]
	console.log(obj[1]);
	console.log(obj['1']); //=>其它非字符串格式作为属性名和字符串格式没啥区别
	obj.n = 200; //=> {n:200}  n是属性名(数据格式是字符串)
	obj['n'] = 200; //=> {n:200} 
	obj[n] = 200; //=> {100:200} => obj[100]=200   n本身是一个变量(n和'n'的区别:前者是一个变量,后者是一个字符串的值),它代表的是所存储的值100(是一个数字格式)
	obj[m] = 200; //=>Uncaught ReferenceError: m is not defined   m这个变量没有被定义
	obj[true] = 300; //=>{true:300}
	obj[undefined] = 400; //=>{undefined:400}

3. 管理一个对象的成员

  • 直接编写在大括号{}中的,(而对于Symbol或者对象类型的属性名,以及需要把一个变量存储的值作为属性名,都需要基于中括号[]包裹起来,保证语法的正确性)

  • 基于JS动态管理成员(新增/修改/删除)

  • 对象的成员是不允许重复的(0和'0'是按照相同的成员处理的),在动态管控的时候,之前有这个成员则是修改成员的属性值,没有这个成员才是给对象新增一个成员.

        var symb = Symbol('xx');
        var obj = {
            name: '云朵',
            0: 10,
            // symb: 'xxx', //这样处理,属性名就是"symb",而不是这个变量存储的值
            [symb]: 'xxx' //这样处理,属性名是Symbol(xx),等同于把变量存储的值作为属性名
        };
        console.log(obj[symb]); //=>'xxx'
        
        var symb = Symbol('xx');
        var obj = {
            name: '云朵',
            0: 10
        };
        obj.age = 11; //给obj增加age这个属性
        obj["age"] = 11; //给obj增加age这个属性
        obj["symb"] = 'xxx'; //相当于给obj增加symb:'xxx'这个属性
        obj[symb] = 'xxx'; // -> obj[Symbol(xx)]='xxx' 相当于给obj增加Symbol('xx'):'xxx'这个属性
        obj['name'] = "云朵"; //相当于修改了name这个属性
        console.log(obj[0]); //=>10
        console.log(obj["0"]); //=>10
        
        // 假删除:利用访问对象不存在的成员,返回undefined的特征,我们把某个成员的值修改为undefined,
           这样以后再获取这个成员,结果也是undefined,我们则可以认为当前成员是不存在(本质还是存在的)
        obj.name = undefined;
        
        // 真删除:彻底从对象中移除这个成员
        delete obj["name"];
        console.log(obj);    

特殊对象

特殊对象:数组或者类数组对象(集合).

  • 属性名(成员/键)是数字,而且数字从零开始,逐级递增,

    • 有顺序和规律的数字属性名被称为“索引”:记录每一项的位置信息的.
    • 第一项索引是0,第二项索引是1...最后一项索引是length-1.
  • 有一个length成员,存储集合的长度.

    “数组/类数组[索引]” 进行成员访问以及相关的操作.

        // 数组 =>它是Array类的实例,用[]包起来.
        var arr = [10, 20, 30];
        console.log(arr[0]); //获取第一项的值
        console.log(arr[arr.length - 1]); //获取最后一项的值
        console.log(arr);
       
        // 类数组(类似于数组,但不是数组) =>不是Array的实例,虽然结构类似,但是不能直接使用数组的办法
        var obj = {
            0: 10,
            1: 20,
            2: 30,
            length: 3
        };
        console.log(obj);
        
        // HTMLCollection元素集合:类数组
        console.log(document.getElementsByTagName('*'));
        // NodeList节点集合:类数组
        console.log(document.querySelectorAll('*'));

五、函数function数据类型

函数 : 就是一个方法,可以实现某个功能.

为什么会有对象呢?

  • 我们把描述当前事物的属性或者方法(特点)存放在一起,防止变量的覆盖或者冲突
        var person1={
          name:'xxx',
          age:25
        };

为什么会有函数呢?

  • 函数其实就是一个方法/一个功能体

  • 封装:把实现当前功能的代码封装到函数中,后期想要实现这个功能直接调用函数执行,无需重新编写代码,这样提高了开发的效率,减少了页面中的冗余代码 “低耦合,高内聚”

  • 闭包:私有化

  • ...

            var n = 10,
                m = 20;
            var total = n + m;
            var average = (total / 2).toFixed(2);
            console.log(average);
    
            var n = 17,
                m = 28;
            var total = n + m;
            var average = (total / 2).toFixed(2);
            console.log(average);
    
            var n = 189,
                m = 231;
            var total = n + m;
            var average = (total / 2).toFixed(2);
            console.log(average);

创建函数 function sum(x, y){...}

  • sum函数名(等同于变量,也是声明一个sum变量,只不过存储的值是一个函数)

  • x或y :形参(变量),存储传递实参信息的,它是函数提供的一个入口(原因:封装这个功能,很多信息信息此时不清楚,执行时候用户传递给我才清楚)

  • {...}函数体:编写具体功能代码的区域

      function sum(x, y) {
      //console.log(sum); //-> ƒ sum(x, y) {}  sum变量(函数名)代表的是函数本身
      var total = x + y,
      average = total / 2;
      average = average.toFixed(2);
      console.log(average);
      }

执行函数 函数(实参1,实参2,...)

  • 实参(具体的值):就是给函数的形参变量传递的具体值.

        sum(17, 28);
        sum(189, 231); 
        sum(); //x=undefined y=undefined
        sum(10); //x=10 y=undefined  => NaN 创建函数定义了形参,但是执行时候没有传递实参值,则默认形参变量的值是undefined
        sum(10, 20); //x=10 y=20  =>15.00
        sum(10, 20, 30); //x=10 y=20  =>15.00

项目中一般会对形参进行默认值处理

  • if条件判断
            function sum(x, y) {
            if (x === undefined) //若x没有传值,则x = 0.
            {
                x = 0;
            }
            if (y === undefined) 
            //if (typeof y === "undefined") 
            {
                y = 0;
            } 
            var total = x + y,
            average = total / 2;
            average = average.toFixed(2);
            console.log(average);
          }
            sum(); // =>0
            sum(10); // x=10 y=0 => 5.00 
            sum(10, 20); // x=10 y=20  =>15.00
            sum(10, 20, 30); // =>15.00
  • 逻辑或|| 和 逻辑与&&
    • A||B 首先看A是真还是假,如果A是真返回A的值,如果A是假返回B的值.

    • A&&B 首先看A是真还是假,如果A是真返回B的值,如果A是假返回A的值.

    • 两者同时出现,&&优先级高于||. 只有“0/NaN/空字符串/null/undefined”是假,其余都是真.

           function sum(x, y) {
           // 对于 x = x || 0; 这个办法,x或y的值不仅仅是undefined会变为0,当x或y的值是 0/NaN/空字符串/null 的时候也都会变为0,这种方法相对不严谨,但是可以这样处理.
            x = x || 0; //当x是undefined即x为假时,返回0.
            y = y || 0; 
            var total = x + y,
            average = total / 2;
            average = average.toFixed(2);
            console.log(average);
        }
            sum(); // =>0
            sum(10); // x=10 y=0 => 5.00 
            sum(10, 20); // x=10 y=20  =>15.00
            sum(10, 20, 30); // =>15.00
  • ES6中的形参赋值默认值
    • 设定形参不传递值,这时形参为等号后面的默认值,
    • 但是一旦传递值了(undefined除外,当传的值是undefined时,形参为0),不论传递什么都不会为默认值.
            function sum(x = 0, y = 0) {
            var total = x + y,
            average = total / 2;
            average = average.toFixed(2);
            // 在函数体中一定可以拿到处理完成的结果的
            console.log(average); //"15.00"
            }
            sum(10, 20);
            console.log(average); // Uncaught ReferenceError: average is not defined (在函数体外,是不能直接访问函数体中的内容的,函数内部的东西,是不允许我们直接拿函数内部东西的(内部的东西是私有的变量))
                                 
                               

函数的出口:返回值机制

return

  • return后面是啥,返回值就是啥.

  • 不写return或return后面啥都没有,默认返回值都是undefined.

  • 函数体中只要遇到return,函数体中,return下面的代码都不会再执行的.

  • return的一定是一个值,return average也不是返回变量,而是把变量存储的结果返回 -> return '15.00'.

            function sum(x = 0, y = 0) {
            var total = x + y,
            average = total / 2;
            average = average.toFixed(2);
            return average; //-> return '15.00'
            // 函数体中只要遇到return,函数体中,return下面的代码都不会再执行的
            console.log('OK');
          }
           var result = sum(10, 20);// sum(10, 20)返回的值是15.00
           console.log(result);// => 15.00

正常创建函数:声明一个变量叫做fn(函数名),只不过存储的值是一个函数.

function fn() {}

匿名函数(没有函数名字)

  • 函数表达式:把创建的函数当作值,赋值给变量或者其他内容.

  • 自执行函数:创建函数和执行函数一起完成了.

“函数表达式”创建函数:和上面方式的效果是一样的(在变量提升中有一些区别)

        var fn = function () {
        // 这个里面也相当于函数表达式:创建一个匿名函数,把其作为值返回.
        return function () {}
        };
        var f = fn();
        //事件绑定:把函数当作值赋值给body的点击事件,当点击body的时候触发函数执行
        document.body.onclick = function () {}; 

自执行函数:第一个小括号中存放的是创建的函数,第二个小括号是把函数执行

         (function (x) {
          // ...
         })(100); //实参100传给了形参x.
        //除了用小括号把函数包裹起来可以解决语法错误(因为创建的函数没有名字)的问题,在前面加 ~、+、-、! 也都可以让语法正确
        ~ function (x) {
          // ...
        }(100); 

需求:执行函数的时候传递实参值,但是传递多少个实参“不确定”,我们想接受函数传递的实参信息.

  • 设定形参变量:但是需要知道传递实参的数量和顺序.
  • 函数内置实参集合 arguments(兼容所有浏览器):不论是否传递以及传递多少实参(也不管是否设定形参),集合中包含了所有传递的是实参信息.
    • 不传递就是一个空集合.
    • 这个集合是一个“类数组”.
  • ES6中的“...”剩余运算符(ES6中的,不兼容一般浏览器):函数形参中的剩余运算符,可以获取到,除前面设定形参变量接收到的实参外,剩下的实参都放到这个集合中.
    • 如果一个形参变量都没有定义,则所有传递的实参信息都存到这个集合中.

    • 这个集合是一个“数组”集合,params变量存储参数集合.

        function fn(...params) {
          console.log(params);
          //console.log(arguments);
          //console.log(params,arguments);
        }
        fn();
        fn(10);
        fn(10, 20);
        fn(10, 20, 30);

ES6中“创建函数”的新方式:“箭头函数”「所有箭头函数都是函数表达式创建方式」

  • 创建函数的语法不一样.

  • 执行函数是一致的. fn()

        var xxx = ([形参])=>{
          [函数体]
        }
  • 箭头函数
    • 如果只有一个形参,可以不加小括号

    • 如果函数体中只有一句话,而且是return xxx的,则可以省略函数体的大括号和return...

    • 箭头函数中没有arguments(想获得函数传递的所有实参信息但传递多少个实参“不确定”时,只能使用剩余运算符"..."了)

        function fn(x) {
          return x * 10;
        }
        //改为箭头函数
        var fn = (x) => {
          return x * 10;
        };
        // 只有一个形参,可以不加小括号
        // 如果函数体中只有一句话,而且是return xxx的,则可以省略函数体的大括号和return...
        // 即为
        var fn = x => x * 10; 

        function fn(x) {
           return function (y) {
               return x + y;
            };
        }
        //改写为箭头函数
        var fn = x => y => x + y