• 3.JS


    1.简介

    JavaScript 因为互联网而生,紧随着浏览器的出现而问世

    1997年7月,ECMAScript 1.0发布。

    1998年6月,ECMAScript 2.0版发布。

    1999年12月,ECMAScript 3.0版发布,成为JavaScript的通行标准,得到了广泛支持。

    2007年10月,ECMAScript 4.0版草案发布,对3.0版做了大幅升级,预计次年8月发布正式版本。草案发布后,由于4.0版的目标过于激进,各方对于是否通过这个标准,发生了严重分歧。以Yahoo、Microsoft、Google为首的大公司,反对JavaScript的大幅升级,主张小幅改动;以JavaScript创造者Brendan Eich为首的Mozilla公司,则坚持当前的草案。

    2008年7月,由于对于下一个版本应该包括哪些功能,各方分歧太大,争论过于激进,ECMA开会决定,中止ECMAScript 4.0的开发(即废除了这个版本),将其中涉及现有功能改善的一小部分,发布为ECMAScript 3.1,而将其他激进的设想扩大范围,放入以后的版本,由于会议的气氛,该版本的项目代号起名为Harmony(和谐)。会后不久,ECMAScript 3.1就改名为ECMAScript 5。

    2009年12月,ECMAScript 5.0版正式发布。Harmony项目则一分为二,一些较为可行的设想定名为JavaScript.next继续开发,后来演变成ECMAScript 6;一些不是很成熟的设想,则被视为JavaScript.next.next,在更远的将来再考虑推出。TC39的总体考虑是,ECMAScript 5与ECMAScript 3基本保持兼容,较大的语法修正和新功能加入,将由JavaScript.next完成。当时,JavaScript.next指的是ECMAScript 6。第六版发布以后,将指ECMAScript 7。TC39预计,ECMAScript 5会在2013年的年中成为JavaScript开发的主流标准,并在此后五年中一直保持这个位置。

    2011年6月,ECMAscript 5.1版发布,并且成为ISO国际标准(ISO/IEC 16262:2011)。到了2012年底,所有主要浏览器都支持ECMAScript 5.1版的全部功能。

    2013年3月,ECMAScript 6草案冻结,不再添加新功能。新的功能设想将被放到ECMAScript 7。

    2013年12月,ECMAScript 6草案发布。然后是12个月的讨论期,听取各方反馈。

    2015年6月,ECMAScript 6正式发布,并且更名为“ECMAScript 2015”。这是因为TC39委员会计划,以后每年发布一个ECMAScirpt的版本,下一个版本在2016年发布,称为“ECMAScript 2016”。

    除了ECMAScript的版本,很长一段时间中,Netscape公司(以及继承它的Mozilla基金会)在内部依然使用自己的版本号。这导致了JavaScript有自己不同于ECMAScript的版本号。1996年3月,Navigator 2.0内置了JavaScript 1.0。JavaScript 1.1版对应ECMAScript 1.0,但是直到JavaScript 1.4版才完全兼容ECMAScript 1.0。JavaScript 1.5版完全兼容ECMAScript 3.0。目前的JavaScript 1.8版完全兼容ECMAScript 5。

    2.JS的引入方式

    2.1 嵌入式

     

    2.2 导入式

      



    3.基本语法

    3.1变量

    复制代码
    // 方式1 先声明再赋值
    var 变量名;   // 声明的变量如果没有进行赋值,或者没有被定义的变量,值默认是undefined
    变量名 = 变量值;
    // 方式2 声明并赋值
    var 变量名 = 变量值;
    // 方式3 一行可以声明多个变量.并且可以是不同类型
    var name="yuan", age=20, job="lecturer";
    复制代码

    1、声明变量时 可以不用var. 如果不用var 那么它是全局变量

    2、变量命名,首字符只能是字母,下划线,$美元符 三选一,余下的字符可以是下划线、美元符号或任何字母或数字字符且区分大小写

    3.2注释

    // 单行注释
    
     /*
       多行注释
     */

     

    3.3语句分隔符

    var a = 1;   // 分号和换行符作为语句分隔符号
    var b = 2;
    console.log(a,b);

    4.基本数据类型

    4.1 数字类型

    JavaScript 没有整型和浮点型,只有一种数字类型,即number类型

    var x = 10;
    var y = 3.14;
    console.log(x,typeof x);  // 10 "number"
    console.log(y,typeof y);  // 3.14 "number"

     

    4.2 字符串

    字符串创建(两种方式)

    • 变量 = “字符串”

    • 字串对象名称 = new String (字符串)

    var str1="hello world";
    var str1= new String("hello word");

    字符串常用方法

    复制代码
    var str = "hello";
    console.log(str);
    
    // length 计算字符串的长度
    console.log( str.length );
    
    // 字符串对象内置方法
    // toUpperCase();  字母大写转换
    // toLowerCase();  字母小写转换
    console.log( str.toUpperCase() );
    console.log( str.toLowerCase() );
    
    // indexOf 获取指定字符在字符串中第一次出现的索引位置
    // 字符串也有下标,也可以使用中括号来提取字符串的指定字符
    console.log(str[1]); // e
    console.log( str.indexOf("e") ); // 1
    
    // 切片,当前方法支持使用负数代表倒数下标
    // slice(开始下标)   从开始位置切到最后
    // slice(开始下标,结束下标)  从开始下标切到指定位置之前
    var str = "helloworld";
    var ret = str.slice(3,6); // 开区间,不包含结束下标的内容
    console.log(ret); // low
    var ret = str.slice(5);
    console.log(ret); // world
    var ret = str.slice(2,-1);
    console.log(ret); // lloworl
    var ret = str.slice(-4,-1);
    console.log(ret); // orl
    var ret = str.slice(-1,-4);
    console.log(ret); // orl
    
    // split   正则分割,经常用于把字符串转换成数组
    var str = "广东-深圳-南山";
    var ret = str.split("-");
    console.log( ret );
    
    // substr  截取
    var str = "hello world";
    var ret = str.substr(0,3);
    console.log(ret); // hel
    
    // trim    移除字符串首尾空白
    var password = "    ge llo   ";
    var ret = password.trim();
    console.log(password.length); // 13
    console.log(ret.length);  // 6
    复制代码

     

    4.3 布尔值

    Boolean类型仅有两个值:true和false,也代表1和0,实际运算中true=1,false=0

    console.log(true);
    console.log(false);

     

    4.4 空值

    • undefined类型
      (1)当声明的变量未初始化时,该变量的默认值是 undefined。
      (2)当函数无明确返回值时,返回的也是值 undefined;

    • null类型
      另一种只有一个值的类型是 null,它只有一个专用值 null,即它的字面量。值 undefined 实际上是从值 null 派生来的,因此 ECMAScript 把它们定义为相等的。
      尽管这两个值相等,但它们的含义不同。undefined 是声明了变量但未对其初始化时赋予该变量的值,null 则用于表示尚未存在的对象。如果函数或方法要返回的是对象,那么找不到该对象时,返回的通常是 null。

    4.5 类型转换

    js中,类型转换有2种.一种就是强制转换,一种就是自动转换.

    • 强制转换

      复制代码
      // 1. 转换数据为数值类型
       // parseInt     把数据转换成整数
       // parseFloat   把数据转换成小数
       // Number       把数据转换成数值
       var box1 = "一共100件"; // 转换会失败
       var box1 = "100件";     // 转换会成功
       var ret = parseInt(box1);
       console.log(box1);
       console.log(ret);
       ​
       var box2 = "3.14";
       console.log(parseFloat(box2) ); // 3.14
      var box3 = "3.14";   // 使用Number转换的数据里面必须是纯数字!!!!否则都会转换失败
       // var box3 = "3.1.4";  // 转换失败!
       console.log( Number(box3) );
       ​
       // 对于转换数值,如果转换失败的话,则结果为 NaN ,是 Not a Number ,但是NaN的类型也是number类型
      // 2. 转换数据为字符串
       // 变量.toString()
       // String(数据)
       var box4 = 3.14;
       var ret = box4.toString();
       console.log(ret);
       ​
       ret = String(box4);
       console.log(ret);
       ​
       // 3. 转换数据成布尔类型
       // Boolean()
      var box5 = "";
       console.log( Boolean(box5) ); // false
       var box6 = -1;
       console.log( Boolean(box6) ); // true
       var box7 = 0;
       console.log( Boolean(box7) ); // false;
       var box8 = "false";
       console.log( Boolean(box8) ); // true
       var box9 = [];
       console.log( Boolean(box9) ); // true
       var box10 = {};
       console.log( Boolean(box10) ); // true
       var box11 = "0";
       console.log( Boolean(box11) ); // true
       var box12 = null;
       console.log( Boolean(box12) ); // false
       var box13 = undefined;
       console.log( Boolean(box13) ); // false
      复制代码

       

    • 自动转换

      复制代码
      // 所谓的自动转换,其实弱类型中的变量会根据当前代码的需要,进行类型的自动隐式转化
       var box1 = 1 + true;
       // true 转换成数值,是1, false转换成数值,是0
       console.log(box1); // 2
      var box2 = 1 + "200";
       console.log(box2); // 1200 原因是,程序中+的含义有2种,第一: 两边数值相加, 第二: 两边字符串拼接.但是在js中运算符的优先级中, 字符串拼接的优先级要高于数值的加减乘除,所以解析器优先使用了+号作为了字符串的拼接符号了,因为程序就需要+号两边都是字符串才能完成运算操作,因此1变成字符串最终的结果就是 "1" +"200"
      var box3 = 1 - "200";
       console.log(box3); // -199;因为-号中表示的就是左边的数值减去右边的数值,因此程序就会要求"200"是数值,因此内部偷偷的转换了一下
      复制代码

       

    5.运算符

    复制代码
    /*
    //算术运算符
           +   数值相加
           -   数值相减
           *   数值相乘
           /   数值相除
           %   数值求余
           **  数值求幂
           a++ 数值后自增1   a=a+1
           ++a 数值前自增1   a=a+1
           b-- 数值后自减1   b=b-1
           --b 数值前自减1   b=b-1
       
    //赋值运算符
           =
           +=
           -=
           *=
           /=
           %=
           **=
    
    //比较运算符,比较的结果要么是true, 要么是false
          >   大于
          <   小于
          >=  大于或者等于
          <=  小于或者等于
          !=  不等于[计算数值]
          ==  等于[计算]
    
          !== 不全等[不仅判断数值,还会判断类型是否一致]
          === 全等[不仅判断数值,还会判断类型是否一致]
    
    //逻辑运算符
          &&   并且  and    两边的运算结果为true,最终结果才是true
          ||   或者  or     两边的运算结果为false,最终结果才是false
          !    非    not    运算符的结果如果是true,则最终结果是false ,反之亦然.
     
      //逻辑运算符进阶用法:
         1. 实现短路
            var a = false || 2      >>> a = 2
            var a = true && "hehe"  >>>  a = "hehe"
         
         2. 快速布尔化[把数据快速转换成布尔类型]
            var a = 100
            !!a  >>> true
    
    //条件运算符[三目运算符]
                 条件?true:false
         例如:
              var age = 12;
            var ret = age>=18?"成年":"未成年"; // 相当于 python中的"成年" if age >= 18 else "未成年"
            console.log(ret);
     */
    复制代码

     

    6.流程控制语句

    编程语言的流程控制分为三种:

    • 顺序结构(从上向下顺序执行)

    • 分支结构

    • 循环结构

    之前我们学习的方式就是顺序执行,即代码的执行从上到下,一行行分别执行。

    6.1 分支结构

    • if 分支语句

      复制代码
        if(条件){
            // 条件为true时,执行的代码
          }
          
          if(条件){
            // 条件为true时,执行的代码
          }else{
            // 条件为false时,执行的代码
          }
          
          if(条件1){
            // 条件1为true时,执行的代码
          }else if(条件2){
            // 条件2为true时,执行的代码
          
          }....
          
          }else{
            // 上述条件都不成立的时候,执行的代码
          }
      复制代码
    • switch语句

      复制代码
      switch(条件){
             case 结果1:
                  满足条件执行的结果是结果1时,执行这里的代码..
                  break;
             case 结果2:
                  满足条件执行的结果是结果2时,执行这里的代码..
                  break;
             .....
             default:
                  条件和上述所有结果都不相等时,则执行这里的代码
          }
      复制代码

    1、switch比if else更为简洁

    2、执行效率更高。switch…case会生成一个跳转表来指示实际的case分支的地址,而这个跳转表的索引号与switch变量的值是相等的。从而,switch…case不用像if…else那样遍历条件分支直到命中条件,而只需访问对应索引号的表项从而到达定位分支的目的。

    3、到底使用哪一个选择语句,代码环境有关,如果是范围取值,则使用if else语句更为快捷;如果是确定取值,则使用switch是更优方案。

    6.2 循环结构

    • while循环

      while(循环的条件){
       // 循环条件为true的时候,会执行这里的代码
       }
    • for循环

      复制代码
      // 循环三要素
       for(1.声明循环的开始; 2.条件; 4. 循环的计数){
       // 3. 循环条件为true的时候,会执行这里的代码
       }
       ​
       for(循环的成员下标 in 被循环的数据){
       // 当被循环的数据一直没有执行到最后下标,都会不断执行这里的代码
       }   
      复制代码
    • 退出循环(break和continue)

      复制代码
      for (var i = 0;i<100;i++){
                  if (i===88){
                      continue  // 退出当次循环
                      // break  // 退出当前整个循环
                  }
                  console.log(i)
              }
      复制代码

       

    7.数组对象

    • 创建数组

       创建方式1:
       var arrname = [元素0,元素1,….];          // var arr=[1,2,3];
       ​
       创建方式2:
       var arrname = new Array(元素0,元素1,….); // var test=new Array(100,"a",true);
    • 遍历

       var arr = [111,222,333]
       for (var i in arr){
           console.log(i,arr[i])
       }
    • 数组方法

      复制代码
      var arr = ["A","B","C","D"];
      
      // (1) pop()  出栈,删除最后一个成员作为返回值
      var arr = [1,2,3,4,5];
      var ret = arr.pop();
      console.log(arr); // [1, 2, 3, 4]
      console.log(ret); // 5
      
      
      // (2) push() 入栈,给数组后面追加成员
      var arr = [1,2,3,4,5];
      arr.push("a");
      console.log(arr); // [1, 2, 3, 4, 5, "a"]
      
      
      // (3) shift是将数组的第一个元素删除
      var arr = [1,2,3,4,5];
      arr.shift()
      console.log(arr); // [2, 3, 4, 5]
      
      // (4) unshift是将value值插入到数组的开始
      var arr = [1,2,3,4,5];
      arr.unshift("yuan")
      console.log(arr); // ["yuan",1,2, 3, 4, 5]
      
      
      // (5) reverse() 反转排列
      var arr = [1,2,3,4,5];
      arr.reverse();
      console.log(arr); // [5, 4, 3, 2, 1]
      
      // (6) slice(开始下标,结束下标)  切片,开区间
      
      
      // (7) sort() 排序
      var arr = [3,4,1,2,5,10];
      console.log( arr ); // [3, 4, 1, 2, 5, 10]
      arr.sort();
      //
      // // 这是字符的排序,不是数值的排序
      console.log(arr);   //  [1, 10, 2, 3, 4, 5]
      
      // 数值升序
      var arr = [3,4,1,2,5,10];
      arr.sort(function(a,b){
          return a-b;
      });
      console.log(arr);  // [1, 2, 3, 4, 5, 10]
      
      // 数值降序
      var arr = [3,4,1,2,5,10];
      arr.sort(function(a,b){
          return b-a;
      });
      console.log(arr); // [10, 5, 4, 3, 2, 1]
      
      // (8) splice(操作位置的下标,删除操作的成员长度,"替换或者添加的成员1","替换或者添加的成员2")  添加/删除指定的成员   "万能函数"
      var arr1 = [1,2,3];
      arr1.splice(1,1);
      console.log(arr1); // 删除指定的1个成员  [1, 3]
      
      var arr2 = ["a","b","c","d"];
      arr2.splice(2,0,"w","x","w"); // 添加
      console.log(arr2); // ["a", "b", "w", "x", "w", "c", "d"]
      
      var arr3 = ["a","b","c"];
      arr3.splice(1,1,"w");
      console.log(arr3); // ["a", "w", "c"]
      
      // (9) concat() 把2个或者多个数组合并
      var arr1 = [1,2,3];
      var arr2 = [4,5,7];
      var ret = arr1.concat(arr2);
      console.log( ret );
      
      
      // (10) join()  把数组的每一个成员按照指定的符号进行拼接成字符串
      var str = "广东-深圳-南山";
      var arr = str.split("-");
      console.log( arr ); // ["广东", "深圳", "南山"];
      
      var arr1 = ["广东", "深圳", "南山"];
      var str1 = arr1.join("-");
      console.log( str1 ); // 广东-深圳-南山
      
      
      // (11) find()  高阶函数, 返回符合条件的第一个成员
      var arr = [4,6,5,7];
      var func = (num)=>{
          if(num%2===0){
              return num;
          }
      };
      var ret = arr.find(func);
      console.log( ret ); // 4
      
      // (12)  filter() 高阶函数, 对数组的每一个成员进行过滤,返回符合条件的结果
      var arr = [4,6,5,7];
      function func(num){  // 也可以使用匿名函数或者箭头函数
          if(num%2===0){
              return num;
          }
      }
      var ret = arr.filter(func);  // 所有的函数名都可以作为参数传递到另一个函数中被执行
      console.log( ret );
      
      // (13) map() 对数组的每一个成员进行处理,返回处理后的每一个成员
      var arr = [1,2,3,4,5];
      var ret = arr.map((num)=>{
          return num**3;
      });
      console.log( ret  ); // [1, 8, 27, 64, 125]
      
      // (14) 其它方法
      // includes   查询指定数据是否在数组中存在!
      // indexOf()  查询指定数据在数组中第一次出现的位置
      // isArray()  判断变量的值是否是数组
             
      复制代码

       

    8.Object对象

    Object 的实例不具备多少功能,但对于在应用程序中存储和传输数据而言,它们确实是非常理想的选择。

    • 创建对象

      复制代码
      // 方式一
       var person = new Object();
       person.name = "alvin";
       person.age = 18;
       ​
       // 方式二
       var person = {
                       name : "alvin",
                       age : 18
                    }; 
      复制代码
    • 访问成员 object可以通过. 和 []来访问。

      console.log(person["age"]);
       console.log(person.age)
    • 遍历

      for (var attr in person){
         console.log(attr,person[attr]);
       }
    • 序列化和反序列化

      复制代码
      var data = {
         name: "xiaoming",
         age: 22,
       };
       ​
       // 把json对象转换成json字符串
       var ret = JSON.stringify(data);
       console.log(ret ); // {"name":"xiaoming","age":22}
      // 把json字符串转换成json对象
       var str = `{"name":"xiaoming","age":22}`;
       var ret = JSON.parse(str);
       console.log(ret);
      复制代码

       

    9.Data对象

    • 创建Date对象

      复制代码
       //方法1:不指定参数
       var nowd1=new Date();
       console.log(nowd1.toLocaleString( ));
       ​
       //方法2:参数为日期字符串
       var d2=new Date("2004/3/20 11:12");
       console.log(d2.toLocaleString( ));
       var d3=new Date("04/03/20 11:12");
       console.log(d3.toLocaleString( ));
       ​
       //方法3:参数为毫秒数
       var d4=new Date(5000);
       console.log(d4.toLocaleString( ));
       console.log(d4.toUTCString());
       ​
       //方法4:参数为年月日小时分钟秒毫秒
       var d5=new Date(2004,2,20,11,12,0,300);
       console.log(d5.toLocaleString( ));//毫秒并不直接显示
      复制代码

       

    • 获取时间信息

      复制代码
       获取日期和时间
       getDate()                 获取日
       getDay ()                 获取星期
       getMonth ()               获取月(0-11)
       getFullYear ()            获取完整年份
       getYear ()                获取年
       getHours ()               获取小时
       getMinutes ()             获取分钟
       getSeconds ()             获取秒
       getMilliseconds ()        获取毫秒
       getTime ()                返回累计毫秒数(从1970/1/1午夜)
      复制代码

       

    • 日期和时间的转换

      复制代码
       日期和时间的转换:
       // 返回国际标准时间字符串
       toUTCString()
       // 返回本地格式时间字符串
       toLocalString()
       // 返回累计毫秒数(从1970/1/1午夜到本地时间)
       Date.parse(x)
       // 返回累计毫秒数(从1970/1/1午夜到国际时间)
       Date.UTC(x)
      复制代码

       

      复制代码
       function getCurrentDate(){
                   //1. 创建Date对象
                   var date = new Date(); //没有填入任何参数那么就是当前时间
                   //2. 获得当前年份
                   var year = date.getFullYear();
                   //3. 获得当前月份 js中月份是从0到11.
                   var month = date.getMonth()+1;
                   //4. 获得当前日
                   var day = date.getDate();
                   //5. 获得当前小时
                   var hour = date.getHours();
                   //6. 获得当前分钟
                   var min = date.getMinutes();
                   //7. 获得当前秒
                   var sec = date.getSeconds();
                   //8. 获得当前星期
                   var week = date.getDay(); //没有getWeek
                   // 2014年06月18日 15:40:30 星期三
                   return year+"年"+changeNum(month)+"月"+day+"日 "+hour+":"+min+":"+sec+" "+parseWeek(week);
               }
      复制代码

       

    10.Math对象

    复制代码
     //  Number对象的内置方法
     //  toFixed(x) 保留小数位
     var num = 100.3;
     var ret = num.toFixed(2);
     console.log(num);  // 100.3
     console.log(ret);  // 100.30
    
    // Math对象的内置方法
    // abs(x)  返回数值的绝对值
    // var num = -10;
    console.log( Math.abs(num) ); // 10
    
    // ceil(x)  向上取整
    var num = 10.3;
    console.log( Math.ceil(num) ); // 11
    
    // floor(x) 向下取整
    var num = 10.3;
    console.log( Math.floor(num) ); // 10
    
    // max(x,y,z,...,n)
    console.log( Math.max(3,56,3) ); // 56
    // min(x,y,z,...,n)
    
    // pow(x,y)
    console.log(Math.pow(3, 2)); // 相等于 3**2
    console.log( 3**2 ); // 使用这个,上面废弃
    
    // random()  生成0-1随机数
    console.log( Math.random() );
    
    // 生成0-10之间的数值
    console.log( Math.random() * 10 );
    
    // round(x) 四舍五入
    // 生成0-10之间的整数
    console.log( Math.round( Math.random() * 10 ) );
    复制代码

    11.Function对象

    函数在程序中代表的就是一段具有功能性的代码,可以让我们的程序编程更加具有结构性和提升程序的复用性,也能让代码变得更加灵活强大

    11.1 声明函数

    复制代码
    // 函数的定义方式1
    function 函数名 (参数){
        函数体;
        return 返回值;
    }
    功能说明:
        可以使用变量、常量或表达式作为函数调用的参数
        函数由关键字function定义
        函数名的定义规则与标识符一致,大小写是敏感的
        返回值必须使用return
        
    //  函数的定义方式2
        
    用 Function 类直接创建函数的语法如下:
    var 函数名 = new Function("参数1","参数n","function_body");
    
    虽然由于字符串的关系,第二种形式写起来有些困难,但有助于理解函数只不过是一种引用类型,它们的行为与用 Function 类明确创建的函数行为是相同的。 
    复制代码

     

    11.2 函数调用

    //f(); --->OK
    function f(){
    console.log("hello")
    
    }
    f() //----->OK

    不同于python,js代码在运行时,会分为两大部分———预编译 和 执行阶段。

    • 预编译:会先检测代码的语法错误,进行变量、函数的声明。

    • 执行阶段:变量的赋值、函数的调用等,都属于执行阶段。

     

    11.3 函数参数

    复制代码
    // 位置参数
    function add(a,b){
        console.log(a);
        console.log(b);
    }
    add(1,2)
    add(1,2,3)
    add(1)
    
    // 默认参数
    function stu_info(name,gender="male"){
        console.log("姓名:"+name+" 性别:"+gender)
    }
    
    stu_info("yuan")
    复制代码

    11.4 函数返回值

    在函数体内,使用 return 语句可以设置函数的返回值。一旦执行 return 语句,将停止函数的运行,并运算和返回 return 后面的表达式的值。如果函数不包含 return 语句,则执行完函数体内每条语句后,返回 undefined 值。

    function add(x,y) {
              return x+y
          }
    
    var ret = add(2,5);
    console.log(ret)

     

    11.5 匿名函数

    匿名函数,即没有变量名的函数。在实际开发中使用的频率非常高!也是学好JS的重点。

    复制代码
    // 匿名函数赋值变量
    var foo = function () {
    console.log("这是一个匿名函数!")
    };
    
    // 匿名函数的自执行
    (function (x,y) {
    console.log(x+y);
    })(2,3)
    
    
    // 匿名函数作为一个高阶函数使用
    function bar() {
      return function () {
          console.log("inner函数!")
      }
    }
    
    bar()()
    复制代码

     

    11.6 函数作用域

    变量的作用域有全局作用域和局部作用域两种。

    // 局部变量,是在函数内部声明,它的生命周期在当前函数被调用的时候, 当函数调用完毕以后,则内存中自动销毁当前变量
    // 全局变量,是在函数外部声明,它的生命周期在当前文件中被声明以后就保存在内存中,直到当前文件执行完毕以后,才会被内存销毁掉

     

    11.7 JS预编译

    js运行三个阶段:

    1. 语法分析

    2. 预编译

    3. 解释执行

    预编译可分为全局预编译和局部预编译。

    1. 在js脚本加载之后,会先通篇检查是否存在低级错误;

    2. 在语法检测完之后,便进行全局预编译;

    3. 在全局预编译之后,就解释一行,执行一行;

    4. 当执行到函数调用那一行前一刻,会先进行函数预编译,再往下执行。

    全局预编译的3个步骤:

    1. 创建GO对象(Global Object)全局对象,即window对象。

    2. 找变量声明,将变量名作为GO属性名,值为undefined

    3. 查找函数声明,作为GO属性,值赋予函数体

    局部预编译的4个步骤:

    1. 创建AO对象(Activation Object)执行期上下文。

    2. 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined

    3. 将实参值和形参统一。

    4. 在函数体里面找函数声明,值赋予函数体。

    GO对象是全局预编译,所以它优先于AO对象所创建和执行

    局预编译
         
    复制代码
    GO/window = {
             a: undefined,
             c: undefined,
             foo: function(a) {
                 console.log(a);
                 var a = 123;
                 console.log(a);
                 function a() {}
                 console.log(a);
                 var b = function() {}
                 console.log(b);
                 function d() {}
             }
         }
    复制代码

     

    解释执行代码(直到执行调用函数foo(20)语句)
     
    复制代码
    GO/window = {
             a: 10,
             c: function (){
                 console.log("I at C function");
             }
             test: function(a) {
                 console.log(a);
                 var a = 123;
                 console.log(a);
                 function a() {}
                 console.log(a);
                 var b = function() {}
                 console.log(b);
                 function d() {}
             }
         }
    复制代码

     

    调用函数foo(20)前发生布局预编译
    复制代码
     // 局部预编译前两步:
     AO = {
             a:undefined,
             b:undefined,
         }
     ​
     // 局部预编译第三步:
     AO = {
                 a:20,
                 b:undefined,
             }
     // 局部预编译第四步:
     AO = {
             a:function a() {},
             b:undefined
             d:function d() {}
         }
    复制代码

     

    预编译总结:

    1. 函数声明整体提升-(具体点说,无论函数调用和声明的位置是前是后,系统总会把函数声明移到调用前面)

    2. 变量 声明提升-(具体点说,无论变量调用和声明的位置是前是后,系统总会把声明移到调用前,注意仅仅只是声明,所以值是undefined)

    面试题:

    复制代码
     var num3 = 10;
     function func3(){
         console.log(num3); 
         var num3 = 20;       
     }
     func3();
     console.log(num3); 
     ​
     ​
      /*
     ​
             // 全局编译
     ​
             GO{
                num3:undefined,
                func3: function (){
                 console.log(num3);
                 var num3 = 20;
             }
     ​
             // 全局执行
             var num3 = 10;
             GO{
                num3:10,
                func3: function (){
                 console.log(num3);
                 var num3 = 20;
             }
     ​
     ​
             // 局部编译
             func3.AO{
                num3:undefined,
             }
     ​
     ​
             // 局部执行
     ​
             func3.AO{
                num3:20,
             }
     ​
             // 全局执行
     ​
             GO.num3 = 10
             }
     ​
     */
    复制代码

     

    12.BOM对象

    BOM:Broswer object model,即浏览器提供我们开发者在javascript用于操作浏览器的对象。

    12.1 window对象

    • 窗口方法

      复制代码
       // BOM  Browser object model 浏览器对象模型
      // js中最大的一个对象.整个浏览器窗口出现的所有东西都是window对象的内容.
       console.log( window );
       ​
       // alert()  弹出一个警告框
       window.alert("hello");
       ​
       //confirm  弹出一个确认框,点击确认,返回true, 点击取消,返回false
       var ret = confirm("您确认要删除当前文件么?");
       console.log( ret  );
       ​
       // 弹出一个消息输入框,当点击确认以后,则返回可以接收到用户在输入框填写的内容.如果点击取消,则返回null
       var ret = prompt("请输入一个内容","默认值");
       console.log( ret );
       ​
       // close() 关闭当前浏览器窗口
       window.close();
       ​
       //打开一个新的浏览器窗口
       window.open("http://www.baidu.com","_blank","width=800px,height=500px,left=200px,top=200px";
                   
      复制代码
    • 定时方法 setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数。而setTimeout是在指定的毫秒数后调用code一次。

      复制代码
      // 设置循环定时器
       var ID = window.setInterval(code,millisec)   // 每millisec毫秒执行一次code
       // 取消循环定时器
       window.clearInterval(ID);
       ​
       // 设置单次定时器
       var ID = window.setTimeout(code,millisec) // millisec毫秒后执行code一次
       // 取消单次定时器
       window.clearTimeout(ID);
      复制代码

       

    12.2 Location对象

    复制代码
    
     
     
         
         Title
     
     
     
     
     
     
     
     
    复制代码

     

     

    12.3 本地存储对象

    使用存储对象的过程中, 对象数据会根据域名端口进行保存的,所以 js不能获取当前页面以外其他域名端口保存到本地的数据。也就是说,我们存储对象获取数据只能是自己当前端口或者域名下曾经设置过的数据,一旦端口或者域名改变,则无法获取原来的数据。

    复制代码
     localStorage    本地永久存储
       localStorage.setItem("变量名","变量值");   保存一个数据到存储对象
       localStorage.变量名 = 变量值               保存一个数据到存储对象
     ​
       localStorage.getItem("变量名")   获取存储对象中保存的指定变量对应的数据
       localStorage.变量名              获取存储对象中保存的指定变量对应的数据
     ​
       localStorage.removeItem("变量名")   从存储对象中删除一个指定变量对应的数据
       localStorage.clear()               从存储对象中删除所有数据
     ​
     sessionStorage  本地会话存储
       sessionStorage.setItem("变量名","变量值");   保存一个数据到存储对象
       sessionStorage.变量名 = 变量值               保存一个数据到存储对象
     ​
       sessionStorage.getItem("变量名")   获取存储对象中保存的指定变量对应的数据
       sessionStorage.变量名              获取存储对象中保存的指定变量对应的数据
     ​
       sessionStorage.removeItem("变量名")   从存储对象中删除一个指定变量对应的数据
       sessionStorage.clear()               从存储对象中删除所有数据
    
    复制代码
     localStorage和sessionStorage的区别:
     ​
     1、localStorage和sessionStorage一样都是用来存储客户端临时信息的对象。
     ​
     2、他们均只能存储字符串类型的对象(虽然规范中可以存储其他原生类型的对象,但是目前为止没有浏览器对其进行实现)。
     ​
     3、localStorage生命周期是永久,这意味着除非用户显示在浏览器提供的UI上清除localStorage信息,否则这些信息将永远存在。sessionStorage生命周期为当前窗口或标签页,一旦窗口或标签页被永久关闭了,那么所有通过sessionStorage存储的数据也就被清空了。
     ​
     4、不同浏览器无法共享localStorage或sessionStorage中的信息。相同浏览器的不同页面间可以共享相同的 localStorage(页面属于相同域名和端口),但是不同页面或标签页间无法共享sessionStorage的信息。这里需要注意的是,页面及标 签页仅指顶级窗口,如果一个标签页包含多个iframe标签且他们属于同源页面,那么他们之间是可以共享sessionStorage的。

     

    13.DOM对象

    DOM  document Object Model 文档对象模型

    13.1 查找标签

    • 直接查找标签

       document.getElementsByTagName("标签名")
       document.getElementById("id值")
       document.getElementsByClassName("类名")

       

    • 导航查找标签

       elementNode.parentElement           // 父节点标签元素
       elementNode.children                // 所有子标签
       elementNode.firstElementChild       // 第一个子标签元素
       elementNode.lastElementChild        // 最后一个子标签元素
       elementNode.nextElementSibling     // 下一个兄弟标签元素
       elementNode.previousElementSibling  // 上一个兄弟标签元素

       

    • CSS选择器查找

       document.querySelector("css选择器")  //根据css选择符来获取查找到的第一个元素,返回标签对象(dom对象)
       document.querySelectorAll("css选择器"); // 根据css选择符来获取查找到的所有元素,返回数组

       

     
     1 DOCTYPE html>
     2  <html lang="en">
     3  <head>
     4      <meta charset="UTF-8">
     5      <title>Titletitle>
     6  head>
     7  <body>
     8  9 10  <div id="i1">DIV1div>
    11 12  <div class="c1">DIVdiv>
    13  <div class="c1">DIVdiv>
    14  <div class="c1">DIVdiv>
    15 16 17  <div class="outer">
    18      <div class="c1">itemdiv>
    19  div>
    20 21 22  <div class="c2">
    23      <div class="c3">
    24          <ul class="c4">
    25              <li class="c5" id="i2">111li>
    26              <li>222li>
    27              <li>333li>
    28          ul>
    29      div>
    30  div>
    31 32  <script>
    33 34     // 直接查找
    35 36     var ele = document.getElementById("i1");  // ele就是一个dom对象
    37     console.log(ele);
    38 39     var eles = document.getElementsByClassName("c1"); // eles是一个数组 [dom1,dom2,...]
    40     console.log(eles);
    41 42     var eles2 = document.getElementsByTagName("div"); // eles2是一个数组 [dom1,dom2,...]
    43     console.log(eles2);
    44 45     var outer = document.getElementsByClassName("outer")[0];
    46     var te = outer.getElementsByClassName("c1");
    47     console.log(te);
    48 49     // 导航查找
    50 51      var c5 = document.getElementsByClassName("c5")[0];
    52      console.log(c5);  // c5是一个DOM对象
    53 54      console.log(c5.parentElement.lastElementChild);  // 返回值是dom对象
    55      console.log(c5.parentElement.children);  // 返回值是dom对象数组
    56      console.log(c5.nextElementSibling.nextElementSibling);
    57      console.log(c5.parentElement.children);
    58 59      // css选择器
    60 61      var dom = document.querySelector(".c2 .c3 .c5");
    62      console.log(":::",dom);
    63 64      var doms = document.querySelectorAll("ul li");
    65      console.log(":::",doms);
    66      
    67  script>
    68 69  body>
    70  html>
    71 
    72  
    View Code

     

    13.2 绑定事件

    • 静态绑定 :直接把事件写在标签元素中。

      复制代码
      <div id="div" onclick="foo(this)">clickdiv><script>
           function foo(self){           // 形参不能是this;
               console.log("foo函数");
               console.log(self);   
           }
       script>
      复制代码
    • 动态绑定:在js中通过代码获取元素对象,然后给这个对象进行后续绑定。

      复制代码
       <p id="i1">试一试!p><script>var ele=document.getElementById("i1");
       ​
           ele.onclick=function(){
               console.log("ok");
               console.log(this);    // this直接用
           };
       ​
       script> 
      复制代码

    13.3 操作标签

     <标签名 属性1=“属性值1” 属性2=“属性值2”……>文本
    • 文本操作

      复制代码
       <div class="c1"><span>clickspan>div><script>var ele =document.querySelector(".c1");
       ​
           ele.onclick = function (){
               // 查看标签文本
               console.log(this.innerHTML)
               console.log(this.innerText)
           }
       ​
           ele.ondblclick = function (){
               // 设置标签文本
               this.innerHTML = "yuan"
               //this.innerText = "yuan"
           }
       ​
       script>
      复制代码

       

    • value操作  

      复制代码
       <input type="text" id="i1" value="yuan">
           <textarea name="" id="i2" cols="30" rows="10">123textarea>
           <select  id="i3">
               <option value="hebei">河北省option>
               <option value="hubei">湖北省option>
               <option value="guangdong">广东省option>
           select><script>// input标签
           var ele1 =document.getElementById("i1");
           console.log(ele1.value);
           ele1.onmouseover = function (){
               this.value = "alvin"
           }
       ​
           // textarea标签
           var ele2 =document.getElementById("i2");
           console.log(ele2.value);
           ele2.onmouseover = function (){
               this.innerText = "welcome to JS world!"
               this.value = "welcome to JS world!"
           }
           // select标签
           var ele3 =document.getElementById("i3");
           console.log(ele3.value);
           ele3.value= "hubei"script>
      复制代码

       

       

    • css样式操作

      复制代码
       <p id="i1">Hello world!p><script>
           var ele = document.getElementById("i1");
           ele.onclick = function (){
               this.style.color = "red"
           }
       script>
      复制代码

       

    • 属性操作
       elementNode.setAttribute("属性名","属性值")    
       elementNode.getAttribute("属性名")       
       elementNode.removeAttribute("属性名");

       

    • class属性操作
       elementNode.className
       elementNode.classList.add
       elementNode.classList.remove
    • 节点操作

      复制代码
       // 创建节点:
       document.createElement("标签名")
       // 插入节点
       somenode.appendChild(newnode)             // 追加一个子节点(作为最后的子节点)
       somenode.insertBefore(newnode,某个节点)   // 把增加的节点放到某个节点的前边
       // 删除节点
       somenode.removeChild():获得要删除的元素,通过父元素调用删除
       //替换节点
       somenode.replaceChild(newnode, 某个节点);
      复制代码

    13.4 常用事件

    • onload事件

      复制代码
      DOCTYPE html>
       <html lang="en">
       <head>
           <meta charset="UTF-8">
           <title>Titletitle>
       ​
       ​
           <script>
              window.onload = function (){
                   ele = document.getElementById("i1")
                   console.log(ele.innerHTML);
              }
           script>
           
       head>
       <body><div id="i1">yuandiv>body>
       html>
      复制代码

       

    • onsubmit事件

      复制代码
      DOCTYPE html>
       <html lang="en">
       <head>
           <meta charset="UTF-8">
           <title>Titletitle>head>
       <body><form action="" id="i1">
            用户名:<input type="text">
            密码:  <input type="password">
           <input type="submit">
       form>
       ​
       ​
       <script>var ele = document.getElementById("i1");
            var user = document.querySelector("#i1 [type=text]")
            var pwd = document.querySelector("#i1 [type=password]")
            ele.onsubmit = function (e){
                  console.log(user.value);
                  console.log(pwd.value);
       ​
                   return false;    // 终止事件执行
                  // e.preventDefault() // 阻止元素默认行为
            }
       ​
       script>
       body>
       html>
      复制代码

       

    • onchange事件

      复制代码
      DOCTYPE html>
       <html lang="en">
       <head>
           <meta charset="UTF-8">
           <title>Titletitle>head>
       <body><select name="provonce" id="s1">
           <option value="hebei">请选择省份option>
           <option value="hubei">湖北省option>
           <option value="hunan">湖南省option>
           <option value="hebei">河北省option>
       select><select name="provonce" id="s2">
           <option value="hebei">请选择城市option>select><script>var  data={"hunan":["长沙","岳阳","张家界"],"hubei":["武汉","襄阳","荆州"],"hebei":["石家庄","保定","张家口"]};
          console.log(data);
          var ele =  document.getElementById("s1");
          var ele2 =  document.getElementById("s2");
          ele.onchange=function () {
              console.log(this.value);
              var citys = data[this.value];
              console.log(citys);
              // 清空操作
              ele2.options.length=1;
              // 创建标签
              for (var i=0;i<citys.length;i++){
                  var option =  document.createElement("option"); // 
                  option.innerHTML=citys[i];
                  ele2.appendChild(option)
              }
          }
       ​
       script>
       ​
       ​
       body>
       html>
      复制代码

       

    • onmouse事件

      复制代码
      DOCTYPE html>
       <html lang="en">
       <head>
           <meta charset="UTF-8">
           <title>Titletitle>
           <style>
               #container{
                   width: 300px;
               }
               #title{
                   cursor: pointer;
                   background: #ccc;
               }
              #list{
                  display: none;
                  background:#fff;
              }
       ​
               #list div{
                   line-height: 50px;
               }
               #list  .item1{
                   background-color: green;
               }
       ​
                #list  .item2{
                   background-color: rebeccapurple;
               }
       ​
                #list  .item3{
                   background-color: lemonchiffon;
               }
       ​
       ​
           style>
       head>
       <body>
       <div id="container">
               <div id="title">使用了mouseout事件↓div>
               <div id="list">
                       <div class="item1">第一行div>
                       <div class="item2">第二行div>
                       <div class="item3">第三行div>
               div>
       div>
       <script>// 1.不论鼠标指针离开被选元素还是任何子元素,都会触发 mouseout 事件。
      // 2.只有在鼠标指针离开被选元素时,才会触发 mouseleave 事件。
      var container=document.getElementById("container");
          var title=document.getElementById("title");
          var list=document.getElementById("list");
          title.onmouseover=function(){
              list.style.display="block";
          };
       ​
          container.onmouseleave=function(){  // 改为onmouseout试一下
              list.style.display="none";
          };
       ​
       /*
       ​
       因为mouseout事件是会冒泡的,也就是onmouseout事件可能被同时绑定到了container的子元素title和list
       上,所以鼠标移出每个子元素时也都会触发我们的list.style.display="none";
       ​
       */
       script>
       body>
       html>
      复制代码

       

    • onkey事件

      复制代码
      <input type="text" id="t1"/><script type="text/javascript">var ele=document.getElementById("t1");
       ​
            ele.onkeydown=function(e){
               console.log("onkeydown",e.key)
           };
       ​
            ele.onkeyup=function(e){
               console.log("onkeyup",e.key)
           };
       script>
      
       
      
      onblur和onfocus事件
      
       <input type="text" class="c1">
       ​
       ​
       <script>var ele = document.querySelector(".c1");
       ​
           // 获取焦点事件
           ele.onfocus = function () {
               console.log("in")
           };
       ​
           // 失去焦点事件
           ele.onblur = function () {
               console.log("out")
           }
       ​
       script>
      复制代码

       

       

    • 冒泡事件

      复制代码
      <div class="c1">
           <div class="c2">div>
       div>
       ​
       ​
       <script>var ele1 = document.querySelector(".c1");
           ele1.onclick = function () {
               alert("c1区域")
           };
       ​
           var ele2 = document.querySelector(".c2");
           ele2.onclick = function (event) {
               alert("c2区域");
               
               // 如何阻止事件冒泡
               event.stopPropagation();
           }
       ​
       script>
      复制代码

       

     

  • 相关阅读:
    返回文件名问题
    求一份网页设计结课大作业,要求用到html,css,javascript,的知识
    spring 全家桶常用注解
    C++初识--------带你从不同的角度理解引用的巧妙之处
    腾讯云架构师整理总结的MySQL性能优化和高可用架构实践文档
    SaaSBase:什么是汇思?
    Python-time.time() 和 time.perf_counter()
    【设计模式】中介者模式
    How To Install and Configure VNC Server on Ubuntu 20.04
    【cloud Alibaba】(一)服务注册和配置中心——Nacos
  • 原文地址:https://www.cnblogs.com/victor1234/p/16888395.html