JavaScript (javascript和jscript)

目录

一、概念

1.  一门客户端脚本语言

2. 功能:

3. JavaScript发展史:

4. JavaScript = ECMAScript + JavaScript自己特有的东西(BOM+DOM)

二、JavaScript的三种引入方式

1. 行内式js

2. 内嵌式的js

3. 外部js

三、JavaScript的使用

1. 基本语法

2. 字面量

3. 变量

4. 声明变量(比如:设x=2)

5. 标识符

6. 数据类型

    (1)值/原始(简单数据)类型:

  (2)引用(复杂数据)类型:

7. 数据类型转换

       (1)隐式类型转换

       (2)显式类型转换

8. number(数字)

9. 将其他数据类型转化为number数字

10. string(字符串)

11. 将其他数据类型转化为string字符串

12. Boolean 布尔值

  (1)(布尔值只有两个),主要用来做逻辑判断    

  (2)   使用typeof(检查数据类型)检查一个布尔值时,会返回一个boolean

 (3)布尔值true和false参与加法运算时,true当数字型1来看,false当数字型0来看

13. 将其他数据类型转化为Boolean

14. undefined 未定义

15. null

16. 运算符

    (1)  算数运算符

   (2)  一元运算符

   (3)  逻辑运算符    

(4) 赋值运算符   

(5)比较运算符

(6)条件运算符(也叫三元运算符)

17. 语句

18. if else 语句

19. swith语句

20. 循环

   (1) for 循环语句

    双重for循环

  (2)while 循环语句

  (3)do while 循环语句

21. 循环语句中的 break 、continue

      (1)continue

      (2)break

      (3)案例

22. 数组(Arry:js的数组是弱类型)

(1)创建数组:    

  (2)  访问数组(数组的索引)

  (3)插入数组(新增元素):根据数组名和索引号添加(不要直接给数组名赋值,不然所有数组元素都没有了)

 (4)  删除指定数组元素(数组中的成员函数)

 (5)  清空一个数组:

23. 遍历数组(三种轮询数组的方法)

    (1)for(i)方法:按照数组的方式改动数组

    (2)for(in)方法:使用map的方式返回所有非稀疏的节点的key

    (3)forEach方法:返回所有数字的且非稀疏的节点的value

24 . 数组的操作

25. 数组排序

26. 多维数组(可以把数组作为一个元素给另外的数组)

    (1) 二维数组

    (2) 三维数组

27. 类数组

28.  函数

(1)函数的声明:

  (2)函数的调用:

29. 函数的形参和实参

30. 函数的返回值

31. 作用域

32. 执行环境和作用域链

33. 生成作用域链

34. 作用域链的应用

35. 预编译(预解析)(第一次/前置扫描)

   (1)  js引擎运行js分为两步,先预解析后代码执行

   (2)  预解析分为变量预解析(变量提升)和函数预解析(函数提升) 

36. 函数(预编译)

37. 函数(预编译)调用

38. 递归 

39. 闭包

40. this的用法

    (1) 在脚本中,this初始化为window

    (2) 在普通函数中,this初始化为window

    (3) 在object调用的函数中,this被指定为object,谁调用,指向谁

    (4) 在call/apply中,this可以被指定,被指定为第一参数

    (5) 在new的构造函数中,this被指向正在创建的对象

41. 对象

42. (自定义)对象的创建

 43. 对象的属性

44. 对象的使用(调用对象属性或方法)

 45. 对象的遍历

46. Math 对象

  (1)常数

  (2)方法

47. Date日期对象(是一个构造函数,必须new)

   (1) 如何获取当前时间

    (2) 数:1970年1月1日到现在的毫秒数(时间戳,永远不会重复,一直在增加)

    (3) setFullYear()//月份设定特殊,从0-11

    (4) 有参数的构造函数

    (5) UTC(协调世界时间)和GMT (格林尼治时间)

    (6) 设定年setFullYear和getFullYear 

    (7) 设定月(0-11)

    (8) 设定日

    (9) 设定星期几(0:星期日,1-6:周一到周六)

    (10) Date克隆

48. 定时器:也称回调函数callback

49. Arry数组对象

      (1) 检测是否为数组

      (2) 添加数组元素

      (3) 删除数组元素

       (4) 数组排序

       (5) 数组索引

       (6) 数组去重

       (7) 数组转换为字符串

50. 字符串对象

   (1)基本包装类型

    (2) 字符串的不可变

    (3)根据字符返回位置

51. 包装类

52. 数据结构(堆和栈)

53. 特殊字符

54. 编码与解码

55.  json

46. 正则表达式

     (1)正则表达式类 RegExp(exp,param)

    (2)直接量(通过字面量创建)(用两个撇斜杠,/expression/param)

57. 正则表达式详解

    (1)简单类

    (2)范围类

    (3)负向类

    (4)量词一个前面单位出现的次数

58. String支持的正则函数

59. Web API

60. DOM

            (1) console.dir(); 打印返回的元素,更好的查看里面的属性和方法

            (2) 根据ID名获取element元素

            (3)根据class类名获取element元素(h5新增,IE9以下不支持)

            (4)根据标签名TagName获取element元素

            (5)根据标签名Name获取element元素

             (8)获取特殊元素

61. DOM 增删替 (操作元素)

            (1)增加:

             (2)删除:

              (3)替换:

62. 操作Element元素的属性

   (1)修改图片元素属性

    (2)修改表单元素属性

    (3)修改样式属性:Element.style(产生的是行内样式,权重较高,属性采取驼峰命名法)

    (4)修改Element元素名

    (5)排他思想:tab标签切换,点击谁谁的样式改变,且始终只有一个元素样式改变了

     (6)获取元素属性值

      (7)设置元素属性值

     (8)移除属性 Element.removeAttribute('index');

63. 操作Node节点

64. 弹窗

65. HTML DOM 事件

        (1)鼠标事件

        (2)键盘事件

          (3)框架/对象(Frame/Object)事件

        (4)表单事件

        (5)剪贴板事件

        (6)打印事件

        (7)拖动事件

        (8)多媒体(Media)事件       

        (9)动画事件

         (10)过渡事件

         (11)其他事件

        (12)触屏事件(移动端事件)

 66. 事件绑定(注册事件)

      (1) ontype

     (2)addEventListener()

      (3)attachEvent()

 67. 事件解绑定

    (1)直接删除法:适用于行内直接绑定的事件

    (2)传统解除法

    (3)先有绑定函数,再次解除法

    (4)d.attachEvent('onclick',fn1);

68. DOM时间流

69. 事件对象

    (1)事件冒泡:

    (2)事件捕获:

    (3)触发顺序:

     (4)取消事件冒泡:

    (5)阻止默认事件:

    (6)事件源对象:

70. 事件委托

71. js执行机制

72. BOM浏览器对象模型

         (1)窗口加载事件:

       (2)调整窗口大小事件

73. 窗口操作

74. offset、client、scroll

75. 节流阀

76. 本地存储

    (1)window.sessionStorage

     (2)window.localStorage

77. javascript面向对象编程

78. 直接把字符串格式元素添加到父元素中

79 .利用构造函数创建对象

 78.  原型(对象)

79. 原型链

80. ES5中的新增方法

   (1)数组方法 : forEach(), map(), filter(), some(), every(); 

   (2)字符串方法

   (3)对象方法

81. 函数的定义和调用方式

  (1)函数的定义:

  (2)函数的调用方式与this指向:

  (3)this

82. 严格模式

83. 高阶函数

84. 浅拷贝和深拷贝

 85.ES6新增语法

86. 结构赋值

87. 箭头函数:ES6中新增的定义函数的方式

  (1)  () => {} 

  (2)若函数体中只有一句代码,且代码执行结果就是返回值,可以省略大括号

 (3)在箭头函数中,如果形参只有一个,形参外侧的小括号也可以省略

  (4)箭头函数不绑定this关键字,箭头函数中的this,指向的是函数定义位置的上下文this

88. 剩余参数

89. 剩余参数和解构配合使用

90. ES6内置对象扩展

   (1)Array的扩展方法

    (2) 构造函数方法:Array.from()

    (3)String的扩展方法

91. Set数据结构

    (1)Set可以用来进行数组去重

    (2)Set实例方法:

    (3)遍历Set数据结构,从中取值

92. 防抖节流

93. promise

94. s垃圾回收机制

95. EventLoop


一、概念

   1.  一门客户端脚本语言

    * 运行在客户端浏览器中的。每一个浏览器都有JavaScript的解析引擎
    * 脚本语言:不需要编译,直接就可以被浏览器解析执行了

2. 功能:

    * 可以来增强用户和html页面的交互过程,可以来控制html元素,让页面有一些动态的效果,增强用户的体验。

3. JavaScript发展史:

    1992年,Nombase公司,开发出第一门客户端脚本语言,专门用于表单的校验。命名为 : C--    ,后来更名为:ScriptEase
    1995年,Netscape(网景)公司,开发了一门客户端脚本语言:LiveScript。后来,请来SUN公司的专家,修改LiveScript,命名为JavaScript
    1996年,微软抄袭JavaScript开发出JScript语言
    1997年,ECMA(欧洲计算机制造商协会),制定出客户端脚本语言的标准:ECMAScript,就是统一了所有客户端脚本语言的编码方式。

4. JavaScript = ECMAScript + JavaScript自己特有的东西(BOM+DOM)

       DOM 页面文档对象模型(标准编程接口,通过DOM提供的接口对页面上的各种元素进行大小/位置/颜色等操作)
       BOM浏览器对象模型(与浏览器互动的对象结构,通过BOM可以操作浏览器窗口,比如弹出框/控制浏览器跳转/获取分辨率等)

* ECMAScript:客户端脚本语言的标准

二、JavaScript的三种引入方式

1. 行内式js

       (1)可以将js代码填写到body下标签的onclick属性中(当我们点击按钮时,js代码才会执行,每点一次执行一次) 虽然可以写在标签的属性中,但是他们属于结构与行为耦合,不方便维护,不推荐使用 


        


      (2)可以将js代码填写到超链接a标签的href属性中(当我们点击超链接时,js代码才会执行,每点一次执行一次)

   
        
            点我一下
            
    

2. 内嵌式的js

         javascript(js代码需写到script标签中)js语言从上往下执行指令

   

3. 外部js

     可以将js代码编写到外部js文件中(外部js文件中不出现script标签),然后通过script标签引入(可以在不同的页面中同时引用,也可以利用到浏览器的缓存机制,推荐使用)(script标签一旦引入外部文件了,就不能再填写内部代码了,写了浏览器也会忽略 ,如果需要,可以再创建一个新的script标签用于编写内部代码)

 
        
 

三、JavaScript的使用

1. 基本语法

(1)注释

      (注释中的内容不会被执行,但是可以在源代码中查看,养成良好的注释习惯,可以通过注释对代码进行一些简单的调试)

     a. 多行注释

/*
*/

    b. 单行注释

//

(2)js中严格区分大小写

Alert('错误不能执行') //错误示范

(3)js中每一条语句以分号结尾(如果不写,浏览器会自动添加,但是会消耗一些系统资源,而且可能会加错分号,所以开发中必须写分号)

(4)js中会忽略多个空格和换行,所以可以利用空格和换行对代码进行格式美化

2. 字面量

   (都是一些不可改变的值,比如:1、2、3、4),自面量都是可以直接使用,但是一般不会直接使用字面量,可用变量保存字面量,方便调用

3. 变量

     变量是程序在内存中申请一块用来存放数据的空间, (比如:X=3.14159)变量可以用来保存字面量,而且变量的值是可以改变的,变量更加方便使用,所以开发中都是通过变量去保存一个字面量,很少直接使用字面量

4. 声明变量(比如:设x=2)

          (1)在js中使用var关键字来声明一个变量

      var a //声明一个变量a
          a=13  //给a赋值
      console.log(a);//在控制台输出a的值
          
          var b=25 //简写 声明和复制同时进行
          console.log(b);


          (2)通过变量对字面量进行描述
    

          var age=21 
          console.log(age);


          
          (3), 逗号 可以分割多个语句,一般可以声明多个变量时使用
        

          var age=21,
              b=12;
          console.log(age);


          (4)更新变量:一个变量被重新赋值后,它原有的值就会被覆盖,变量值将以最后一次赋的值为准

          (5)声明变量的特殊情况

         只声  明不赋值,结果是undefined
         不声明不赋值,直接使用会报错
         不声明直接赋值使用,是全局变量(可以使用,但不提倡)

          (6)两个变量交换:需要一个临时变量

          (理解思路:左手是苹果,右手是橘子,首先把左手的苹果放到桌子上,此时左手为空,再把右手的橘子交到左手上,空着的右手再拿上桌子上的橘子,这样就实现了位置交换,左手拿橘子右手拿苹果了)  

          var a = '苹果',
              b = '橘子';
           var temp;/*声明一个临时变量*/
              temp = a ;/*temp = '苹果'*/
              a = b;/*a = '橘子'*/
              b = temp;/*b = '苹果'*/

               变量值互换的两种方法

         var inum1=123 ,inum2=456;

     (1)var inum3 = inum2 ;
          inum1 = inum3;
          inum2 = inum1;

     (2)inum1+=inum2;(inum1=123+456)
         inum2 = inum1-inum2;
         inum1 = inum1-inum2;

5. 标识符

(在js中所有的可以由我们自主命名的都可以称为是标识符)(例如:变量名、函数名、属性名都属于标识符)

          命名一个标识符时需要遵守如下规则:

          (1) 标识符中可以含有字母、数字、下划线、$(一般使用描述性的名称,比如:age,sum),变量名称对大小写敏感   

var b_$=25

          (2)标识符不能以数字开头

          (3)标识符不能js中的关键字或保留字

      var var=123  //错误写法
          var if=123  //错误写法

          (4)标识符一般都采用驼峰式命名法(首字母小写,后面单词的首字母大写,其余字母小写)

 helloWorld

          (5)js底层保存标识符时实际上是采用的Unicode编码,所以理论上讲,所有的utf-8中含有的内容都可以作为标识符(也包含中文)

          var 体重=21  //中文也可做标识符,但不提倡用
          console.log(体重);

6. 数据类型

    在计算机中,不同的数据所需占用的空间不同,为了把数据分成所需内存大小的不同数据,充分·=利用存储口空间,于是定义了不同数据类型(js的变量数据类型只有在程序运行时,根据等号右边赋的值确定,变量的数据类型是可变的)

    (1)值/原始(简单数据)类型:

             number(数字)、string(字符串)、boolean(布尔值)、undefined、null

                    a. number:数字。 整数/小数/NaN(not a number 一个不是数字的数字类型)
                    b. string:字符串。 字符串  "abc" "a" 'abc'
                    c. boolean: true和false
                    d. null:一个对象为空的占位符
                    e. undefined:未定义。如果一个变量没有给初始化值,则会被默认赋值为undefined

        ***简单数据类型返回的都是它本身,但null返回的是一个空的object对象
        ***如果有个变量打算存储为对象,但暂时还没有确定的属性和方法,这个时候就可以把这个变量赋值为null

  (2)引用(复杂数据)类型:

                  通过new关键字创建的对象,array、object对象、Date,function
 

         typeof 返回数据类型

     var x = 1;
     console.log(typeof(x) + '
');//number      var x = "abc";      console.log(typeof(x) + '
');//string      var x = true;      console.log(typeof(x) + '
');//boolean      var x = null;      console.log(typeof(x) + '
');//object      var x = undefined;      console.log(typeof(x) + '
');//undefined      var x2;      console.log(typeof(x) + '
');//undefined

7. 数据类型转换

       (1)隐式类型转换

   a.  转换成数字number

       var sNum = '2';
       var iNum = 2;
    
       var iRet = sNum + iNum;
    console.log('数据类型为'+ typeof(iRet) + '
');//string 22       var iRet = sNum - iNum;     console.log('数据类型为'+ typeof(iRet) + '
');//number 0


b. 转换成数字string

    var Stoken = ' ' + 2;
    console.log('数据类型为'+ typeof(Stoken) + '
');//string           var Stoken = ' ' + null;     console.log('数据类型为'+ typeof(Stoken) + '
');//string           var Stoken = ' ' + undefined;     console.log('数据类型为'+ typeof(Stoken) + '
');//string           var Stoken = ' ' + true;     console.log('数据类型为'+ typeof(Stoken) + '
');//string 


 c.9转换成数字string(临界点0和非0的区别)

    var bvar = !0;
    console.log(typeof(bvar) + '
')//bolean true          var bvar = !1;     console.log(typeof(bvar) + '
')//bolean false          var bvar = !1000;     console.log(typeof(bvar) + '
')//bolean false          var bvar = !!1000;     console.log(typeof(bvar) + '
')//bolean true

       (2)显式类型转换

  Number();  数据类型转化为number数字
  
  parseInt();  数据类型转化为number数字取整或截取number数字
   
 parseFloat();  与parseInt类似,但支持小数点和科学计数法 
    
 (isNaN();  判断是不是一个数--调用Number();函数)/*NAN:不是一个数字*/
   
  String(变量);  数据类型转化为string字符串
   
  变量.toString();  数据类型转化为string字符串(可以转进制数)
   
 Boolean();  数据类型转化为boolean布尔值

8. number(数字)

      整数和浮点数(NAN是一种特殊的number)   

       inumber=Number.MAX_VALUE 最大值
       inumber=Number.MIN_VALUE 最小值
       inumber=Number.MAX_INFNITY 无限大
       
      document.write('isFinite(inumber)=' + isFinite(inumber)+'
') 判断inumber是否是无限大(finity有限/infinity无限)(所有的INFNITY都是一样的不能用来比较)        document.write('isNaN(inumber)=' + isNaN(inumber)+'
') 判断inumber是否是NaN(NaN:not a number)(NaN==NaN=false NaN!=NaN=true)

在js中,各进制表示法

           (1)如果需要表示16进制的数字,则需要以0x开头(转换成10进制输出)

 a=0x10;//a=16

           (2)如果需要表示8进制的数字,则需要以0开头(转换成10进制输出)(有些浏览器会当成10进制数解析)

        b=070; //b=56
        b=parseint(a,8);可以在parseInt()中传递一个第二个参数来指定数字的进制(所有浏览器适用)(parseInt(score/10) 结果取整)

           (3)如果需要表示2进制的数字,则需要以0b开头(转换成10进制输出)(并不是所有浏览器都支持)

  c=0b10;//c=2

            (4)浮点数

    fnumber=5.61e7;//fnumber=56100000(科学计数法:e7表示*10^7)
31.01.+02为什么不等于0.3

因为浮点数运算的精度问题。

在计算机运行过程中,需要将数据转化成二进制,然后再进行计算。

小数转化为IEEE754的过程:先转化为二进制的形式,然后再用科学计数法表示,
接着把通过科学计数法表示的二进制数用IEEE754标准表示。

js中的Number类型遵循IEEE754标准,在IEEE754标准的64位浮点数相加,
因为浮点数自身小数位数的限制而截断的二进制在转化为十进制,
就变成0.30000000000000004,所以在计算时会产生误差。

9. 将其他数据类型转化为number数字

(1)Number本质上可以转换成数字

(2)ParseInt看上去像数字的可以转换成数字

(3)Number可以,但parseInt不可以的:false、null

(4)Number不可以,但parseInt可以的:数字开头掺杂其他

(5)都不可以的:undefined、字母开头的字符串

(6)Number()(false、null、' '转化后数值为0/undefined、不是数 转化后数值为Nan)

    var iNum = Number(undefined);
    console.log(typeof(iNum) + '
')//number Nan          var iNum = Number(null);     console.log(typeof(iNum) + '
')//number 0          var iNum = Number('10');     console.log(typeof(iNum) + '
')//number 10          var iNum = Number('1.5');     console.log(typeof(iNum) + '
')//number 1.5          var iNum = Number('1.5.3');     console.log(typeof(iNum) + '
')//number Nan          var iNum = Number(' ');     console.log(typeof(iNum) + '
')//number 0   parseInt()(不是数 转化后数值为Nan)     var iNum = parseInt('1.12');      console.log(typeof(iNum) + '
')//number 1     console.log(iNum.toFixed(1) + '
')// 1.1 保留一位小数          var iNum = parseInt('2.5.6');     console.log(typeof(iNum) + '
')//number 2          var iNum = parseInt('123a');     console.log(typeof(iNum) + '
')//number 123           var iNum = parseInt('a123');     console.log(typeof(iNum) + '
')//number Nan           var iNum = parseInt('0xA0');//0x代表16进制数     console.log(typeof(iNum) + '
')//number 160            var iNum = parseInt('070');//0代表8进制数,但在此无效      console.log(typeof(iNum) + '
')//number 70             var iNum = parseInt(' ');      console.log(typeof(iNum) + '
')//number 0            var iNum = parseInt('1.1E5');//科学计数法,但在此无效      console.log(typeof(iNum) + '
')//number 1             var iNum = parseInt('A0',16);//16进制数      console.log(typeof(iNum) + '
')//number 160             var iNum = parseInt('70',8);//8进制数      console.log(typeof(iNum) + '
')//number 56 parseFloat();与parseInt类似,但支持小数点和科学计数法       var iNum = parseFloat('1.1E5');//科学计数法(浮点数)      console.log(typeof(iNum) + '
')//number 110000             var iNum = parseFloat('10');//科学计数法(浮点数)      console.log(typeof(iNum) + '
')//number 10             var iNum = parseFloat('10.00');//科学计数法(浮点数)      console.log(typeof(iNum) + '
')//number 10             var iNum = parseFloat('10.5');//科学计数法(浮点数)      console.log(typeof(iNum) + '
')//number 10.5              var iNum = parseFloat('1.5.3');//科学计数法(浮点数)       console.log(typeof(iNum) + '
')//number 1.5              var iNum = parseFloat('1.7 ');//科学计数法(浮点数)       console.log(typeof(iNum) + '
')//number 1.7              var iNum = parseFloat('1.5aaa');//科学计数法(浮点数)       console.log(typeof(iNum) + '
')//number 1.5 


    隐式转换:

      console.log('12'-0)//12
      console.log('12'-'10')//2
      console.log('12'*1)//12
      console.log('12'/6)//2

10. string(字符串)

      (1)用英文引号(js推荐使用单引号,引号嵌套:外单内双)

    sTocken = 'hello world!'
    var length = sTocken.length;检测获取字符串的长度//length=11


     (2)字符串拼接(数值相加,字符相连):       

              console.log('沙漠'+'骆驼');/*沙漠骆驼*/
              console.log('沙漠'+'33');/*沙漠33*/
              console.log('沙漠'+'true');/*沙漠true*/
              console.log('33'+'33');/*3333*/

     (3)常用方法

    var ilength = sTocken.indexOf(o);查询o是第几个字符//ilength=4

    document.write('chartAt='+sTocken.charAt(ilength)+'
');提取出o//chartAt=o     document.write('substring='+sTocken.substring(0,ilength+1)+'
'); 截取到0的一段字符串//substring=hello     sTocken2 = 'abcd abce a234 1314 scfdva'         var iStart = sTocken2.indexOf(' '), iEND if(iStart!=-1){//查询第一个空格         iEND = sTocken2.indexOf(' ',iStart+1);         if (iEND!=-1){//查询第er个空格         document.write('substring = ['+sTocken2.substring(start+1,iEND)+']
');             }     }截取第二个单词

 (4)在字符串中使用转义字符输出unicode编码(有些浏览器不支持)

   a.  js中:\u四位编码

 console.log("\u2620")


   b. html中:&#四位编码

   

(需把16进制转换为10进制)

11. 将其他数据类型转化为string字符串

    String();        

    var Stoken = String(2);
    console.log(+ typeof(Stoken)+'
')//string          var Stoken = String(null);     console.log(+ typeof(Stoken)+'
')//string          var Stoken = String(undefined);     console.log(+ typeof(Stoken)+'
')//string          var Stoken = String(true);     console.log(+ typeof(Stoken)+'
')//string


    toString();

    var inumb1 = 80;
    Stoken = inumb1.toString();
    console.log(+ typeof(Stoken)+'
')//string 80          var inumb1 = 80;     Stoken = inumb1.toString(16);十转成16进制数     console.log(+ typeof(Stoken)+'
')//string 50          var inumb1 = 80;     Stoken = 80.toString();不可以,出错     console.log(+ typeof(Stoken)+'
')//string 80          Stoken = true.toString();     console.log(+ typeof(Stoken)+'
')//string true          Stoken = null.toString();不可以,出错     console.log(+ typeof(Stoken)+'
')//string           Stoken =undefined.toString();不可以,出错     console.log(+ typeof(Stoken)+'
')//string 80


例题:将一个二进制字符串转化成16进制字符串

    var sString = '10101001'
    var nNum = parseInt(sString,2);
    if(!isNaN(nNum)){
        console.log(nNum.toString(16));
    }

12. Boolean 布尔值

  (1)(布尔值只有两个),主要用来做逻辑判断    

      true //表示真
      false //表示假

 (2)   使用typeof(检查数据类型)检查一个布尔值时,会返回一个boolean

    var bool = true/false
    console.log(typeof bool);返回boolean
    console.log(bool);输出值


(3)布尔值true和false参与加法运算时,true当数字型1来看,false当数字型0来看

    console.log(true + 1);//2
    console.log(false + 1);//1

13. 将其他数据类型转化为Boolean

使用Boolean()函数  

                      (初值为空值,否定值会被转换为false,如:'' 0 NaN null undefined,其他都转换为true)

    (1)数字转Boolean,除了0和NaN是false,其他都是true
    (2)字符串转Boolean,除了空串和是false,其他都是true
    (3) null和undefined转Boolean都会转换为false
    (4) 对象也会转换为true

    var a=123;
        a=Boolean(a); 
        
        console.log(typeof a);
        console.log(a);

14. undefined 未定义

     (1)undefined类型的值就一个,就undefined,当声明一个变量,但是并不给变量赋值时,他的值就是Undefind

    (2)使用typeof检查一个undefind时,会返回一个undefined

       var b=undefined;

       undefined==undefined=true

       undefined==null=true


15. null

(1)null类型的值就一个,这个值专门用来表示一个空的对象,使用typeof检查一个null值时,不会返回一个null,会返回object

     var a=null;
    (null==null=true/undefined==null=true)

(2)任何数据类型和字符串相加,结果都是字符串相连(字符型)

    a.  NaN undefined和数字相加,最后结果是NaN
    b.   null和数字相加,结果是原数字

16. 运算符

    (1)  算数运算符

              + - * / %(取余:取余为0则证明这个是能被整除)
              (浮点数运算时精度有问题,尽量避免浮点数直接运算和比较)

    var = sToken = 5 + 5//=10
    var = sToken = "5" + 5//=55
    var = sToken = "5" - 5//=Nan
    var = sToken = 5 - 5//=0
    var = sToken = "5" - "5"//=0
    var = sToken = 4 / 3//=1.3333333
    var = sToken = 4 / 0//=infinity
    var = sToken = 0 / 0//=Nan
    var = sToken = 4.5 % 3//=1.5
    var = sToken = 4 % 0//=Nan
    var = sToken = 0 % 0//=Nan 

      运算符的优先级:先乘除后加减
                 从上往下优先级依次降低(优先级越高越优先运算,优先级相同则从左往右运算)
                 如果优先级不确定 可以用()改变其优先级
        (注:除===和!===判断内容是:不仅判断数值,而且判断类型,其他关系运算符都只判断数值)

      . 【】 new
      . ()                                    //小括号
      . ++ -- !                                //一元运算符
      . ! +(单目) -(单目) typeof void delete
      . %                                     //算数运算符,先乘除
      . +(双目) -(双目)                       //算数运算符,后加减
                 . << >> >>>
      . < <= > >=                           //关系运算符
      . ==(判等于) !==(非全等于) ===(全等于) //相等运算符
                 . &
                 . ^
      . &&//逻辑运算符,先与
      . ||//逻辑运算符,后或
      . = += -= *= /= %= <<= >>= >>>= &= ^= |=     //赋值运算符
      . ,(多个逗号表达式,只以最后一个表达式作为自己的表达式,前面的都抛掉) //逗号运算符

     
(2)  一元运算符

    只需要一个操作数(数值取反)
        +   //正号-不影响值,可以对其他的数据类型使用+,将其转化为number,他的原理和number函数一样
        -   //负号-值为负,对于非number类型的值,先转化为number,然后再运算

(3)  逻辑运算符    

    && || !(与或非运算)

    与运算:遇假为假,两真则真
    或运算:遇真为真,两假则假
    非运算:非真为假,非假为真
    短路运算(逻辑中断):当有多个表达式(值),左边的表达式值可以确定结果时,就不再运算右边的表达式的值;

a.   与运算

      如果第一个值为true,则必然返回第二个值,如果第一个值为false,则直接返回第一个值
      如果两个值都为true,则返回后面的
      如果有false,则返回false的原值
      如果两个值都为false,则返回前面的

b.  或运算

      如果第一个值为true,则必然返回第一个值,如果第一个值为false,则直接返回第二个值

c.  非运算(布尔值取反

d.  &&   || ( 短路运算)  非布尔值的情况
             对于非布尔值进行与或运算时,会将其转换为布尔值,然后再运算,并且返回原值

              与运算:

                    如果第一个值为true,则必然返回第二个值,如果第一个值为false,则直接返回第一个值
                    如果两个值都为true,则返回后面的
                    如果有false,则返回false的原值
                    如果两个值都为false,则返回前面的

            或运算:

                   如果第一个值为true,则必然返回第一个值

                  如果第一个值为false,则直接返回第二个值

(4) 赋值运算符   

             = 可以将符号右侧的值赋值给符号左侧的变量
            +=(a+=5等价于a=a+5)
            -=(a-=5等价于a=a-5)
            *=(a*=5等价于a=a*5)
            /=(a/=5等价于a=a/5)取模 
            %=(a%=5等价于a=a%5)

            a=5
    后置递增    a++(a++=5 a=6)先运算后赋值(先返回原值后自加1)
    前置递增    ++a(++a=6 a=6)先赋值后运算(先自加1后返回值)

(5)比较运算符

          > < >= <= == != === !==

        ***注意   =: 赋值,把右边给左边
                    ==: 判断,判断两边值是否相等(有隐式转换,会把字符型转换为数值型)
                  ===: 全等,判断两边的值和数据类型是否完全相同
 

      数字比较

  document.write('[>]2>1?'+ (2>1)+'
');//true  document.write('[>]1>2?'+ (1>2)+'
');//false

        字符串比较(从左往右一个字符一个字符的比较)

 document.write('[>] \'aaa\'>\'abb\'?'+ ('aaa'>'abb')+'
');//false document.write('[>] \'aba\'>\'Abb\'?'+ ('aaa'>'abb')+'
');//true

        数字字符串和数字比较(将数字字符串直接变成数字进行比较)
          

  document.write('[>] \'25\'>4?'+ ('25'>'4')+'
');//true 5==NaN=false false==0=true(===为false) true==1=true(===为false) true==2=false undefined==0=false null==0=false "5"==5=true "5"===5=false null===undefined=false

(6)条件运算符(也叫三元运算符)

     语法:
             条件表达式?语句1:语句2

    执行流程:
           条件运算符在执行时,首先对条件表达式进行求值,
           如果该值为true,则执行语句1,并返回执行结果
           如果该值为false,则执行语句2,并返回执行结果
           如果条件的表达式的求值结果是一个非布尔值,会将其转换为布尔值,然后再运算,并执行语句  

           var a=10,b=20;//a与b谁大
           a>b ?alert("a大"):alert("b大")
           
           var max= a>b ?a:b //a与b中取最大
           console.log("max="+max)\
           
           var max= a>b ?a>c?a:c:b>c?b:c; //a、b、c中取最大
           console.log("max="+max)

17. 语句

      (1)我们的程序是由一条一条语句构成的,语句是按照自上而下一条一条执行的
      (2)在js中,可以使用大括号{}来为语句进行分组,同一个{}中的语句我们称为是一组语句(一个代码块),要么都执行,要么都不执行
      (3)js中的代码块,只具有分组的作用,没有其他的用途,代码块中的内容,在外部是完全可见的

18. if else 语句

     适用于分支较少范围判断的时候

    if(判断条件){
        条件满足执行语句1
    }
        else{
            不满足条件则执行语句2
        }
        
    例子 var iscore = 78 (90-100优/75-90良/60-75中/0-60差)

        (1)最不好(if)//单条件单分支

        if(iscore>=90 && iscore<=100){document.write('iscore=优')}
        if(iscore>=75 && iscore<90){document.write('iscore=良')}
        if(iscore>=60 && iscore<75){document.write('iscore=中')}
        if(iscore>=0 && iscore<60){document.write('iscore=差')}

        (2)不好(if...else)/*单条件双分支 */

  if(iscore>=90){
            document.write('iscore=优')
            }
            else{
                if(iscore>=75){
                    document.write('iscore=良')
                    }
                    else{
                        if(iscore>=60){
                            document.write('iscore=中')
                            }
                            else{
                                document.write('iscore=差')
                            }
                    }
            }

        (3)最优(if...else if ... else)/*多条件多分支*/  

    if(iscore>=90){
            document.write('iscore=优')
            }
            else if(iscore>=75){
                    document.write('iscore=良')
                    }
            else if(iscore>=60){
                    document.write('iscore=中')
                            }
            else{
                    document.write('iscore=差')
                            }

19. swith语句

     单条件多分支,利用表达式的值和case后面的选项值相匹配(全等,值和数据类型都匹配),匹配上就执行case里面的语句,没有匹配上则执行default里面的语句*/ (适用于case为比较确定的值时,分支较多时switch效率更高)

       switch(变量或表达式){
              case 1(变量取值为常量1时):满足条件执行语句1;
                 break;(必须break,不然会一直往下执行,会出错)
              case 2(变量取值为常量2时):满足条件执行语句2;
                break;
              case 3(变量取值为常量3时):满足条件执行语句3;
              default(变量最后一种取值情况或容错):满足条件执行语句last;
                  break;
 

      var score=86;
      switch(true){
        case score>=60;
        console.log("合格")
         break;
            default:
            console.log("不合格")
            break;
         }
         var day = 6;
         switch(day){
            case 0:x = '星期天';
                 break;(必须break,不然会一直往下执行,会出错)
            case 1:x = '星期一';
                break;
            case 2:x = '星期一';
                break;
            case 3:x = '星期二';
                break;
            case 4:x = '星期三';
                break;
            case 5:x = '星期四';
                break;
            case 6:x = '星期五';
                break;
            default:x = 'error';
                break;
            }
        document.write('今天是'+ x + '
')

20. 循环

     重复执行某些代码

   (1) for 循环语句

             满足条件进入循环运行一次,直到条件不满足跳出循环,通常和计数有关系

     for(初始变量; 条件表达式; 操作表达式){
         循环体
    }

        初始变量:var声明的一个普通变量,通常用于作为计数器使用,
        条件表达式:决定循环是否继续执行,即终止的条件,
        操作表达式:每次循环最后执行的代码,经常用于对计数器变量进行更新(递增或递减)

  for(var i = 0; i < 20; i++){
         console.log('哈喽');/*循环执行相同的代码*/
         document.write(i + '
');/*循环执行不同的代码*/     }  等价于   var i = 0     for(i < 20; ){         console.log('哈喽');          document.write(i + '
');          i++;     }

for循环算数运算

    var sum = 0;
    for(var i = 1; i <=100; i++){
        sum+=i;
    }

 
    求1-100之间所有偶数的和和奇数的和

    var even = 0,
        odd = 0;
    for(var i = 1; i <= 100; i ++){
        if(i % 2 == 0){
            even = even + i;
        }else{
            odd = odd + i;
        }
    }

    console.log('1-100之间偶数和是'+even);
    console.log('1-100之间奇数数和是'+odd);


    双重for循环

             循环嵌套是指在一个循环语句中再定义一个循环语句的语法结构(可以把里面的循环看成是外面循环的语句,外层循环一次,里面的循环执行全部)

        for(外层的初始化变量;外层的条件表达式;外层的操作表达式){
            for(里层的初始化变量;里层的条件表达式;里层的操作表达式){
                执行语句;
            }
        }

  for(var i = 1;i <= 3;i ++){
            console.log('这是外层循环第'+ i +'次');
            for(var j = 1;j <= 3;j ++){
                console.log('这是里层循环第'+ j +'次');
            }
        }


    打印5行5列星星

       var str = '';
       for(var i = 1;i <= 5;i ++){ /*外层循环负责打印5行*/
           for(var j = 1;j <= 5;j ++){ /*内层循环负责一行打印5个*/
               str = str + '*'; /*内层语句循环5次,每次+1个*/
           }
        str = str + \n; /*外层循环换行5次*/
       }
       console.log(str);

  
    打印10行倒三角

       var str = '';
       for(var i = 1;i <= 10;i ++){ /*外层循环负责打印10行*/
          for(var j = i;j <= 10;j ++){ /*内层循环负责一行打印10-i+1个*/
               str = str + '*'; /*内层语句循环10次,每次+1个*/
           }
        str = str + \n; /*外层循环换行10次*/
       }
       console.log(str);

 
    九九乘法表(正三角)

       var result = '';
           for(var i = 1;i <= 9;i ++){ /*外层循环负责打印9行*/
         for(var j = 1;j <= i;j ++){ /*内层循环负责一行打印i个*/
            result += j + 'x' + i + '=' + i * j + '\t'; /*内层语句循环i次,每次+1个*/
               }
            result = result + '\n'; /*外层循环换行9次*/
           }
           console.log(result);

 (2)while 循环语句

         满足条件进入循环运行一次,直到条件不满足跳出循环,适用于判断条件比较复杂时使用

          while (i<20){
            document.write(i + '
'); 
            i++;
          }
          
    输入内容不符时循环

       var message = prompt('你是爱坤吗?');
        while (message != '是'){
            alert('再给你一次重新组织语言的机会!');
            message = prompt('你是爱坤吗?');
        }
        alert('姬霓太美!!!')

(3)do while 循环语句

          先执行一次循环体后再判断是否满足条件,满足条件则继续进入循环,直到条件不满足跳出循环(do while至少循环一次,执行更自然)
 

  var i=0;
    do{
        document.write(i + '
');         i++;     }     while(i<20);

21. 循环语句中的 break 、continue

      (1)continue

                只跳出当前循环(立即跳出本次循环,其后的语句本次不再执行,继续开始下一次循环。)(计划吃5个包子,吃到第3个发现上面有虫子,那么扔掉第三个包子,接着吃第4个和第5个)

  求1-100之间,除了能被7整除之外的整数和 

var sum = 0;
      for(var i = 1; i<=100; i++){
          if(i % 7 == 0){
              continu;
          }
          sum+=i;
      }
      console.log(sum);

      (2)break

              直接跳出循环(立即结束整个循环并转到循环后续语句执行)(计划吃5个包子,吃到第3个发现上面有虫子,那么第3个和剩下的包子都扔了)

   while (i<20){
            if(i == 10){
            break;
            }
                document.write(i + '
');                  i++;     }


    (3)案例

    a. 找出5000以内满足%7==5、%13==7、%17==13的前5个数

    var count=0
    for(i=1,i<=5000,i++){
    if (i % 7 == 5 && i % 13 == 7 && i % 17 == 13){
        document.write('5000以内' + i '
')         count++;         if (count >=5){             break;         }     } }


    b. 10的阶乘

    var iRet = 1 , n = 10 ;
    for(var i = n , i>=1 , i--){
        if (!isFinite(iRet)){
        document.write('无限大');
            break;
        }
        iRcet *= i;
    }
    document.write('10的阶乘=' + iRcet + '
');


      c. 1累加到100

    var n = 100 , iret = 0;
    var iRet = 1 , n = 10 ;
    for(var i = 1 , i<=n , i++){
        if (!isFinite(iRet)){
        document.write('无限大');
            break;
        }
        iRcet += i;
    }
    document.write('1累加到100=' + iRcet + '
');  


      d. 5的n次幂

    var n = 10 ,iret = 1,inumb = 5;
    for(var i = 0 , i<=n , i++){
        if (!isFinite(iRet)){
        document.write('无限大');
            break;
        }
        iRcet *= inumb;
    }
    document.write('1累加到100=' + iRcet + '
');

22. 数组(Arry:js的数组是弱类型)

       数组是一组数据的集合,其中每个元素被称为元素,在数组中可以存放任意类型的元素,数组是一种将一组数据存储在单个变量名下的优雅方式

如何判断一个变量是数组:
     var arr = [];
     console.log(arr.constructor.name == 'Array');

 (1)创建数组:    

    a.使用构造函数方式生成数组:

        arr = new Array();//等价于arr = [];
        arr1 = new Array(0,1,2,3);//等价于arr1 = [0,1,2,3];
       *arr2 = new Array(4);//等价于arr2 = [,,,];

    
    b.使用数组字面量创建数组:(最常见)

    var 数组名 = [数组元素];

       var arr = [];空数组
       var arr1 = [0,1,2,3];
       var arr2 = [0,1,,3];
       var arr3 = [,,,];
       var arr1 = [0,accc,undefined,null,true,{}];

   
     稀疏数组/矩阵:插入空的empty length不消耗内存,调用时再取用)

    larr[3] = 5;// [,,,5]
    larr[1.5] = 7;// 1.5:7


      可以把数组当map用

                                       key = value(map不影响length)

    var a4 = [];
    a4['China'] = '满汉全席';
    a4['American'] = '火机';
    a4['France'] = '牛排';
    console.log(a4);


  (2)  访问数组(数组的索引)

      索引号从0开始计数,通过"数组名[索引号]"的形式获取数组中的元素(若没有这个元素,则返回undefined)

    console.log(arr1[1]);
    console.log(arr4[3]);
    console.log(arr[1]);


  (3)插入数组(新增元素):根据数组名和索引号添加(不要直接给数组名赋值,不然所有数组元素都没有了)

    a.修改length长度

    var arr1 = [0,1,2,3]; // length = 3
    arr1.length = 5; 
    console.log(arr1); //[0,1,2,3,emptyx2]
    console.log(arr1[4]); //undefined


    b.修改索引号:如果一个下标位置原来不存在,会添加,还会增加length(数组有长度length),如果下标存在,则新值会覆盖原值

    var arr2 = [0,1,2,3];
        arr[3] = 5;(第4个位置插入5)
    则  arr3 = [0,1,2,5];
        arr[4] = 6;(第5个位置插入6)
    则  arr3 = [0,1,2,5,6];


    例题:将数组[2,6,4,9,1,7,45,35,19,24,12]中大于10的元素选出来放到一个新数组中

var arr = [2,6,4,9,1,7,45,35,19,24,12];
var newArr = [];新数组length为0
                       (var j = 0;)
 for (var i = 0; i <= 10; i++) {
     f(arr[i] > 10){
       newArry[newArry.length] = arr[i]; 或 (newArry[j] = arr[i]; j++;) 
                                                //新数组索引号应该从0开始
}    
    }


(4)  删除指定数组元素(数组中的成员函数)

        a.  slice(iStart[,iEnd]) :节选数组中的一段,(相当于拷贝了一份出来)原数组不受影响(从start开始到end前一个结束)//[,iEnd]可有可不有,即等价于slice(iStart,iEnd)/slice(iStart)    

var arr = [0,1,2,3,4,5,6,7,8];
console.log('slice截取后:' + arr.slice(6) + '
');(未设置end)//[6,7,8] console.log('slice截取后:' + arr.slice(3,6) + '
');(设置了end)//[3,4,5] console.log('slice截取后:' + arr.slice(-3) + '
'); (负数表示从1开始倒数第几位)//[6,7,8]


      b.  splice(iIndex[,iHowmany][,item1][,item2][,item3]...):从Index开始删除元素(原数组受到影响,占位和内容一起删除--length改变),删除几个由Howmany决定,item:要插入的元素

var arr = [0,1,2,3,4,5,6,7,8];
var arr1 = arr.splice(6);
console.log('splice删除后:' + arr + '
');(未设置end)//[0,1,2,3,4,5] console.log('splice删除后:' + arr1 + '
');(未设置end)//[6,7,8] 
  var arr = [0,1,2,3,4,5,6,7,8];
  var arr1 = arr.splice(-3);
 console.log('splice删除后:' + arr + '
');(未设置end)//[0,1,2,3,4,5]  console.log('splice删除后:' + arr1 + '
');(未设置end)//[6,7,8] 

  

   var arr = [0,1,2,3,4,5,6,7,8];
   var arr1 = arr.splice(2,3);
   console.log('splice删除后:' + arr + '
');(未设置end)//[2,3,4,]    console.log('splice删除后:' + arr1 + '
');(未设置end)//[0,1,5,6,7,8] 

      

 var arr = [0,1,2,3,4,5,6,7,8];
 var arr1 = arr.splice(2,3,-1,-2,-3,-4);
 console.log('splice删除后:' + arr + '
');(未设置end)//[2,3,4,]  console.log('splice删除后:' + arr1 + '
');(未设置end)//[0,1,-1,-2,-3,-4,5,6,7,8] 

   
      c.  delete(iIndex[,iHowmany][,item1][,item2][,item3]...):从Index开始删除元素(原数组受到影响,只是删除内容,位置由empty占位--length不变),删除几个由Howmany决定,item:要插入的元素

       var arr = [0,1,2,3,4,5,6,7,8];
       var arr1 = arr.delete(4);
       console.log('delete删除后:' + arr + '
');//[4]       console.log('delete删除后:' + arr1 + '
');//[0,1,2,3,5,6,7,8]


   (5)  清空一个数组:

       a. 通过length(位置还在,内容清空)     

       var arr = [1,2,3];
       console.log(arr);

       arr.length = 0;
       console.log(arr); //[,,]


       b. 通过splice(相当于堆内存里申请了一个新变量)

       var arr = [1,2,3];
       console.log(arr);

       arr.splice(0);
       console.log(arr); 


       c.直接赋值( )

       var arr = [1,2,3];
       console.log(arr);

       arr = [];
       console.log(arr); 

23. 遍历数组(三种轮询数组的方法)

                   arr = [0,1,2,3,4,5]

        (1)for(i)方法:按照数组的方式改动数组

   for(var i = 0; i < arr.length; i++){ // 索引从0开始,所以i从0开始,小于arr.length,数组名.length:动态检测数组元素的个数
            console.log(arr[i]);
        }


    例题:求数组[2,6,1,8,54,68,14,9,3]的最大值,

    var arr = [2,6,1,8,54,68,14,9,3];
    var max = arr[1]; // 默认最大值取数组中的第1个元素
    for (var i = 1; i <= arr.length; i++) { // 第一个值赋给了max,则从第二个元素开始遍历
        if(arr[i] > max) {
            max = arr[i]; // 如果遍历到比max值大的元素,就将这个元素的值赋值给max
        }
    }
    console.log('该数组的最大值是' + max);


    例题:将数组['red','green','blue','black','yellow']内容反过来存放,

    var arr = ['red','green','blue','black','yellow'];
    var newArry = [];
    for(var i = arr.length-1; i >= 0; i--) {
        newArr[newArry.length] = arr[i];
    }
    console.log(newArry);


    (2)for(in)方法:使用map的方式返回所有非稀疏的节点的key

     for(var i in arr ){
            console.log(arr[i]);
        }
        


    (3)forEach方法:返回所有数字的且非稀疏的节点的value

       arr.forEach(function(x) {
            console.log(x);
        }
    );


24 . 数组的操作

    concat:两个数组合并成一个数组
    join:把数组打开并将所有元素连接成一个字符串
    sort:对数组里面的值(字符串)进行排序并返回(字符串比较ASCII码值:0-30h/a-41h/A-61h)
    
 (1)concat:    

    var arr =[3,2,1];
    var arr2 =[4,5,6];
    var arr3 = arr.concat(arr2);
    console.log(arr3);//[3,2,1,4,5,6]


(2)join:

    var arr =[3,2,1];
    var arr2 =[4,5,6];
    console.log(arr3.join('-'));//3-2-1-4-5-6

    
(3)sort

    arr3 = [1,5,3,2,9,4,0,8];
    console.log(arr3.sort());//[0,1,2,3,4,5,8,9]
    
    arr3 = ['bbb','aaa','ccc'];//字符串排序(从第一位开始比较)
    arr3.sort();
    console.log(arr3);//['aaa','bbb','ccc']


25. 数组排序

         冒泡排序:一种算法,把一系列的数据按照一定的顺序进行排列显示(从小到大或从大到小),每轮两两进行比较调换位置,

    var arr = [4,1,2,3,5];
    for (var i =0; i <= arr.length -1; i++) { //外层循环管趟数,趟数为arr.length-1
        for (var j = 0; j <=arr.length - i -1; j++) { //内层循环管每一趟,同一个数需要交换的次数:arr.length - i - 1
            if (arr[j] > arr[j+1]) { //内部交换两个变量的值,前一个元素和后一个元素相比较
                var temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
    console.log(arr);

26. 多维数组(可以把数组作为一个元素给另外的数组)

    (1) 二维数组

          var matrix = [[1,2,3],[4,5,6],[7,8,9]];
   等价于 matrix = [];
          matrix[0] = [1,2,3];
          matrix[1] = [4,5,6];
          matrix[2] = [7,8,9];
        console.log(matrix[1][1]);访问matrix数组一行一列//5

     
    (2) 三维数组

        var cubic = [];
        cubic[0] = [];
        cubic[0][0] = [[1,2,3]];
        cubic[0][1] = [[4,5,6],];
        cubic[0][2] = [[7,8,9]];
        cubic[1] = [];
        cubic[1][0] = [[10,11,12]];
        cubic[1][1] = [[13,14,15],];
        cubic[1][2] = [[16,17,18]];
        cubic[2] = [];
        cubic[2][0] = [[19,20,21]];
        cubic[2][1] = [[22,23,24],];
        cubic[2][2] = [[25,26,27]];
    console.log(cubic[1][1][1]);访问cubic数组一行一列一层//14    

27. 类数组

    (1)有下标,有length,有push和splice方法,就是一个类数组

    (2)类数组既可以当数组用又可以当对象用

    (3)DOM里的数组都是类数组

       var arr = [1,2,3];//数组
       
       var obj = {//类数组
           '0':1,
           '1':2,
           '2':3,
           'length':3,
           'push':Array.prototype.push,
           'splice':Array.prototype.splice
       };    

28.  函数

        封装一段可以被重复执行调用的代码块,方便大量代码重复利用

        函数使用:首先声明函数,然后调用函数,函数不调用自己不执行

      (1)函数的声明:

               函数可以有形参,也可以没有,可以有返回值,也可以没有,若没有返回undefined

       a.  利用函数关键字自定义函数(命名函数):

              function 函数名 (形参){
                   函数体/语句
               }

            例1:x = [1,2,3,4,5,NaN,undefined,'abc'],数组求和

   function sum(arr){
                var iRet = 0;
                for(var i = 0; i < arr.length; i++){
                    if (typeof(arr[i]) == 'number'){
                        if(!isNaN(arr[i]) && isFinite(arr[i])){
                            iRet += arr[i] ;
                        }
                    }
                }
                return iRet;
            }
        console.log(sum(x));//15 


        例2:[1,2,3,4,5]--[5,4,3,2,1]    用函数实现

 function reverseNumber(num){
            if(typeof num != 'number'){
                return '';
            }
          if(!isFinite(num) || isNaN(num)){
              return '';
          }
          var tem + num.toString().split('').reverse().join('')
        }
        console.log(reverseNumber(12345));


    b.  函数表达式(匿名函数):函数表达式声明和声明变量差不多,只不过变量里面存的是值,而函数表达式里面存的是函数//系统不会存储函数名,所以不需要函数名,且表达式需要加分号

          ( function f(){ } );
//相当于    var f = function(){ };


             例题:阶乘

var f = function(x){//等价于function fact(x)
                 if (x <= 1){
                     return 1;
                 } else{
                     return x * arguments.callee(x-1)//等价于return x* fact(x-1)
                     }; 
             };
             console.log(f(5));


    c.  函数可以作为参数传递给另一个函数

        //f2()是函数声明
    function f2(){
        console.log('I am f2()');
        return 'f2 say hello!';
    }
  f1(f2);
 //f3是函数表达式
    var f3 = function(){
             console.log('I am f3()');
             return 'f3 say hello!';
         };
     f1(f3);


    d.   立即执行函数:不需要调用,立马能够自己执行的函数,只能用一次//引用数变为0,即被GC释放(function是一个引用类型的对象)
                 写法: ( function ( ) {  } ) ( )

                    或 ( function( ) { } ( ) )  //第二个小括号可以看作是调用的意思

                     --优点:独立创建了一个作用域,里面所有的变量都是局部变量,不会有命名冲突,用完释放,减少内存压力 
                     --只有函数表达式可以,函数声明不可以
                     --函数表达式中的名字不会被放在GO或者AO中

     console.log(
                   (
                  function(x){
                     console.log('I am f3()');
                     return 'f3 say hello to ' + x '!';
                  }
           )
            (wangli)
     );


    e.  嵌套函数:重复过程要提炼出函数

 function hypotenuse(a,b){
        return Math.sqrt(a*a + b*b);
    }
    console.log(hypotenuse(3,4))


    改为嵌套函数后:

  function hypotenuse(a,b){
        function square (x){
            return x*x;
        }
    }
    console.log(hypotenuse(3,4))


  (2)函数的调用:

    a. 函数的方式

f2(f1)


    b. 作为对象的方法

 var obj = {
            add:function(a,b){
                return a + b;
            }
        }
    console.log(obj.add(1,2));


    c. 构造函数

 var arr = new Array();


    d. 间接调用:间接调用和直接调用唯一的区别就是可以绑定this指针,如果不考虑this,这三种调用方式完全一样

  function hypotenuse(a,b){
        return Math.sqrt(a*a + b*b);
    }
    this.hypotenuse(3,4);//直接调用
    hypotenuse.call(this,3,4);//间接调用
    hypotenuse.apply(this,[3,4]);//间接调用


    e. 函数之间可以相互调用

    例题:用户输入年份,输出当前年份2月份的天数

    function isRunYear (year) { //如果是闰年返回true,否则返回false
        var flag = false;
        if (year % 4 == 0 && year % 100 == 0 || year % 400 == 0){
            flag = true;
        }
        return flag;
    }
 function backDay(){
        var year = prompt('请输入要查询的年份')
        if(isRunYear (year)){  //调用函数需要加小括号
            alert(year + '年是闰年,2月份有29天');
        } else{
            alert(year + '年是平年,2月份有28天');
        }
    }
    backDay();

29. 函数的形参和实参

     在函数内部某些值不固定,可以通过参数在调用函数时传递不同的值进去,参数可以实现执行不重复的代码(形参和实参数量和类型都可以不一样,形参和实参会绑定,动态关联)

function 函数名 (形参1,形参2) { //函数声明小括号里的是形参(形式上的参数)  }

   函数名(实参1,实参2)

             函数调用小括号里的是实参(实际的参数),函数调用的时候把值传递给形参
   
 注意:

         a.如果实参和形参个数一致,则正常输出结果
         b.如果实参的个数多于形参的个数,会依次取够形参的个数即不会再往后取后面的值
         c.如果实参的个数小于形参的个数,没有接收到实参传递的值得形参可以看作是不用声明的变量,即undefined,相加结果为NaN
         
 arguments的使用

          不确定有多少个参数传递的时候,可以完全不写形参,因为所有函数都内置了一个arguments对象,且只有函数中有arguments,arguments对象中存储了传递的所有实参,传递的实参可以通过arguments来获取
           arguments展示形式是一个伪数组,可以进行遍历,具有length属性,按索引方式存数数据,但不具有数组的push和pop等方法     

function foo(){ 
       console.log(foo.length);//6
       console.log(arguments);  //arguments是实参的数组 [1,2,3,4,5,6]
       console.log(arguments[2]);//3
       for (i = 0; i < arguments.length; i++){ //遍历arguments中的参数
           console.log(arguments[i]);//1 2 3 4 5 6
       }
   }
  foo(1,2,3,4,5,6);
    

30. 函数的返回值

       return语句:通过returen将函数将值返回给调用者,同时return也是终止语句,return后面的语句不再执行

       return只能返回一个值,有多个值时只返回最后一个值,若要返回多个值,可以一个数组的形式返

    错误示范:

function cook (aru) {
        console.log(aru);//函数内部一般不书写输出语句输出最终结果
    }
    cook('大猪肘子');


  正确语法:

     function 函数名 (形参) {
              return 需要返回的结果;//只要函数遇到return就把后面的结果返回给函数的调用者,若函数没有return则返回的结果是undefined
          }
          函数名(实参); //等同于return后面的结果
          console.log(函数名(实参));


    正确示范:

    function getSum (num1,num2) {
        return num1 + num2;
    }
    console.log(getNum (1,2));//输出3

31. 作用域

                   是在运行时代码中某些特定部分的变量、函数、和对象的可访问性。作用域决定了代码区块中变量和其它资源的可见性,分为局部作用域和全局作用域

                    就是代码名字在某个范围内起作用和效果,目的是为了提高程序的可靠性,减少命名冲突,在不同作用域下变量名不会冲突

          全局作用域:整个script标签内或一个单独的js文件

          局部作用域(函数作用域):在函数内部,代码名字只在函数内部起效果和作用

          变量作用域:根据作用域的不同,变量分为全局变量和局部变量  
          全局变量:在全局作用域下的变量,在全局下都可以使用
  
               ***如果在函数内部没有声明直接赋值的变量也属于全局变量

          局部变量:在局部作用域下的变量,即在函数内部的变量就是几部变量

               ***函数的形参也可以看作是局部变量


          
      函数作用域
          外部对内部可见

          var scope = 'g';
          function t (){
              console.log(scope);//g
              console.log(scope);//g
          }
          t();


          内部对外部不可见

         function t (){
                      var scope = 'l';
          }
          t();
          console.log(scope);//报错


          都可见时,内部优先

          var scope = 'g';
          function t (){
                        console.log(scope);//undefined
                      var scope = '1';
                        console.log(scope);//1
          }
          t();


       js中只有函数级别的作用域,没有块级别的作用域(es6时新增块级作用域);

       换句话说,只有在进入或者退出函数的时候,作用域会发生变化    

32. 执行环境和作用域链

       (1)执行环境

               定义了执行期间可以访问的变量和函数

          全局执行环境:全局变量只有浏览器关闭时才会销毁,比较占内存资源

              Global Object (window)
              从见到JS代码开始创建
              到网页关闭时销毁

          函数执行环境:局部变量当程序执行完毕就会销毁,比较节约内存资源

            Activation Object
            从函数调用开始创建
            到函数调用结束时销毁


     (2)

             a.作用域链(scope),每个函数都有,内部函数访问外部函数的变量(函数嵌套),采取的是链式查找(一级一级往上,就近原则)的方式来决定取那个值,这种结构称为作用域链

             b.作用域是私有属性,只能由JS引擎访问;

             c.作用域链,是AO和GO构成的链

             d.所谓执行环境,就是根据作用域链依次查找变量和函数
               找到即停
               全部找完无果,报错

            e.作用域链,每个函数都有

33. 生成作用域链

      每个函数在定义(函数声明/函数表达式)时会拷贝其父亲函数的作用域链
      在函数被调用时,生成AO然后将AO压入作用域链的栈顶
    (函数在被多次调用时产生不同的AO,函数在被多次递归调用时产生不同的AO)
    (with,生成新的with variable object,放在作用域链表顶端)

        var name = 1;
        var person = {
            name:2
        }
        with(person){
            console.log(name);//2
        }    

34. 作用域链的应用

      (1) 尽量少使用靠近上层的变量,多使用自己的局部变量,不然效率低
      (2) 尽量减少不同层次函数使用相同的变量名,避免函数名与变量名一样,不然重名,容易出错

35. 预编译(预解析)(第一次/前置扫描)

   (1)  js引擎运行js分为两步,先预解析后代码执行

        a. 预解析:js引擎会把js里面所有的变量声明(var)和函数声明(function)提升到当前作用域的最前面(只是声明不赋值)

        b. 代码执行:按照代码书写的顺序从上往下执行

   (2)  预解析分为变量预解析(变量提升)和函数预解析(函数提升) 

     a. 变量提升就是把所有变量声明提升到当前作用域的最前面(不提升赋值操作) 

         console.log(num); // undefined
         var num = 0;


        执行顺序:var num; //预解析

  console.log(num); // undefined
  num = 0;


     b. 函数提升就是把所有函数声明提升到当前作用域的最前面(不调用函数)

       fun(); // 报错
        var fun = function(){
            console.log(222);
        }


     执行顺序:var fun; //预解析

             fun(); // 报错
             fun = function(){
                 console.log(222);
             }


    36. 函数(预编译)

        (1):创建全局对象GO(window)(上下文)
        (2):加载函数文件
        (3):预编译

               a.找出所有的变量声明,按照变量名加入全局对象,如果已存在,忽略
               b.找出所有的函数声明,按照函数名加入全局对象,如果已经存在同名变量或者函数,替换
               c.非声明不予理睬
       (4): 解释执行
              a. 没有var的变量,都不是变量声明,全部认为是window的全局变量,不参与编译            

                              console.log(aa);
                              aa = 5;
                              console.log(aa);


             b. 即使在函数中,aa也是全局变量,是运行时,不是定义时;     

                              text();
                              function text (){
                                a = 5;
                              }
                              console.log(a);


              c.函数中,所有变量声明,在函数的预编译阶段完成,所有变量的声明与实际的书写位置无关

                             console.log(aa);
                              var aa = 5;
                              console.log(aa);


           d. 函数中,所有函数声明,在函数的预编译阶段完成,所有函数的声明与实际的书写位置无关

                              console.log(haha);
                              function haha (){
                                      console.log('h1');
                              }


          e.函数中,如果变量与函数同名,那么,函数将覆盖变量

                              console.log(haha);
                              var haha = 123;
                              function haha (){
                                      console.log('h1');
                              }


          f. 函数中,只有函数能够覆盖变量,变量无法覆盖函数

                              console.log(haha);
                              function haha (){
                                      console.log('h1');
                              }
                              var haha = 123;


           g.函数中,函数如果同名,后面的函数声明会覆盖前面的函数声明,并且忽略参数           

   haha(1);
   console.log(haha); 
   function haha (a){
   console.log('haha1');
   }
   function haha (b){
   console.log('haha2');
                              }


    37. 函数(预编译)调用

       (1)创建活动对象AO(Active Object)(上下文)

       (2)预编译
          scope chain
          初始化arguments
          初始化形参,将arguments中的值赋值给形参
          找出所有的变量声明,按照变量名加入AO,如果已存在忽略
          找出所有函数声明,按照函数名加入AO,如果已存在同名变量或者函数,替换
          this初始化

        (3)解释执行
             a. 函数中,所有变量声明,在函数的预编译阶段完成,所有变量的声明与实际的书写位置无关

    function f(){
        console.log(aa);
        var aa = 5;
        console.log(aa);    
        }


              b. 函数中,所有函数声明,在函数的预编译阶段完成,所有函数的声明与实际的书写位置无关

     function f(){
        console.log(haha);
        function haha (){
                console.log('h1');
        }
    }


               c. 函数中,如果变量与函数同名,那么,函数将覆盖变量


               d. 函数中,只有函数能够覆盖变量,变量无法覆盖函数

        function f(){
        console.log(haha);
        function haha (){
                console.log('h1');
        }
        var haha = 123;


                e. 函数中,函数如果同名,后面的函数声明会覆盖前面的函数声明,并且忽略参数

        haha(1);
        console.log(haha); 
        function haha (a){
                console.log('haha1');
        }
        function haha (b){
                console.log('haha2');
        } 


               f. 当函数编译后,遇到需要访问的变量或函数,优先考虑自己AO中定义的变量和函数,如果找不到,才会在其定义的上一层中寻找,直到到达GO

38. 递归 

一个函数在内部可以调用其本身,那么这个函数就是递归函数(简单理解就是函数内部自己调用自己)

递归函数作用和循环效果类似
        由于递归很容易发生'栈溢出'错误(stack overflow),所以必须加退出条件 return
        递归可用于遍历多层对象

    案例:利用递归求1-n的阶乘1*2*3*...n

 function fn(n){
             if (n === 1){
                 return 1;
             }
             return n * f(n-1);
         }
         fn();

  
        案例:利用递归求斐波那契数列(兔子序列:指定的那一项是他前两项的和) 1,1,2,3,5,8,13...

   function fb(n){
                 if (n === 1 || n === 2){
                     return 1;
                 }
                 return f(n-2) + f(n-1);
             }
             console.log(fb(3));//2 

    递归构造:

                    找到已知f(x-1)情况下(找到递归的基石,比如f(0)、f(1)的值)求解f(x)的通式

    递归的例子:
                   有一台阶,阶数为n,可以一次跨1阶、2阶、3阶,一共有多少种走法?

function step(n){
        switch(n){
            case 1:return 1;
                   break;
            case 2:return 2;
                   break;
            case 3:return 4;
                   break;
            default:return (step(n-3)+step(n-2)+step(n-1));
                   break;
        }
        return '';
    }
    console.log(step(5));

39. 闭包

  闭包是一个函数加上创建函数的函数的作用域的连接,闭包关闭了函数的自由变量
   function fun(){
			  	var a=10;
			  	return function fuu(){
			  		console.log(a)//a是自由变量
			  	}
			  }

    (1) 变量作用域: 函数内部可以使用全局变量,函数外部不可以使用局部变量,函数执行完毕,本作用域内的局部变量会销毁

    (2)闭包:  指有权访问另一个函数作用域中变量的函数(简单理解就是:一个作用域可以访问另一个函数内部的局部变量) ,//被访问的拥有局部变量的那个函数就是闭包函数

        闭包的主要作用:访问其他函数内部变量,延长变量的生命周期,避免定义全局变量所造成的污染

function fn (){  //fn是闭包函数
            var num = 10; //num是局部变量
            function fun(){
                console.log(num);
            }
            return fun();
        }
        var f = fn();
        f();


    fn外面的作用域也可以访问fn内部的局部变量
    
    案例:使用闭包的方式得到当前li的索引号 

 for(var = i = 0; i < lis.length; i++){
             (function(i){ //立即执行函数也称为小闭包,因为立即执行函数里面任何一个函数都可以使用他的变量
                 lis[i].onclick = function(){
                     console.log(i); //调用立即执行函数传进来的参数i
                 }
             })()
         }

      函数的AO通过scope chain相互连接起来,使得函数体内的变量都可以保存在函数的AO,这样的特性称为“闭包”

    闭包的危险:闭包会造成原有AO不释放,造成内存泄露

    如何避免闭包引起的内存泄漏:

                        在退出函数之前,将不使用的局部变量赋值为null

    闭包的应用:实现公有变量
                         缓存存储结构
                         封装,实现属性私有化

            练习1:

     function outer (){
                var num = 100;
                function add {
                    num ++;
                    console.log(num);
                }
                return add;
            }
            var fn = outer();
            fn();//101
            fn();//102
            fn();//103
            var fn2 = outer();
            fn2();//101


        练习2:

   function outer(){
            var result = new Array();
            for (var i = 0; i < 2; i++){
                result[i] = function (){
                    return i;
                }
            }
            return result;
        }
    var fn = outer();
    console,log(fn[0]());//2
    console,log(fn[1]());//2

40. this的用法

    (1) 在脚本中,this初始化为window

console.log(this);


    (2) 在普通函数中,this初始化为window

  function f (){
         console.log(this);
      }
      f();


    (3) 在object调用的函数中,this被指定为object,谁调用,指向谁

 var obj = {
          name: 'a',
          f2: fuction(){
             console.log(this); 
          }
      };
      obj.f2();


    (4) 在call/apply中,this可以被指定,被指定为第一参数

    var obj = {
                 name: 'a',
                 f2: fuction(x,y){
                    console.log(this); 
                 }
       };
       obj.f2();
       var f = obj.f2;
       f.call(obj,1,2);//object


    (5) 在new的构造函数中,this被指向正在创建的对象

   function F(){
           console.log(this);
       }
       var obj = new F();

41. 对象

        对象是一个具体的事物,js中对象是一组无序的相关属性和方法的集合,所有事物都是对象,例如字符串,数值,数组,函数等

        对象是由属性和方法组成的 (js中的对象表达机构更清晰,更强大)

javascript中的对象分为三种:自定义对象,内置对象(Math,Date,Arry,String等),浏览器对象

42. (自定义)对象的创建

          (除最后一行外用逗号分割)

               (1)  对象里面的属性或者方法采取见值对的形式,键(属性名) : 值(属性值)

               (2)  多个属性或者方法中间用逗号隔开

               (3)  方法冒号后面跟的是一个匿名函数
对象的三种命名规则
   (1)匈牙利命名规则:属性+类型+对象描述
                      属性:成员变量m_、静态成员s_
					  类型:整形i、数组a、字符串str
					  对象描述:单词
   (2)小驼峰命名规则:对象描述(第一个单词首字母小写,其他单词首字母大写)
   (3)大驼峰命名规则:对象描述

 

 (1)  利用字面量创建对象{ }

  var obj1 = {};

 
            例子:var objBook = {

                  name :'Book Name',//原始成员
                      pageNumber:300;
                      author:{          //引用成员
                          firstname:'aaa',
                          lastname:'bbb';
                      },
                      query: function(){//成员函数表达式
                          console.log('query');
                      }  
            };
            


        (2)  利用new Object创建对象

  var obj2 = new Object(); // 两个方法一样


          利用 = 赋值的方法添加对象的属性和方法
          每个属性和方法之间用分号结束

           obj2.name = '张三';
           obj2.age = 18;

 
       (3)  构造函数(创建对象)

           把对象里面一些相同的属性和方法抽象出来封装到函数里面
           能够每次以相同的方式构造对象,同时改动这个函数,所有的对象都能跟着改动
           与前两个创建对象的方法(一次只能创建一个对象)相比,构造函数可以一次创建多个对象//构造函数名称以大写字母开头(约定俗成)

                 构造函数不需要return就能返回结果
                 调用构造函数必须使用new
                 属性和方法前面必须添加this

  

             new在执行时的步骤:
                 a. 在内存中创建一个新的空对象
                 b. 让this指向这个新的空对象
                 c. 执行构造函数里的代码,给这个对象添加属性和方法
                 d. 返回这个新对象(所以构造函数不需要return就能返回结果)


                function 构造函数函数名(){
                        this.属性 = 值;
                        this.方法 = function(){};
                    }
                 new 构造函数名(); 

 function Student(name,age,gender ){
                this.name = name;
                this.age = age;
                this.gender = gender;
            }
           var std = new Student('wangli',30,'male');

 43. 对象的属性

     对象属性可以增删改查,与数组类似,但不需要声明变量

     枚举:自己的东西可以枚举出来,继承别人来的东西不能枚举出来 

 var obj = {};


    (1)  增加一个属性    

                obj.a = 'aaa';
                obj['1'] = 'bbb'
                obj.f1 = function(){
                    console.log('ff........')
                };


                
   (2)查询一个属性

            a.  in

  console.log('a' in obj);

 
          b.   hasOwnProperty()

 console.log(obj.hasOwenProperty('a'));

 (3)删除一个属性
          delete 

 delete obj.a;

                 
(4)修改一个属性

   obj.a = 123;

44. 对象的使用(调用对象属性或方法)

(1)调用对象的属性1:对象名.属性名

   console.log(objBook.name);


(2)调用对象的属性2:对象名['属性名']
    等价于:

console.log(objBook['age']);


(3)调用对象的方法:属性名.方法名()

 objbook.query();

              
45. 对象的遍历

for in

        for (变量 in 对象){
            
        }    

    for (var in obj){ //for in里面的变量名,最常用的是k 和 key
        console.log(k); //k变量输出,得到的是属性名  name 
        console.log(obj[k]); // obj[k] ,得到的是属性值 张三 
        
    }

46. Math 对象

  (1)常数

   console.log(Math.E);//2.71828
   console.log(Math.LN2);//0.9
   console.log(Math.LN10);//2.3
   console.log(Math.PI);//3.1415926535
   console.log(Math.SQRT1_2)//根号下1/2


  (2)方法

  绝对值

   console.log(Math.abs(-5));


    三角函数

  console.log(Math.sin(30));//0.5


    反三角函数

 console.log(Math.asin(1));


    四舍五入以及取整

        console.log(Math.round(10.4));//10
        console.log(Math.round(10.5));//11
        console.log(Math.floor(10.6));//10 向下取整
        console.log(Math.ceil(10.4));//11 向上取整


    指数和对数

        console.log(Math.exp(2));//7.3     e^2
        console.log(Math.pow(2,2));//4     2^2
        console.log(Math.log(25));//3.2     e^3.2=25
        console.log(Math.sqrt(25));//5     根号下25


    最大值最小值

        console.log(Math.max(1,5,25));//25
        console.log(Math.min(1,5,25));//1


    随机数

  console.log(Math.random());//0-1之间的均匀分布 [0,1)


     随机数公式:得到两个数之间的随机整数且包含这两个数:

 function getRandom(min,max){
         return Math.floor(Math.random()*(max-min+1))+min;
     }
        console.log(getRandom(1,10));


    案例

            a. 猜1-10之前的一个数(只有3次机会)    

   var getRandom = function (min,max){
        return Math.floor(Math.random()*(max-min+1))+min;
    }    
    var random = getRandom(0,10);
    console.log(random)
    
    for(var i = 1; i<= 3; i++){
        var num = prompt('请猜一个1-10之间的数')
        if (num < random){
            alert('对不起,你猜小了')
        } else if(num > random){
            alert('对不起,你猜大了')
        } else{
            alert('恭喜你,你猜对了')
            break;
        }
    }


    
            b.随机点名:

    var arr = ['张三丰','霍元甲','李小龙'];
    console.log(arr[getRandom(0,arr.length-1)]);
    Math object
        console.log(Math.valueOf();//Math本身是一个object

47. Date日期对象(是一个构造函数,必须new)

   (1) 如何获取当前时间

      var d1 = new Date();//必须先实例化,才能调用其他(年月日时分秒)对象
      console.log(d1);


    (2) 数:1970年1月1日到现在的毫秒数(时间戳,永远不会重复,一直在增加)

      var d3 = Date.parse(d1.toString());//获取总的毫秒数
      console.log(d3);
      console.log(d1.getTime());//获取总的毫秒数
      var x = d1.getTime();
      x = x / (1000*3600*24*365);
      console.log(x);//1970年到现在有几年
console.log(d1.valueOf());//获取总的毫秒数
var date1 = +new Date(); // +new Date()返回的就是总的毫秒数
console.log(Date.now()); //获取总的毫秒数(h5新增)


    (3) setFullYear()//月份设定特殊,从0-11

d1.setFullYear(2017,0,12);//2017年1月12日


    (4) 有参数的构造函数

   var d2 = new Date(2017,0,12);//2017年1月12日


    (5) UTC(协调世界时间)和GMT (格林尼治时间)

       console.log(d1.toUTCString());
       console.log(d1.toGMTString());


    (6) 设定年setFullYear和getFullYear 

       d1.setFullYear(2015);
       console.log(d1);
       d1.setFullYear(d1.getFullYear() +1);
       console.log(d1);


    (7) 设定月(0-11)

     console.log(d1.getMonth() + 1 );//设定月


    (8) 设定日

      console.log(d1.getDate());//设定日


    (9) 设定星期几(0:星期日,1-6:周一到周六)

console.log(d1.getDay());//设定日


    (10) Date克隆

        var d4 = new Date(d1);
        console.log(d4);

48. 定时器:也称回调函数callback

 (1) setTimeout(调用函数,延迟的毫秒数)  只调用一次函数

        clearTimeout(定时器名) 停止定时器
        
 (2) setInterval(调用函数,延迟的毫秒数)一直调用函数

      clearInterval(定时器名) 停止定时器
      
(3) this:this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,一般情况下this的最终指向是那个调用他的对象

         a.全局作用域或者普通函数中this指向全局对象window(注意定时器里的this指向window)

         b.方法调用中谁调用this指向谁

         c.构造函数中this指向构造函数的实例
            function Fun(){ //this指向fun
                console.log(this);
            }
            var fun = new Fun();
       
    练习:做一个时钟(可终止)

var timer;
        
        function startTime(){
            var today = new Date();//获取当前时间
            var h = to2bit(today.getHours());//获取小时
            var m = to2bit(today.getMinutes());//获取分钟
            var s = to2bit(today.getSeconds());//获取秒
            
            var div = document.getElementById('txt');//找到输出时间的div
            div.innerHTML = h + ':' + m + ':' + s;//将div中原有内容替换为时间
            timer = setTimeout('startTime()',20);//每隔20毫秒运行一次setTimeout这个函数
        }
        timer = setTimeout('startTime()',20);//每隔20毫秒运行一次startTime这个函数
        
        function to2bit(num){//当时分秒数字显示小于10时,在时间前补0占位
            if(num < 10){
                return '0' + num;
            }else{
                return '' + num;
            }
        }
        
        function stopTime(){//清除定时器
            clearTimeout(timer);
        }


    练习:做一个定时器

var time = prompt('请输入什么时间点结束(时间格式:2020-09-10 18:00:24)')
    function countDown (time){
        var nowTime = +new Date(); //返回当前时间的总豪秒数
        var inputTime = +new Date(time); //用户输入的时间(未来时间,即到什么时候结束)的总豪秒数
        var timeDown = (inputTime - nowTime)/1000; //现在时间到未来时间剩余时间的总秒数
        var d = parseInt(timeDown/60/60/24); //计算天数
            d = d < 10 ? '0' + d : '' + d; //不足10则补0占位
        var h = parseInt(timeDown/60/60%24); //计算小时
            h = h < 10 ? '0' + h : '' + h; //不足10则补0占位
        var m = parseInt(timeDown/60%60); //计算分钟
            m = m < 10 ? '0' + m : '' + m; //不足10则补0占位
        var s = parseInscrot(timeDown%60); //计算秒数
            s = s < 10 ? '0' + s : '' + s; //不足10则补0占位
        return d + '天' + h + '时' + m + '分' + s + '秒'    ;
        
    }    
    
    function show(){ 
        console.log('距离结束还有' + countDown(time));
        var timer = setTimeout('show()',1000);//每隔20毫秒运行一次countDown这个函数
    }    
        
    show();


    练习:做一个可以变长的进度条

  function startLonger(){
        var div = document.getElementById('divid');
        var width = Number.parseInt(div.style.width);
        if(width < 300){
            width += 5;
            div.style.width = width + 'px';
            setTimeout(startLonger(),20);
        }else{
            div.style.width = '300px';
        }
        
    }
    setTimeout(startLonger(),20);

49. Arry数组对象

 var arr = new Array();//创建了一个空数组
 var arr = new Array(2);//表示数组长度为2,里面有2个空的数组元素
 var arr = new Array(2,3);//等价于var arr = [2,3];里面有2个数组元素,2和3


    (1) 检测是否为数组

       a. instanceof Array   //运算符

         var arr = [2,3];
         var obj = {name:'张三'};
        console.log(arr instanceof Array);//true
        console.log(obj instanceof Array);//false


        b. Array.isArray()  //h5新增

          var arr = [2,3];
          var obj = {name:'张三'};
          console.log(Array.isArray(arr));//true
          console.log(Array.isArray(obj));//false

  
    (2) 添加数组元素

        a. push(推):在数组末尾添加一个或多个数组元素
                   push()参数直接写数组元素就行,多个元素用英文逗号隔开
                   push之后,返回的结果是新数组的长度,原数组也会发生变化

          var arr = [1,2,3];
          arr.push(4); //arr = [1,2,3,4]
          arr.push(4,'pink'); //arr = [1,2,3,4,'pink']


        
        b. unshift():在数组前面添加一个或多个数组元素
                   unshift()参数直接写数组元素就行,多个元素用英文逗号隔开
                   unshift之后,返回的结果是新数组的长度,原数组也会发生变化

          var arr = [1,2,3];
          arr.unshift(4); //arr = [4,1,2,3]
          arr.unshift(4,'pink'); //arr = [4,'pink',1,2,3]


    (3) 删除数组元素

        a. pop(推):删除数组的最后一个元素
                   pop()没有参数
                   pop之后,返回的结果是新数组的长度,原数组也会发生变化

          var arr = [1,2,3];
          arr.pop(); //arr = [1,2]


        b. shift():删除数组的第一个元素
                   shift()没有参数
                   shift之后,返回的结果是新数组的长度,原数组也会发生变化

          var arr = [1,2,3];
          arr.shift(); //arr = [2,3]

     
    (4) 数组排序

         a. 翻转数组:reverse()

           var arr = [1,2,3];
           arr.reverse(); //arr = [3,2,1]


           
         b. 冒泡排序:sort() 

            var arr = [4,3,1];
            arr.sort(); //arr = [1,3,4]


            sort只能个位排序,超过个位从左往右依次比较排序

            var arr = [4,3,11,1,35];
            arr.sort(); //arr = [1,11,3,,35,4]

    
        解决超过两位数的sort排序:

             var arr = [4,3,11,1,35];
             arr.sort(function(a,b){
                return a-b; //升序排列
                return b-a; //降序排列
             }); //arr = [1,3,4,11,35]

   
        (5) 数组索引

            a. indexOf(数组元素):从前面开始查找,返回该数组满足条件的第一个元素的索引号,找不到该数组元素则返回负一(-1)

               var arr = [4,3,11,3,35];
               console.log(indexOf(3));//1
               console.log(indexOf(8));//-1


            b.lastIndexOf(数组元素):从后面开始查找,返回该数组满足条件的第一个元素的索引号,找不到该数组元素则返回负一(-1)              

               var arr = [4,3,11,3,35,5];
               console.log(lastIndexOf(3));//3
               console.log(lastIndexOf(8));//-1


        (6) 数组去重

           遍历旧数组,拿着旧数组得元素去查询新数组,如果该元素不在新数组中就添加进新数组,如果新数组已经由相同元素就不添加

 function unique(arr){
                var newArray = []; //声明一个新数组
                for (var i = 0; i < arr.length; i++){ //遍历旧数组
                    if (newArray.indexOf(arr[i]) === -1){ //在新数组里查询旧数组的该元素,若不能查到
                        newArray.push(arr[i]);// 则把旧数组的这个元素添加到新数组里
                    }
                }
                return newArray;
            }
            var demo = unique(['3','5','6','5','6','3','1');
            console.log(demo);


            (a)//时间复杂度,与x元素个数成正比-----(number/number、boolean、string都适用)

            var x = [1,3,4,5,1,3,2,1,2,4];
            var y = [];
            for (var i = 0;i < x.length; i++){ //遍历旧数组
                for (var j = 0; j < y.length; j++){ //遍历新数组
                    if(x[i] === y[j]){//看看这个元素y里是不是有,没有的话push ,等于说明重复
                        break;
                    } 
                }
                if(j >= y.length){
                    y.push(x[i]);
                }
            }
            console.log(x); //[1,3,4,5,1,3,2,1,2,4];
            console.log(x); //[1,3,4,5,2];


            (b)//时间复杂度,生成y的时间复杂度O(N),x排序,时间复杂度O(N*logN)(基于比较的排序,堆排序,时间都是N*logN)--------(只适用于number)

            var x = [1,3,4,5,1,3,2,1,2,4];
            var y = [];
            x.sort();//x排序,不用每次翻找y
            console.log(x);//[1,1,1,2,2,3,3,4,4,5];
            for(var i = 0; i < x.length; i++){
                if(y.length != 0 || y[y.length - 1] !== x[i]){
                    y.push(x[i]);
                }
            }
            console.log(y);//[1,2,3,4,5]


            (c)//取决于arrMap的时间复杂度

            var arrMap = [];
            for(var i = 0; i < x.length; i++){
                arrMap[x[i]] = true;
            }
            for(var j in arrMap){
                y.push(+j);//[1,2,3,4,5]
            }
            console.log(y);


        
        (7) 数组转换为字符串

           a. toString()

              var arr = [1,2,3]
              console.log(arr.toString()); // 1,2,3

         
           b. join(分隔符) //可以添加分隔符

               var arr = [1,2,3]
               console.log(arr.join()); // 1,2,3 默认逗号
               console.log(arr.join(-)); // 1-2-3

50. 字符串对象

   (1)基本包装类型

       把简单的数据类型(String,Number,Boolean)包装成为复杂数据类型,这样基本数据类型也就同对象一样有了属性和方法,

           var str = 'andy';
           console.log(str.lengthg);//4


         类包装执行过程
         a.生成临时变量,把简单数据类型包装成为复杂数据类型

    temp = new String('andy');


         b.赋值给我们声明的字符变量          

 str = temp; //str = new String('andy');


         c.销毁临时变量

  temp = null;

    (2) 字符串的不可变

         指的是里面的值不可变,虽然可以给一个字符串的变量重新赋一个新的值,看上去内容可以改变,但其实是新开辟了一个内存空间把新的值存进去,在让声明的变量指向新空间,本质上地址已经变了,因此不要大量拼接字符串和给字符串变量重新赋值,这样会占用大量内存空间

    (3)根据字符返回位置

         字符串所有方法,都不会修改字符串本身(字符串不可变特性),操作完成会返回一个新的字符串,
        indexOf/lastIndexOf('查找的字符',查找的起始位置)
        
      例题:查找字符串'abcdeohofgoasdocvoxcoadopp'中所有o出现的位置以及出现的次数

var str = 'abcdeohofgoasdocvoxcoadopp';
        var index = str.indexOf('o');//查找o首次出现的位置
        var count = 0;
        while (index !== -1){ //如果查找到有o
            console.log('o出现的位置是字符串的' + index + '号索引位置');
            count += 1;
            index = str.indexOf('o',index + 1);
        }
        console.log('o出现的次数一共是' + count + '次');


    (4)根据位置返回字符

         a.charAt(index):返回指定位置的字符,

 var str = 'andy';
 console.log(str.charAt(3));//y


             遍历字符串

  for (var i = 0; i < str.length; i++){
               console.log(str.charAt(i))
           }
           


        b.charCodeAt(index):获取指定位置处字符的ASCILL码,可以判断用户按了哪个键

  var str = 'andy';
  console.log(str.charCodeAt(0));//97


        c.str[index]:获取指定位置处字符 //html新增 ,IE8以上支持

var str = 'andy';
 console.log(str[3]);//y


    案例:判断一个字符串'abcodofodoxcfopp'中出现次数最多的字符,并统计其出现的次数

     var str = 'abcodofodoxcfopp';
        var obj = {};//声明一个空对象
        for (var i = 0; i < str.length; i++){ //遍历字符串
                    var  property = str.charAt(i); //把遍历的字符复制给属性
                            if(obj[property]){ //如果空对象里有该字符这个属性
                                obj[property]++; //那么这个属性值+1
                            } else{ //不存在
                                obj[property] = 1;//则属性值为1
                            }
        }
        console.log(obj);

        var max = 0; //声明一个最大值
        var theChar = ''; //声明一个变量接收最大属性
        for (var k in obj){ //遍历对象
             if (obj[k] > max){ //如果对象里的属性值大于声明的最大值
                 max = obj[k]; //那么最大值就被赋值=属性值
                 theChar = k; //最大属性值的属性就是该字符
             }
        }
        console.log('出现次数最多的字符是' + theChar);
        console.log('一共出现的次数是' + max + '次');


    (5)字符串操作方法
        a.concat(str1,str2,str3):用于连接两个或多个字符串,等效于+,
        
        b.substr(start,length):从start位置开始(索引号),length取的个数
        
        c.slice(start,end):从start位置开始,截取到end位置,end不包含在内
        
        d.substring(start,end):从start位置开始,截取到end位置,end不包含在内,基本和slice相同,但是不接受负值

          var str = "hello world"
          console.log(str.substring(0,l+1));//hello


    (6)    其他方法
        a.replace('被替换的字符','替换为的字符') //只会替换第一个字符 

            var str = "hello world"
            console.log(str.replace(o,a));//hella world


        b.split('分隔符')
        
        c.toUpperCase()  转换大写

            var str = "hello world"
            console.log(str.toUpperCase());//HELLO WORLD

 
        d.toLowerCase  转换小写

              var str = "hello world"
              console.log(str.toLocaleLowerCase());//hello world


              
        e.trim()去除空格

           var str = "hello world"
           trimleft();去除左空格/trimright();去除右空格·
           console.log(str.trim()); 去除全部空格//helloworld 

51. 包装类

    var n1 = new Number(123);
    var s1 = new String('aaa');
    var b1 = new Boolean(true);
    console.log(typeof(n1),typeof(s1),typeof(b1));//object

52. 数据结构(堆和栈)

    堆栈(内存)空间分配:
    
     (1) 栈stac

               由操作系统自动分配释放存放函数的参数值,局部变量的值

               简单数据类型(值类型:number、string、Boolean、undefined、null)存放到栈内存里面(栈里开辟空间存放值,变量名指向栈里的对象)

              原则:后进先出,进栈:push,出栈:pop(尾进尾出)(进栈:unshift,出栈:shift(头进头出))
    
     (2) 堆

          一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收

         复杂类型(引用类型:array、 function、object)(对象)存放到堆里面     (变量名先指向栈里存放的地址/引用,地址再指向堆里的值)

         push-pop(尾进尾出)

      堆:一块存储空间,没有任何原则 
    
    栈:    
    push-pop(尾进尾出)  

      var arr = ['a','b','c'];
      console.log(arr.join(','));
      arr.push('z');
      console.log(arr.join(','));//['a','b','c','z']
      console.log(arr.pop());
      console.log(arr.join(','));//['a','b','c']

  
    unshift-shift(头进头出)

     var arr = ['a','b','c'];
     console.log(arr.join(','));
     arr.unshift('z');
     console.log(arr.join(','));//['z','a','b','c']
     console.log(arr.shift());
     console.log(arr.join(','));//['a','b','c']


      
      队列queue:原则:先进先出
      push-shift(尾进头出)

        var arr = ['a','b','c'];
        console.log(arr.join(','));
        arr.push('z');
        console.log(arr.join(','));//['a','b','c','z']
        console.log(arr.shift());
        console.log(arr.join(','));//['b','c','z']


    unshift-pop(头进尾出)

        var arr = ['a','b','c'];
        console.log(arr.join(','));
        arr.unshift('z');
        console.log(arr.join(','));//['z','a','b','c']
        console.log(arr.pop());
        console.log(arr.join(','));//['z','a','b',]

 
    栈的应用    ://6.1动手实验(暂时看不懂,以后研究)
例题:a = '2+3*5-4' ,应用四则运算,先乘除后加减,数0-9,+-*/没有括号,不调用系统解释器

思路:
      算法思路:
             不同优先级,右侧操作符优先级高于左侧,则右侧优先
             不同优先级,左侧操作符优先级高于右侧,则左侧优先
             相同优先级,左侧优先

        
      软件工程思路:
        (1)测试用例

            2+3*5-4
            1+2+3+4
            1*2+3*4/5-4/2
            1+2


        (2)debug的工具和手段(Debug、log)
    //栈:push-pop(后进先出)    

    var nArray = [];
    var oArray = [];            
                
    var nRet = 0; 
    //first number
    var sN Token = x.charCodeAt(0) - 48;
    

    栈和堆

    var a = 5;//key是变量名a, value就是5
    var arr = [];//key是变量名arr,value是[]的地址/引用 


    栈内存中的对象,有一个引用计数
    GC:垃圾收集,内存回收机制,MC,COM---(谁的引用数为0,就摧毁谁)
    GC时间:堆内存达到一定使用门槛或定期
    当代码运行到栈内变量的作用域之外时,变量将被摧毁,如果变量被摧毁,引用数减1,如果变量被赋值,指向其他值变量或引用变量,引用数减1
    循环引用:变量将永远不会被摧毁

                                 var a1 = [];
                                 var a2 = [a];
                                 a1[0] = a2;
                                 a2[0] = a1;

    var a = 5;
    var b = a;
    var arr = [];
    var arr1 = [];
    var s ='abc';


    栈内存:

    ST001:a,5
    ST002:b,5
    ST003:arr,HP001
    ST004:arr1,HP001
    ST005:s,'abc'

 
    堆内存

 HP001:[]

53. 特殊字符

\r\n 字符表示换行(文件都是一行的,编辑器为了照顾人类感受,见到\r\n,显示为换行)
\r 0x0d CR carrage return 回车
\n 0x0a LF line feed 换行

    转义字符
           如果在字符串中涉及到一些特殊字符如“\” “'” “""” 等,这些字符无法直接使用,需要采用转义字符的方式。 

           \b 退格符
           \t 水平制表符(空格)
           \f 换页符
           \n 换行符
           \r 回车符
           \' 单引号
           \" 双引号
           \\ 反斜线

54. 编码与解码

   编码:用户输入字符,计算机记录对应二进制的值

   解码:计算机根据记录的二进制值,显示为人类课认识的字符图像

   字符集:是一个系统支持的所有抽象字符的集合

   字符编码:字符集的编码规则

   常见字符集:

           ASCLL字符集

           GB字符集族:
              GB2312、GBK、GB18030

            Unicode字符集族:
              UTF-8、UTF-16、UTF-32

            USC字符集族:
              USC-2、USC-4

55.  json

       json指的是javascript对象表示法

       json对象
               { }中书写
               名称/值对,"key":'value'

        json数组
                [ ]中书写
                对象间,用逗号分隔

    json字符串

   var strJSON='{"name":"ALbad",\n'+'
                    "age":"25"}';
    console.log(strJSON);


      string-->Object
        (1) evel() 自己产生一个string当做js脚本,交由js引擎运行

 var strJSON2 = '('+ strJSON +')';
            console.log(strJSON2)
            var obj1 = eval(strJSON2);


        (2) JSON.parse()

   var obj2 = JSON.parse(strJSON);


        (3) $().parseJSON() 

    var obj3 = jQuery.parseJSON(strJSON);

  
       Object-->string
         (1) JSON.stringify()     

     var strJSON3 = JSON.stringify(obj1);
                   console.log(strJSON3);


            (2) jQuery.toJson()

     var strJSON4 = jQuery.toJson(obj1);
                   console.log(strJSON4); 


    练习1:把一张九九乘法表放入json,然后解析

  {
              '0':['1x1=1'],
              '1':['1x2=2','2x2=4'],
              ...
          }
        var ONNTable = {};
        for (var i = 1;i <= 9;i++){
            var line = [];
            for(var j = 1;j <= i;j++){
                var str = i + 'x' + j + '=' + (i*j);
                line.push(str);
            }
            ONNTable.[i-1] = (line);
        }
    var sNNTable = JSON.stringify(ONNTable);
        
    var jsonTable = JSON.parse(sNNTable);
    for(var x in jsonTable){
        var line = jsonTable[x];
        for(var y in line){
            var text = line[y];
            console.log(text);
        }
    }

46. 正则表达式

        用于匹配字符串中字符组合的模式(正则表达式也是对象)

    正则表达式的创建:

     (1)正则表达式类 RegExp(exp,param)

 var regExp = new RegExp(/[0-9]+/,'g');//正整数
    //[ ]指代一个字符,里面的字符表示被指代的字符的选择范围
    //+ 表示前面的字符,1次或者1次以上
    //g 代表global,全局
    var str1 = '123a123';
    console.log(str1.match(regExp));\
    
//在match这个函数里
                     g,匹配所有的字符串
                     没有g,匹配第一个然后停止

    (2)直接量(通过字面量创建)(用两个撇斜杠,/expression/param)

    var regExp2 = /[0-9]+/g;
       string对象的match:

    console.log(str1.match(/[0-9]+/g));
    console.log(str1.match(/\d+/g));
    console.log(str1.match(/123/g));只匹配123,不重复
    console.log(str1.match(/(123)+/g));匹配123,至少循环一次,允许重复


       RegExp对象的test方法:用来检测字符串是否符合正则表达式的规范

    var regExp2 = /[0-9]+/g;
    console.log(typeof(regExp2));//object
    console.log(regExp2.test(str1));//true(能匹配上则返回true,否则返回false)


57. 正则表达式详解

      ^表示以什么开头,$表示以什么结尾

    (1)简单类

            单词本身

               var str = 'hello world!';
               console.log(str.match(/hello/g));


    (2)范围类

            [ ]指代一个字符,内部指出字符的范围

                [0123456789] [0-9] [a-z] [A-Z]
                十六进制 [0-9a-fA-F]


    (3)负向类

              [^0-9]//^在括号里面表示取反,表示不能是数字,排除数字        

             str = '546456;adfar145;Bz4156;';
             console.log(str.match(/[0123456789]/g));//等价
             console.log(str.match(/[0-9]/g));//等价
             console.log(str.match(/\d/g));//等价
             console.log(str.match(/[0-9][0-9]/g));//匹配字符串中的两位数


    (4)量词一个前面单位出现的次数

            {n} //出现次数
        console.log(str.match(/[0-9]{3,4}/g));
            {m,n} //至少m次,至多n次
            {m,} //至少m次,至多不限


        贪婪量词:? + * //找到匹配的最大串
         

             ? //0次或者1次 = {0,1}
            + //1次或者多余1次 = {1,}
            * //0次或者多余0次 = {0,}


        惰性量词:

*? +?  //找到匹配的最小串  

  
    (5)通配符 预定义类

       [^\n\r] //除了回车换行以外,都可以匹配
       \d = [0-9] //数字
       \D = [^0-9] //非数字
       \w = [a-zA-Z_0-9] //数字、字母、下划线
            变量名:/[a-zA-Z_]\w*/  //变量名只能是字母数字和下划线且不能以数字开头
         \W = [^a-zA-Z_0-9] //非数字、字母、下划线
        \s = [\t\n\x0B\f\r] //空格或者空白
        \S = [^\t\n\x0B\f\r] //非空格或者非空白
        \b //表示边界(两个字符中间的位置)一边是\w,另一边是\W
        \B //不是边界
        ^  //表示开始
        $  //表示结束


    
    (6)正则表达式参数/表达式/[switch](switch也称为修饰符,按照什么样的模式来匹配,有三中值)
       g : 全局匹配(不会出现匹配到第一个值就停止继续往后匹配的情况)
       i : 忽略大小写
       gi : 全局匹配+忽略大小写
    
    (6)分组
           一个正则表达式,不但可以对整个匹配进行操作,还可以对()中的子串进行匹配分组

     (pattern) 匹配 pattern 同时捕获结果,自动设定好组
      \1 RegExp.$1   :反向引用
     \k       :反向引用
      (?pattern) 匹配pattern同时捕获结果,设定name为组名
        str = 'mom and dad';
        console.log(str.match(/mom( and dad)?/))
        console.log(regExp.$1);
        str = 'word excel excel hello word word!';
        console.log(str.match(/(\b[a-zA-Z]+\b)\s+\1/g));//excel excel     word word
        console.logstr.match(/(?\b[a-zA-Z]+\b)\s+\k/));


        零宽(正负向)先行/后行断言
               零宽(正负向)先行/后行:如通配符,不占用字符宽度//正向:是    负向:非
               断言:判断是否符合要求进行匹配

        str = 'reaaa;rcaaa=bbb;';

        //零宽先行断言(?<):寻找四个字符,以ea开头
        console.log(str.match((/(?<=ea).{4}/g);
        //零宽后行断言(?):寻找两个字符,两字符以分号结尾
        console.log(str.match(/.{2}(?=;)/g));
        //零宽负向先行断言(

    (7)或 |
    str = 'var aaadf1';
    str2 = 'function f(){}';

console.log(str.match(/^var\s+\[a-zA-Z]\w*;|^funxtion\s+\/[a-zA-Z]\w*\s*\(\))\{\};);
console.log(str2.match(/^var\s+\[a-zA-Z]\w*;|^funxtion\s+\/[a-zA-Z]\w*\s*\(\))\{\};);

 
    (8)匹配:

 匹配手机号   /^1[34579]\d-?\d{4}-?\d{4}$/;//137-4561-1546
 匹配邮箱号   /^[\w\-\.]+@[\w\-]+(\.[a-zA-Z]{2,5}){1,3}$/; //[email protected]
 匹配整数     /^[+-]?\d+$/; //-1
 匹配浮点数   /^[+-]?\d+(\.\d+)?([Ee][+-]?\d+)?$/;  //1.2E5
 匹配中国汉子 /^[\u4e00-\u9fa5\uff0c\u3002]+$/; //中文。

58. String支持的正则函数

        (1)search(regExp) 直接量和对象,返回整数,即开始的位置,-1表示没有找到
                       g :search不支持全局搜索,直接忽略参数g,同时忽略regExp的lastIndex

  str = 'I word excel word ok';
                console.log(str.search(/\b word \b/));//2
                console.log(str.search(/\b worda \b/));//-1

    
        (2)match(regExp) 直接量和对象
                      没有g:返回数组,0:第一个匹配的最大串,其他是分组的子串;index:最大串开始的位置;input:原始的串
                      有g:  返回数组,所有匹配的最大串,但是没有分组的子串;index和input无效

 console.log(str.match(/\b excel \b/));
                console.log(str.match(/\b excel \b/g));

     
        (3)replace(regExp/substring,replacement)
                regExp:直接量,对象,substring:子串
                replacement:替换进去的串,或者函数
                        //   $1-$99:分组,
                        //   $&:代表全部子串,
                        //   $`:子串左侧
                        //   $':子串右侧
                把小写变成大写:

 str = 'I word excel word ok';
 console.log(str.replace(/\b word \b/,'WORD'));
     等价于  
 console.log(str.replace('word','WORD'));


        全部替换

console.log(str.replace(/\b word \b/g,'WORD'));

     
        颠倒位置:

   str = 'aaa-bbb cc-ddd';
   console.log(str.replace(/([a-z]+)-([a-z]+)/g,'$2-$1')) //bbb-aaa ddd-cc

      
        (4)split(separetor,hoemany) //字符串分割成数组
                separetor:正则表达式/字符串,

       str = 'I word excel word ok';
            console.log(str.split(/\s+/));
            console.log(str.split(/\s+/,4));
            console.log(str.split(''));

 
        (5)regExp test() //返回true是否匹配

            str = 'I word excel word ok';
            console.log(str.test(/\b word \b/.test(str)));//true


        (6)regExp exec() //返回数组,找不到:null
                        没有g: 数组的0位:最大匹配串,后面是数组
                               index:开始匹配的位置
                               input:原串
                        有g  :lastIndex中放入子串结束位置的下一位,每次调用后移

  str = 'I word excel word ok';
            var regExp2 = /\b word \b/g;
            regExp2.lastIndex = 6;
            var aRst = regExp2.exec(str);
            console.log(aRst);
            console.log(regExp2.lastIndex);//17

59. Web API

      浏览器提供的一套操作浏览器功能和页面元素的API(接口),包括BOM 和DOM

60. DOM

       文档对象模型,是w3c组织推荐的处理可扩展标记语言的标准编程接口

      (有了这些DOM接口就可以改变网页的内容,结构和样式),DOM把所有内容看作对象,即文档对象模型

 *文档:一个页面就是一个文档,DOM中用document表示(document对象:console.log(window.document);)
 *元素:页面中所有的标签都是元素,DOM中用element表示
 *节点:网页中所有内容都是节点(标签,属性,文本,注释等),DOM中使用node表示


        获取元素:文档页面从上往下加载,得先有标签才能获取,因此script语句写在标签下面
        
            (1) console.dir(); 打印返回的元素,更好的查看里面的属性和方法

 Var p1 = document.getElementById('c1');
                console.dir(p1);


            (2) 根据ID名获取element元素

   getElementById(string);//id名 返回一个匹配ID的元素
            Var p1 = document.getElementById('c1');
            console.log(p1);


            (3)根据class类名获取element元素(h5新增,IE9以下不支持)

               a. getElementsByClassName(string);//class名 返回获取过来的所有满足条件元素的集合,以伪数组的形式存储

  Var p2 = document.getElementsByClassName('c2');
            console.log(p2);


               b. element.classList 返回元素的类名(返回多个以数组的形式)

  console.log(div.classList);


                  添加类名:element.classList.add('类名'); //不会覆盖以前的类名

 div.classList.adddd('two');


                  切换类名:element.classList.toggle('类名');//有就删除,没有就加上,即从无到有,从有到无变化            

  btn.addEventListener('click',function(){
  div.classList.toggle('bgc');//点击一下添加bgc的类名,再点击一下取消类名
                          })


                  删除类名:element.classList.remove('类名');

        div.classList.remove('one');


            (4)根据标签名TagName获取element元素

               getElementsByTagName(string)//标签名 返回获取过来的所有满足条件元素的集合,以伪数组的形式存储

   Var lis = document.getElementsByTagName('li');
              console.log(lis);
              console.log(lis[0]);//返回指定的一个
              for(var i = 0; < lis.length; i++){//遍历每一个符合的标签元素
                  console.log(lis[i]);
              }

     
            (5)根据标签名Name获取element元素

  getElementsByName(string)//返回数组 ,name属性只对部分元素有效(form表单、img、ifram)
  Var inputs= document.getElementsByName('c4');
  console.log(inputs);


            (6) 

              querySelector() //返回指定css选择器的第一个元素
              var firstbox = document..querySelector('.box')
              Var p5= document.querySelector('#c5').style.color = 'red';

   
            (7)

              querySelectorAll() //返回指定css选择器的所有元素
              Var s= document.querySelectorAll('form input');
              console.log(s); //输出所有的form下所有的input元素
              s[0].style.color = 'green';//form下的第1个input内容颜色为绿色
              s[2].style.color = 'red';//form下的第3个input内容颜色为红色

         
            (8)获取特殊元素

                a.获取body元素

   document.body //返回body元素对象

  
                b.获取html元素

  document.documentElement //返回html元素对象

61. DOM 增删替 (操作元素)

            (1)增加:

                   a. 创建节点:document.createElement('p')

                       添加节点:
                           appendChild(父亲元素把儿子元素放到所有当前儿子元素的最后)
                           insertBefore(要添加的节点,添加到谁的前面)(父亲元素把儿子元素放到指定元素的前面)

 var p1 = document.createElement('p');//生成一个p标签(element)
 var txt1 = document.createTextNode('aaa');//生成一个aaa的节点
 p1.appendChild(txt1);//将aaa挂载到p标签下
 document.body.appendChild(p1);//将p标签挂载到html的body标签下所有子元素的最后
  var p2 = document.createElement('p');//生成一个p标签(element)
  var txt2 = document.createTextNode('bbb');//生成一个bbb的文本节点
  p.appendChild(txt2);//将aaa挂载到p标签下
  document.body.insertBefore(p2,p1);//将p标签挂载到html的body标签下p1标签的前面

      
                    复制节点(克隆节点):node.cloneNode() 
                             括号为空或者里面是false,则执行浅拷贝,只复制标签,不复制里面的内容
                             括号里为true,则执行深拷贝,同时复制标签和里面的内容

    var li = ul.children[0].cloneNode(true);
                             ul.appendChild(li);


                    b.document.write 直接将内容写入页面内容流,但是页面文档流执行完毕再调用,则他会导致页面全部重绘(即重新绘制了一个新页面,之前的内容不存在) //不常用                  

  document.write('
123
')


                    c.innerHtml  //本质上是拼接字符串,当大量创建时效率会降低,但如果用数组方式拼接效率反而会比ceratElement更高                   

   div.innerHtml = '123'


                      数组形式拼接(解决效率低问题)
                      

var arr = [];//声明一个新数组
for (i = 0; i<= 100; i++ ){ //循环
arr.push('123');//将超链接字符串放到数组中
                      }
div.innerHtml = arr.join('');//将数组转化为字符串形式复制给div

                  
            (2)删除:

            removeChild (父亲删除儿子--不是不存在,只是不显示)


                var p3 = document.createElement('p');//生成一个p标签(element)
                var txt3 = document.createTextNode('bbb');//生成一个aaa的节点
                p.appendChild(txt3);//将aaa挂载到p标签下
                document.body.removeChild(p3)//html的body标签下p3标签
       等价于   p3.remove();//删除html的body标签下p3标签


        
           (3)替换:

            a. replaceChild (将后面父亲元素替换成前面的父亲元素)   

var p4 = document.createElement('p');//生成一个p标签(element)
var txt4 = document.createTextNode('bbb');//生成一个bbb的节点
p.appendChild(txt4);//将aaa挂载到p标签下
document.body.replaceChild(p4,p3)//将p3标签替换成p4标签


            b. node.innerText   //所见即所得,不识别html标签(非标准),可读写,会去除空格和换行      

   console.log(p.innerText);
   p.innerText = '


            c. elment.innerHTML //会转译,识别html标签(w3c标准),可读写,保留空格和换行

  console.log(p.innerHtml);
  p.innerHTML = '

 
            d. node.textContent  //所见即所得  

   p.textContent = '


            e. element.setAttribute

  p.setAttribute('class','cls2');//将p标签的class名设置为cls2


            f. element.getAttribute        

 console.log(p.getAttribute('class'));//得到p标签的class名


    案例:动态生成表格:

    
        
            
                
                
                
                
            
        
    
        
    //          
    //            
    //            
    //            
    //            
    //        
    //        
    //                           
    //                           
    //                           
    //                           
    //        
    //        
    //                           
    //                           
    //                           
    //                           
    //        
    //        
    //                           
    //                           
    //                           
    //                           
    //         
    
        
    
姓名学号成绩操作
李星云20190500640190删除
萧炎20190500640292删除
石昊20190500640394删除
张小凡20190500640496删除
  

62. 操作Element元素的属性

   (1)修改图片元素属性

      a.修改图片元素属性src

 img.src = '图片的链接地址';-


      b.修改图片元素属性title

   img.title = '刘德华';


    (2)修改表单元素属性

       a.修改表单元素属性value

 input.value = '请输入内容';


       b.修改表单元素属性disabled(禁用)

      button.onclick = function(){
          this.disabled = true;//this指向的是事件函数的调用者button  
       }


        c..修改表单元素属性type(文本类型)

    input.type = 'password';
        input.type = 'text';


    (3)修改样式属性:Element.style(产生的是行内样式,权重较高,属性采取驼峰命名法)

       a.修改backgroundColor

     div.onclick = function(){
                 this.style.backgroundColor = 'pink';//this指向的是事件函数的调用者div 
       }  


       b.修改显示/隐藏

         button.onclick = function(){
                 div.style.disply = 'none';//盒子隐藏
       }  


    案例:修改精灵图背景

   var lis = doucument.querySelectorAll('li'); //获取所有的li元素
       for (var i = 0; i < lis.length; i++){//遍历每一个li元素
            var index = i * 44; //44是精灵图每个图片的大小(竖向排列是高,横向排列是宽)
            lis[i].style.backgroundPosition = '0 - ' + index + ' px';
       }


       
    案例:文本框获得焦点时隐藏内容(onfocus 获得焦点/onblur 失去焦点)

         var input = doucument.querySelector('input'); //获取文本框
         txt.onfocus = function(){//获得焦点时
            if(this.value === '手机'){
                input.value = '';
            } 
            this.style.color = #333 ;
         }
         txt.onblur = function(){//失去焦点时
             if(this.value === ''){
                 input.value = '手机';
             } 
         }
 


    (4)修改Element元素名

        a.修改元素的className //直接更改元素类名,会覆盖原先的类名(如果样式修改较多可用这种操作)

 div.className = 'change';
 div.className = 'first change';//多类名选择器,可保留原先的类名


    (5)排他思想:tab标签切换,点击谁谁的样式改变,且始终只有一个元素样式改变了

       案例:

 var btns = document.getElementByTagName('button'); //获取所有的按钮元素
 for (var i = 0; i < btns.length; i++){//遍历所有的按钮元素
    btns[i].onclick = function(){
       for (var i = 0; i < btns.length; i++){//遍历所有的按钮元素
         btns[i].style.backgroundColor = ''; //先把所有button背景颜色去掉
  }
    this.style.backgroundColor = 'pink';//再设置当前元素的背景颜色
          }
               
    }


        (6)获取元素属性值

           a.Element.属性(只能获取内置属性值)

   console.log(div.id);//box
   console.log(input.checked);//true/false


           b.Element.getAttribute('属性')(还可获取自定义属性值) 

console.log(input.getAttribute('index'));

  
           c.Element.dataset.属性(h5新增获取自定义属性)
          

  console.log(input.dataset.index);
  console.log(input.dataset[index]);


              
        自定义属性:为了保存并使用数据,有些数据可以保存到页面中而不用保存到数据库中
             设置h5自定义属性:以属性data开头作为属性名并且赋值

 

  
        (7)设置元素属性值

           a.Element.属性 = '值';(直接赋值)

  div.id = 'box';


           b.Element.setAttribute('属性','值’)(主要针对自定义属性)  

 console.log(input.setAttribute('index',2));

   
        (8)移除属性 Element.removeAttribute('index');

        案例:全选与取消全选(全选按钮选中状态,则下面所有其他按钮都是选中状态,反之亦然,但只要下面的其他按钮至少有一个不是选中状态,全选按钮就是未选中状态)
        

var checkAll = document.getElementById('checkAll');//获取全选按钮(复选框)
var checks = document.getElementById('checkbody').getElementByTagName('input');
                                                              //获取下面所有复选框
            checkAll.onclick = fuction(){
                for (var i = 0; i < checks.length; i++){//遍历其他所有复选框
                     checks[i].checked = this.checked;
                                        //把所有复选框改为全选按钮的选中状态
                }
            }
            
            for (var i = 0; i < checks.length; i++){//遍历其他所有复选框
                 checks[i].onclick = function (){ //给下面所有复选框遍历都添加点击事件
                     var flag = true;//控制全选按钮是否被选中
                     for (var i = 0; i < checks.length; i++){ 
                                          //在遍历一遍看是否有至少一个没被选中
                         if(!checks[i].checked){
                             flag = false;
                         }
                     }
                     checkAll.checked = flag;
                 }
            } 


63. 操作Node节点

      节点至少拥有nodeType(节点类型),nodeName(节点名称),nodeValue(节点值)这三个基本属性

           元素节点nodeType为1 (最常用)
           属性节点nodeType为2
           文本节点nodeType为3(包含文字,空格,换行等)


    (1)parentNode 父节点 (得到离元素最近的父节点,找不到则返回null)

 console.log(li.parentNode);


    (2)

       a. children 子节点(获取所有子元素节点,比骄常用)

        console.log(ul.children);
        console.log(ul.children[1]);//ul里的第二个子元素
        console.log(ul.children[ul.length-1]);//ul里的最后一个子元素


         b. childNode 子节点(得到包含文本在内的节点,不常用)

 console.log(ul.childNode);


    (3)

         a.  nextElementSibling 兄弟节点(返回当前元素下一个兄弟元素节点,找不到返回null) //IE9以下不支持

  console.log(nav.nextElementSibling);

  
        b.  previousElementSibling 兄弟节点(返回当前元素上一个兄弟元素节点,找不到返回null)

     console.log(nav.previousElementSibling);

64. 弹窗

    function clk1(){
        window.alert('我是警告框');
    }
    
    function clk1(){
        var r = prompt('提示文字','输入的内容');//输入框,输入的内容会返回控制台
        return r;
    }
    console.log(r);
    
    function clk1(){
        var r = window.confirm('提示文字');//确认对话框,确定或取消,会返回true或false回控制台
        return r;
    }
            console.log(r);

65. HTML DOM 事件

    事件由三部分组成:事件源(被触发对象(按钮)),事件类型(如何触发(点击onclick)),事件处理程序(通过函数赋值完成)

  var d = document.getElementById('button'); //获取事件源
                    d.onclick = function(){ //绑定/注册事件
                        console.log(我被点击了); //添加事件处理程序
                    };


        (1)鼠标事件

        onclick              当用户点击某个对象时调用的事件句柄。    
        oncontextmenu        在用户点击鼠标右键打开上下文菜单时触发     
        ondblclick           当用户双击某个对象时调用的事件句柄。    
        onmousedown          鼠标按钮被按下。    
        onmouseenter         当鼠标指针移动到元素上时触发(鼠标只是经过自身盒子触发)    
        onmouseleave         当鼠标指针移出元素时触发    
        onmousemove          鼠标被移动。    
        onmouseover          鼠标移到某元素之上(鼠标经过自身盒子触发,经过子盒子还会触发)。    
        onmouseout           鼠标从某元素移开。    
        onmouseup            鼠标按键被松开。   


        (2)键盘事件

         属性             描述    DOM
        onkeydown     某个键盘按键被按下。    
        onkeypress    某个键盘按键被按下并松开。    
        onkeyup       某个键盘按键被松开。

  
        (3)框架/对象(Frame/Object)事件

         属性                         描述    DOM
        onabort               图像的加载被中断。 ( )    
        onbeforeunload        该事件在即将离开页面(刷新或关闭)时触发    
        onerror               在加载文档或图像时发生错误。 ( , 和 )   
        onhashchange          该事件在当前 URL 的锚部分发生修改时触发。     
        onload                一张页面或一幅图像完成加载。    
        onpageshow            该事件在用户访问页面时触发    
        onpagehide            该事件在用户离开当前网页跳转到另外一个页面时触发    
        onresize              窗口或框架被重新调整大小。    
        onscroll              当文档被滚动时发生的事件。    
        onunload              用户退出页面。 (  和 )  
  


        (4)表单事件

         属性               描述    DOM
        onblur        元素失去焦点时触发    
        onchange      该事件在表单元素的内容改变时触发( , ,