zoukankan      html  css  js  c++  java
  • javascript高级程序设计学习笔记

        javascript高级程序设计,当枕头书已经好久了~zz  现在觉得自己在js的开发上遇到了一些瓶颈,归根究底还是基础太薄弱,所以重新刷一遍js高程希望有更新的认识。

    一、javascript简介

      1、ECMAScript 版本规范

      2、DOM 文档对象模型

      3、BOM 浏览器对象模型

    二、HTML中应用script

      1、<script>标签

        属性:async="async" / defer="defer"

          异步脚本:async:立即下载脚本,对外部脚本有用。在lode事件之前执行,因为异步所以执行没有先后顺序。

          延迟脚本:defer:文档加载完成后执行,对外部脚本有用,。可以立即下载,但是要延迟执行,所以这个脚本文件是可以放到<head>里的。

      2、文档模式:标准模式  /  混杂模式

      3、<noscript></noscript> :当页面禁用script脚本时的一个解决方案,只有被禁用时会显示标签里的内容。(平稳退化思想)

    三、基本语法

      1、语法格式

          a、区分大小写,首字母小写,驼峰式写法。

         b、严格模式。在代码顶部添加“use strict”。

        c、标识符:规定变量、函数、属性的名字首字符必须是字母、下划线、$。

       2、变量*(用于保存值的占位符)

          !!如果在函数中定义一个变量,那么在函数退出后变量失效。省去var所定义的变量将会是全局变量,即使函数退出也可以访问到。

            a、var mood ;var age;等同于var mood,age;(中间用逗号分隔)

            b、var mood ="happy";var age = 10;等同于var mood="happy",age=10;(这个注意一下)

          在论坛上看到一句话,所有的变量都是对象的属性,好比全局对象window,所创建的全局变量就是window的属性

       3、数据类型

        a、五种简单类型;Undefined、Null、Number、String、Boolean。一种复杂数据类型:Object;

        b、typeof鉴别数据类型。/** typeof(变量名) ??typeof是关键字不是方法 写法:alert(typeof(123));alert(typeof h);   

        c、undefined(未定义)是null(空)的一个派生值     

    alert(undefined == null) // true

        d、boolean值。true / false 。

        e、number

          1、浮点数值(带小数点的值,一些小数里的极大值极小值,用e来代替)

          2、NaN:不是数值。

            a、本来要返回一个数值的然后没有返回应该返回的,就会抛出一个错误(NaN)

            b、alert(NaN == NaN);会返回false

            c、用isNaN()方法来辨别是否是数值.

          3、数值转换*把非数值转化成数值,三种方法:

            a、Number();转型函数,可以用于任何数据类型       

     例:var num1 =  "hello world!" ;  Number(num1);// NaN
       var num2 = NaN;  Number(num2);//0
       var num3 = 00000033;  Number(num3);//33
       var num4 = "123"; Number(num4);//123
       var num5 = " "; Number(num5);//0
       var num6 =true;  Number(num6);//1
       number(undefined); // NaN
       number(null);//0 

            b、parseInt():最常用,用于字符串的转化       

    例:var num1 = “hahha1234”;  parseInt(num1);//1234
      var num2 = " ";  parseInt(num2) ;//NaN
      var num3 = "22.5";  parseInt(num3);//22
      parseInt("70");//70

                十六进制转化:parseInt("AF",16);//156  (指定了参数,这种写法可以用在其他数值上,用来化解进制的转化)

            c、parseFloat();用于字符串的转化

              区别:和parseInt()相比较,parseFloat()解析到浮点数的第二个小数点就会停止解析。其次,它还是还是会忽略前导0,它只能解析十进制的数,十六进制之类的会化成0,所以也就没有基数参数一说。         

    例:parseFloat("22.34.22");//22.34
        parseFloat("0XA");//0

        f、String字符串

          1、把一个值转化成字符串:toString(); (例如toString(16);输出16进制的字符)。

          2、String();(在不确定所转化的值是否是null或者undefined,用这个方法,应为这两个值没有toString()方法)。

        g、Object类(所有对象的基础)

          1、首次引入对象的概念,对象说白了就是一组数据和对应功能的集合,可以通过new操作符后跟一个对象类型名称来创建。

            例:创建一个object类型的自定义对象,同样的讲object类型是所有实例的基础,object所具有的方法属性也都存在于其他实例中。

                var obj = new object(); //如果不传递参数,省略圆括号也没有错,但是不推荐。

            a、检查一个对象是否有某个属性:hasOwnProperty(propertyName),它的参数就是一个属性名,但是这个属性名必须用字符串来表示,就是说要加引号。

            b、toPrototypeOf(object);用于检查传入的对象是不是另一个对象的原型。

            c、propertyIsEnumberable(propertyName);用于检查给定的属性是否可以使用for-in语句。和hasOwnProperty()用法一样。

            d、toLocaleString();返回对象的字符串表示,和toString()一个意思。

            e、valueOf();返回对象的字符串、数值或布尔值表示。之后的大多继承转字符串方法来自这里。

            !!!那么问题来了toString()和toLocaleString()和valueOf()的区别在哪?

              答:这三者都是返回字符串。valueOf()方法最好理解,它是输出这个对象本身的值(属性值,内容)。

                toString(获取的是传统字符串),使用这个是保险的(推荐),他不会应为本地环境的改变而出现错误。

                toLocaleString(获取的是本地环境字符串),如果要返回时间类型的数据推荐使用这个。

          2、dom和bom属于宿主对象,它的功能是由宿主提供的。

      4、操作符

        1、一元操作符(操作一个值的操作符)

          a、递增和递减操作符。(++ / --)       

    例:var age = 30; ++age = 31; --age = 29;    //前置操作符
          var age = 30; age++ = 31; age-- = 29;    //后置操作符
          var num = 30;
          var numAll = --num + 1;
         alert(num);//29
         alert(numAll);//30    

           后置操作符与前置操作符有个非常明显的区别,就是它是在求值之后在执行的。     

    例:var num1 = 2;
          var num2 = 30;
          var numAll = num1++  + num2;
          alert(numAll);//32
          alert(num1 + num2);//33   

           b、这四个操作符对任何值都适用,但是在不同数据类型下又有不同使用方法。    

             例:var a = "2";
                var b = "z";
                var c = false;
                var d = 1.1;
                var e = {
                  valueOf:function(){
                    return -1;
                  }
                };
    
              应用操作符之后:
    
                a++; //3(数字类型字符串需先转化数字,在递加递减)
                b++; //NaN(对于不包含数字的字符串,转化成NaN)
                c++; //1(布尔值:true:1; false:0;在这个基础上递加递减)
                d--; //0.1000000000000000......
                e--; //-2(对于对象的加减值,先调用valueOf()在执行加减,但是如果数值是NaN,需要调用toString()方法在执行加减法)

            c、一元加和减操作符。

              + - 对应数值正常加减,如果是对应非数值的数据加减,就有不同结果了,和递加递减类似需要转化为数值在执行运算,如果是对象需要调用valueOf();或者toString();在执行运算。        

     例:var a = "1";//  +a 结果是1;转化成数字后在计算。
    var b = "1,1"; // +b结果是1.1;原理同上。
    var c = “z”; // +c是NaN;
    var d = false;// +d 是0;
    var e = NaN;// 此处存疑
    var f = undefined;// 此处存疑
    var g = {
        valueOf:function(){
            return -1, 
        } // +g是-1.
    } ;    

              对于减操作符,就是转化为负数,但是其他数据有不同的结果。

              例:var a = 1; // -a结果就是-1.

                其他数据的减运算同上述加运算类似。

          2、位操作符

          3、布尔操作符

            a、逻辑非。!和!!区别是第二个会将第一个得到的布尔值在取反。

            b、逻辑与。(&&) 

              如果说第一个操作值就可以决定出结果,那么他就不会执行第二个值,例如第一个值是false那么它的值就不会是true。

              1、第一个值是对象,返回第二个操作数。

              2、第二个是对象,那么在第一个值为对的情况下才会执行第二个值。

              3、两个皆是对象,则返回第二个。

              注意在使用逻辑与运算符不能使用未定义的数值,否则会报错,但是有种情况第一个值就能判断false那么第二个值未定义,也不会报错。

            c、逻辑或。(||)

          4、乘性操作符

            a、乘法(*)这节有个Infinity知识点

            b、除法(/)

            c、求模(余数),用一个%来表示

              例:var result = 26 % 25; // 1

          5、加性操作符

            a、加法(+)

              例:var result = 10+10;//20.

             它在不同数据类型下,有不同运算方法:

                1、都是数字,正常加法运算。

                2、其中一个是NaN,结果是NaN。

                3、各种Infinity运算。

                4、如果两个都是字符串,则将两个拼接起来。

                5、如果一个是字符串,将另一个转化为字符串之后在拼接起来。

              忽视加法操作符中的数类型是js运算里一个常见的错误。

             

                    例:var n1 = 5;
                var n2 = 10;
                var n3 = "hello world!"
                alert(n3+n2+n1); // hello world! 105(输出结果是510而不是15,是应为加法操作是独立执行的这个关系执行了两遍运算,它会首先计算n3+n2的值,组成一个字符串之后在加上n3的值组成一个新的字符串)
                换成这个写法:alert(n3+(n2+n1)),//hello world! 15;(这个的运算顺序是,先将数字运算出来,在将字符串拼接起来)
    

      

            b、减法。

              它所遵循的规则有

                1、皆是数值,正常减法。

              2、其中有一个值是NaN,输出NaN。

              3、+0和+0相减值是+0;

              如果包含字符串,布尔值,null、undefined的减法运算,把它们用number()换算成数值之后在遵循上述方法进行运算,对象的话就调用valueOf()或者toString()方法将其转化之后再运算。

          6、关系操作符(<、>、<=、>=)比较之后都会返回一个布尔值

            同样,它的运算方法有:

              1、如果比较双方是字符串,那么比较它俩的字符编码值。(注意相同字符,大小写不同它的编码值也会不同)

                例:var result = "25" < "3"; // true

                  var result = "a" < 3; // false;因为字符串"a"转化数值的时候转化成了NaN;根据规则,任何数与NaN比较结果都是NaN,

              2、如果一个是数值一个是字符串那么把字符串的那个值转化为数值在进行比较。

          7、相等操作符

            相等和不相等——先转化在比较

            全等和不全等——仅比较而不转换

            a、相等:==

            b、不相等:!=

            undefined和NaN相等,不能将它们转化成其他值比较,如果其中有一个值是NaN,那么所有的比较都不相等,会返回NaN,!!!NaN不等于NaN.

            c、全等:===

            d、不全等:!==

              例: var result1 = "5" == 5; // ture 因为转化后相等

                 var result2 = "5" === 5; // false 因为全等不转化数据类型,类型不同所以不相等

                 null === undefined; // false;类型不一样

              为了保证代码的严谨性,推荐使用全等不全等操作符。

          8、条件操作符

            例:value = num1 ? num2 : num3;

              如果value=num1成立,那么把num2赋值给value,否则赋值num3

              var num = ( num2>num3 )?num1 : num2;

              如果返回true则把num1赋值给num,否则赋值num2;

              !!!现在豁然开朗,原来这个是操作符,我一直以为这是条件语句。

          9、赋值操作符 =

            还有在=号前加乘性加性或者其他操作符,就会组成符合操作符。

            例:var num = 10; num = num+10;num += 10;

            常见:/= ; %=; +=; -=; <<=,(左移/赋值)>>=(右移/赋值)>>>=;

          10、逗号操作符

            逗号操作符多用于声明多个变量,或者赋值

            var num1 = 1,num2 = 2, num3 = 3; 

            var num = (1,2,3,4,5,6); // 最后是把6赋值给了num,不要当成是数组了。

      5、语句

        循环语句

        A、do-while语句

          它是后测试循环语句,意思是先执行while里的语句,再会执行do里的语句,意味着循环必须要执行一次。

          do{

            statement;

          }while(expression); 

                     例:
            var i=0;
            do{
              i += 2;
            }while(i<10);
            alert(i);
            意思是如果i<10,i一直会做+=2的操作,直到i<10;                 

          do-while;语句和while语句在语法上的区别:do-while语句必须用do开始while结束;并且do里的语句用分号结尾,而while里的语句用圆括号括起来语句不用分号结尾。

        B、white语句

          它属于前测试循环语句,在执行循环体内的代码之前就会对出口代码求值,意味着循环体内的代码可能永远都不会被执行(!!!和do-while区别)

          while(expression) statement     

        C、for语句

          固定格式:(!!!固定)

            for( initialize ; test ; increment);//这三个负责初始化,循环判断,变量更新,记住中间一定是两个分号!!!。

              statement   

     例:
             var num = 10;
            for( var  i = 0; i<num; i++ ){
              alert(i);
            }
          以上这个例子等同于:
            var num = 10;
            var i = 0;
            while( i<num ){
              alert(i);
              i++;
            }

          同样的,如果一个循环用for做不到,那么它用while也做不到。for循环只是把代码集中在了一个位置。

          因为ECMAscript没有块级作用域,所以循环内部的值,循环外部也可以访问的到。        

                例:var num = 10;
               for( var i = 0 ; i < num ; i++){
                alert(i);
              };alert(i);//外部的alert(i);会弹出来一个10,外部的代码可以访问到内部的代码。                 

          无限循环:

            for( ; ; ){};  

          如果只给出条件判断语句,实际上就是把for循环转换成了while循环。      

                 例:var num =10;
              var i = 0;
              for( ; i < num ; ){
                alert(i);
                i++;
              } 

        D、for-in语句

          是一种迭代语句,可以进行枚举对象的属性。     

            例:for( var propName in window ){
              document.write(propName);
            }      

            这个式子可以枚举出来window的所有属性,直到把window的属性全部展示出来之后这个循环才会停止。

        选择语句

         A、if条件语句     

        if (content) num1 else num2;(要区别这个式子和之前的条件操作符(带?,:)的区别)
          if( i > 6 ){
            alert(num1);
          }else{
            alert(num2);
          }
    
          更为复杂的方式:
    
          if (content) num1 else if(con1) num2 else num3;(就像是把代码块的花括号去了就行了)
          if ( i >6 ){
            alert("haha");
          }else if( i >4 ){
            alert("heihei");
          }else{
            alert("huhu");
          }  

         B、switch语句

          和if语句关系最为密切,模板:

          switch (expression) {

          case value :statement

          break;

          case value :statement

          break;

          case value :statement

          break;   

           default:statement

          }

          上述模板意思是,case就是每一种情形,如果每种情况下条件符合value,则执行statement语句,break则是跳出当前执行的语句,而如果忽略了break这个值它将会case一直执行下去。最后的default的值是说如果这个式子以上都不符合则执行default里的值。

          实际操作理解是:     

         if(i == 20){
            alert("20");
          }else if(i == 30){
            alert("30");
          }else if(i == 40){
            alert("40");
          ]else{
            alert("50");
          }  

        switch语句就是为了避免程序员写出这样的代码,用switch来写的话:  

       switch(i){
    
          case 20;
    
          alert("20");
    
          break;
    
          case 30;
    
          alert ("30");
    
          break;
    
          case 40;
    
          alert("40");
    
          break;
    
          default :
    
          alert("50");
    
        }

        当然break也不是必须,如果省略一定要添加注释说明。

        例:截取中间一小部分说明

          case 35:

          case 45:

          /**合并两种情况**/

          alert(35 or 45);

          break;

        其中case的值不一定是常量,也可以是变量或者表达式等  

          例;swich("hello world!"){
    
           case "hello" + "world!":
    
           alert("Greeting was found.");
    
                             break;
    
           case "haha":
    
           alert("Closing was found.");
    
              break;
    
           default:
    
                        alert("hahahaha");
    
         }//第一个是对的所以弹出来已找到。

        还有一种情况: 

        var num=10;
    
        switch(true){
    
          case num<0;
    
          alert("错了");
    
          break;
    
          default:
    
          alelt("好好写");
    
        }//循环还可以对外部的变量做操作,参数true是告诉case每次执行返回的都是对,让循环按顺序一直执行下去。
    

         跳转语句    

          A、break和continue语句

          都是用于在循环代码中控制语句的执行,来看看它们的区别;

          break可以跳出任何闭合的语句块。直接跳出,不再执行后面的代码!!!

          var num = 0; 

          for( var i = 0 ; i < 10 ; i++ ){

            if(i % 5){ (求模运算) 

              break;

            }

            num++;

          };alert(num);

        这个num弹出来是4,因为当i循环到5时,if语句成功,执行break语句,跳出循环没有在执行后面的num++,所以num 最后的数是i累加到4时执行后的结果。

        continue:跳出执行那个条件,再继续循环之后的值!!!

          var num = 0; 

          for( var i = 0; i < 10; i++ ){ 

            if( i % 5 ){ 

              continue; 

            } 

            num++; 

          };alert(num);

        这个num弹出来的是8,因为当i循环到5时,执行if里的continue函数,跳出循环后这个式子就不会执行i=5时num++的值,然后再返回循环执行i=6时的num++的值,后面i=9时,num结果是8,当i=10时循环结束。 

        break语句可以和标签(lable)语句联合使用, 返回代码中特定的位置,这种形式多用于循环嵌套的情况下。   

          例:var num = 0 ;outermost;
            for (var i = 0; i < 10; i ++ ){
              for(var j = 0; j < 10; j++){
                if(i == 5 && j == 5){
                  continue outermost;
                }
                num++;
              }
            }
            alert(num); // 95

          B、return:终止函数运行,并返回一个值

        补充语句

          A、lable语句(标签语句)

          在代码中添加标签,为以后使用。     

              例:start :for( var i = 0 ; i < num ; i++){
              alert(i);
            }      

          之后可以使用标签名来调用这个函数。   

         B、with语句:简化对同一个对象的编写过程。    

          例:var eg = location.search.substring(1);
            var hosName = location.hostname;
            var  url = location.href;
            以上是普通的写法,转化成with写法如下:
            with(location){
              var eg = search.substring(1);
              var hosName = hostname;
              var url = href;
            }

            严格模式下,不允许使用with语句,由于with语句在开发环境中难以调试,所以不建议使用with语句。

           异常处理语句

          A、throw:主动抛出异常

          B、try:指明需要处理的代码段

          C、catch:捕获异常

          D、finally:后期处理

      6、函数

        基本语法:

        例:带返回值的函数:

          function sum(num1,num2){

            return num1 + num2;

          }

          调用这个函数:var result = sum(1,2);这个函数在执行完return语句后,后边的语句就不会在执行。

        return 后边不带有返回值,会返回一个undefined,用来提前中断函数执行,但又不需要返回值。其推荐做法是:要么都返回一个值,要么都不返回值,这样方便调试。

        匿名函数:是一个没有名字的方法,没法调用只能赋值给一个变量//window.onload=function(){}

        1、参数:

            函数传递的参数有极大地自由性,每个参数的内部保存机制都是用数组来表示的,可以使用arguments来访问每个参数。

            arguments对象和数组类似,但它并不是Array的实例,应为它可以用[]括号访问到每个参数,还可以用length来访问长度,举例:

              function sayHi(){

                alert("hello" + arguments[0] + "," + arguments[1]);

              }

            从以上重写的例子可以看到,没有在括号里使用参数,但是这个函数的功能并没有发生变化。所以知道在括号里写参数不是必须的,用arguments也可以访问到。

            用arguments的length属性可以访问函数的参数个数:

            例:

              function sayHa(){

                alert(arguments.length);

              }

              调用:

              sayHa(); //0

              sayHa("string",6);  //2

              sayHa(num); //1

            这点可以给开发人员带来的应用场景有(可以让函数接收任意个参数并实现不同的功能):         

             例:
    
                function doAdd(){
    
                  if(arguments.length == 1){
    
                    alert(arguments[0] + 10);
    
                  }else if(arguments.length == 2){
    
                    alert(arguments[0] + arguments[1]);
    
                  }
    
                }
    
                doAdd(10); //20
    
                doAdd(20,30); //50
    

      

              还有一种arguments和参数混合使用的形式:

               

               function doAdd(num1,num2){
    
                  if(arguments.length == 1){
    
                    alert(num1 + 10);
    
                  }else if(arguments.length == 2){
    
                    alert(arguments[0] + num2);
    
                  }
    
                }
    
                //上述例子中,arguments[0]和num1是等价的,所以可以相互转化。
    

      

              关于arguments的用法还有一点很重要,就是它的值永远与命名参数的值保持同步。

                例:

                  

                  function doAdd(num1,num2){
    
                    arguments[1] = 10;
    
                    alert(arguments[0] + num2);
    
                  }
    

      

                  每次执行这个函数都会发生一次重载,会重新写入num2的值,arguments修改了值会反应到命名参数中去,但是它改变的是他们的值,他们的内存空间不会有变化,内存空间是独立的。但是要记住这种改变是单向的,修改命名空间的值是不会改变arguments的值,而且如果只传入了一个值,arguments[1]设置了值也是不会反映到命名空间中去的。

                  还有没有传递值得参数会被赋予undefined的值。在严格模式下对arguments的功能做出了一些限制。

        2、没有重载。就是后面的会覆盖前面的。

     四、变量、作用域和内存问题

      1、基本类型的引用类型的值。(变量声明各种数据类型的知识点)

        基本类型:声明的简单的数据段

        引用类型:对象

        在这里主要探讨引用类型的值

        js是不允许直接操作内存中的位置的,也就是说不能直接操作内存空间,所以,我们能访问且操作到的是它的引用而不是实际的值

        a、保存方式

          操作引用类型的值时,改变、添加或者删除属性和方法。例:

            var person=new object(); //创建对象,并将它保存在person变量中。

            person.name=" cuzz "

            alert(person.name); //" cuzz "

        b、复制基本类型的值

          复制基本类型的值会在新的变量上重新创建一个值,两个变量的值是独立的,之后改变两个变量也不会相互影响。

          例:var num1=2; var num2=num1;

            num2保存了2,它只是num1变量的一个副本,这两者是独立的不会相互影响。

        c、复制引用类型的值

          复制引用类型,复制过来的对象是被复制对象的一个副本。这个副本就是相当于一个指针,这个指针指向的是堆中的一个对象。复制成功后,这两个变量会指向同一个对象,所以改变其中一个变量就会影响另一个变量。这和基本类型的复制机制是背道而驰的。例:

          var obj = new object();

          var obj2 = obj

          obj2.name="hahha";

          alert(obj.nama);//"hahha"

        d、传递参数

        向参数传递引用类型的值,会把这个值在内存中的地址复制给参数,例:

        基本类型值得参数传递:

          

        function person(num){
    
            num +=10;
    
            return num
    
          }
    
          var content = 20;
    
          var result = person(content);
    
          alert(content);//20;
    
          alert(result);//30;
    

      

        引用类型值得传递:

        上面的例子如果传递的是引用,那么外部的变量content也会变成30.

        例:

       

       function addten(num){
    
          num.name="cuzz"
    
        }
    
        var person = new object();
    
        return addten(person);
    
        alert(person.name);//"cuzz"
    

      

        //对象是按值传递的

        以上例子,在函数内部改变了person的属性,在外部访问这个变量结果是同步的,因为person在堆内存中指向的对象只有一个。

        例:

       

       function addten(obj){
    
          obj.name="cuzz";
    
          var obj = new object();
    
          obj.name="jery"
    
        }
    
        var person = new object();
    
        addten(person);
    
        alert(person.name);//cuzz
    

      

        以上例子说明参数的传递是按值传递的,即使在函数内部修改了参数的值,但原始的引用保持未变,当在函数内部重新定义参数时,这个变量引用的就是一个局部变量了,这个局部变量会在函数执行完生成后被销毁,可以把函数的参数想象成一个局部变量

        2、检测类型

          typeof适合检测基本数据类型,但是对于引用类型(对象)或者null 的作用不大。

          所以检测引用类型的对象是什么类型的对象用到instanceof操作符,如果变量是给定引用类型的实例,那么instanceof操作符会返回true。

          所有引用类型的值都是object的实例,所以instanceof检测时会返回true,但是检测基本类型会返回false。

          例:alert(person instanceof object);//person是object的实例吗

        3、执行环境

          全局环境是最外围的执行环境,在web浏览器中全局环境被默认是window对象,所以全局变量或者环境都是依window为对象创建的,某个执行环境在代码执行完成后会被销毁,全局环境会在浏览器关闭的时候被销毁

          内部环境可以访问外部环境但是外部环境很难访问内部环境,内部环境向上搜索至作用域顶端

          例:

           

            var color = “blue”;
    
            function changeColor(){
    
              var anotherColor = "red";
    
              function swapColor(){
    
                var tempcolor =anothercolor;
    
                anothercolor = color; 
    
                color = tempcolor;
    
                //这里可以访问到tempcolor,anothercolor,color
    
              } 
    
              swapColor();
    
              //这里可以访问到anotherColor,color.      tempcolor变量访问不到
    
            }
    
            changeColor();
    
            //这里可以访问到color;   其他的变量访问不到
    
            //因为函数的作用域,是层层向上查找的
    

      

          延长作用域链:

            在作用域链的前端增加一个变量对象。(catch和with语句)

          没有块级作用域

          例:if(true){

              var color = "blue";

            }

            alert(color);//"blue"  if语句里声明的变量会自动添加到当前的执行环境中,也就是全局环境,所以在外部的alert可以访问的到。{}花括号里的代码在外面也是可以访问得。

          有两个注意点:

            1、声明变量:

              使用var 声明的变量会被自动添加到最接近的环境中去,在函数里就是当前的局部环境,在with语句中,就是函数环境,如果没有用var声明就变成了全局变量,但是不建议不声明的做法。

            2、标识符(变量)的查询

              层层向上查找,搜索从一个作用域链的前端开始,如果找到查找结果,会立即停止查找。

        4、垃圾收集

          1、垃圾收集机制:找到不在使用的变量,然后释放其所占用的内存。

          2、情景:局部变量只在函数执行的时候才有用,所以在这一过程中,会为它们在栈内存上分配相应的空间,用来存放它们的值,但是当函数执行完毕后,局部变量就没有存在的必要了,所以这个时候就要释放内存了。

          所以垃圾回收机制要跟踪那个变量有用那个变量没用,给没用的变量做上标记,以便之后回收其占用的内存。标记的方式通常有以下两个策略:

            a、标记清除 b、引用计数(会出现循环引用导致不能清除无用变量的问题,解决办法是手动清除)

        5、性能问题

        6、管理内存

          1、解除引用。只要数据不在引用,就将其值设置为null,解除其引用。       

              例:function createData(name){
    
                var obj = new object();
    
                obj.name=name;
    
                return obj;
    
              }
    
              var createObj=createData("cuzz");
    
              createObj = null;手动解除其占用的内存
    

      

    总结:

        

     

               

    五、引用类型

      对象(引用类型的值)是引用类型的一个实例。新对象是使用new操作符后加一个构造函数创建的(这个构造函数本身就是一个函数)

      例:

        var person = new object(); //这里的object()构造函数它只是为了新对象定义属性和方法。

      1、Object类型

        创建object实例(对象)方法:

          a、var person = new object();

            person.name="cuzz";

          b、使用对象字面量表示法//推荐使用方法

            var person = {name:"cuzz",age:20};//属性名也可以使用字符串

            还有一种情形:

            var person = {}; //表示只保留默认的属性名及方法的对象,与new object()相同  

          

            例: function displayInfo(item){
    
              if(typeOf item.name== "string"){
    
                alert(item.name)
    
              }
    
            }
    
            displayInfo({name:"cuzz"});
    

      

        访问对象的方法,多半是用.来访问,还可以用[]访问对象的属性

        例:alert(person["name"]);和alert(person.name);效果是相同的

          其中方括号的优点是,可以通过属性名的变量来访问。例:

          var num = “name”;

            alert(person[num]);可以用声明之后的变量来访问

      2、Array()类型

        数组类型的每一项都可以保存不同数据类型。

        创建数组:

        1、var person = new Array();//知道它数量:var person = new Array(30);

          包含三个字符串的数组:var person = new Array("cuzz","azxc","qwer");

             也可以省略new 操作符,其效果是相同的。

        2、使用数组字面量表示

          var person = ["cuzz","zxcv","qwer"];//创建了三个字符串的数组

          var number = []; //创建一个空数组

        修改数组:

        1、根据索引修改:

          person[0] = "haha";//修改数组里第一个项

          person[3] = "hahahaha";//会增加数组的长度,创建索引为3的那个项。

        2、数组的length属性,这个属性不是只读的,它的权利很大不仅可以设置修改数组,还能删除增加数组长度。

         

            例:var person = ["1","2","3"];
    
            person.length=3; //会新增一个数组的项,将数组的长度增加至4,当然新增的属性是undefined
    
            person.length=2;//会删除数组最后一个项
    
            person[person.length]= "4";//在位置3添加一个项
    
            person[person.length]= "5";//在位置4添加一个项      
    

      

        a、检测是否是数组:isArray() 例:Array.isArray(value);  

        b、数组的转化方法

          1、toString(),valueOf(),toLocaleString();

             var person = ["cuzz","hahaha"];
    
            alert(person.toString);//cuzz,hahaha
    
            alert(person.valueOf());//cuzz,hahaha
    
            alert(person.toLocaleString());//cuzz,hahaha
    
            alert(person);//因为数组的项是字符串,全部直接调用toString()方法显示整个字符串数组(记住调用的是toString()方法); 

          2、join(),接收用作分隔符的字符串。       

            例:var person = ["cuzz","hahaha"];
    
              alert(person.join(","));//cuzz,hahaha
    
              alert(person.join("||"));//cuzz || hahaha
    
              如果不给join();传递任何值,那么输出的值会默认用逗号分隔。  

        c、栈方法(先进后出)

          1、push():在数组末尾增加新项。pop()从数组末尾删除数组的项。       

             例:var person = new Array();
    
              count = person.push("cuzz","hahaha");
    
              alert(count.length);//2
    
              count = person.pop()
    
              alert(count);//"hahaha"
    
              alert(count.length);//1 

        d、队列方法(先进先出)

          末端添加项,前端移除项。

          1、shift();移除数组的第一项并返回该项

          2、unshift();在数组前端添加任意项,并返回新数组的长度

        f、重排序方法

          1、 reverse();反转数组项的顺序。      

                 例:var person = [1,2,3,4];
    
              var count = person.reverse();
    
              alert(count);//4,3,2,1 

          2、sort();升序排列数组项,即小的在前大的在后,会将其转化成字符串进行比较。

           

             例:var person = [0,1,5,10,15]
    
              alert(person.sort());//0,1,10,15,5;//很明显得到的结果和解释说不通,但是有个解决的办法是比较法
    
            例:function  compare(value1,value2){
    
                if(value1<value2){
    
                  return -1;
    
                }else if(value1>value2){
    
                  return 1;
    
                }else{
    
                  return 0;
    
                }
    
              }
    
              alert(person.sort(compare));//0,1,5,10,15这样顺序就对了 

        g、操作方法

          1、concat();复制一个数组,这个复制过来的数组是之前数组的一个副本,然后将接收到的项添加到这个数组的末尾,构成一个新的数组,如果没有参数则会创建当前数组的一个副本。

            

              例:
    
              var person = ["1","2","3"];
    
              alert(person.concat("a",["s","w"]));//1,2,3,a,s,w
    

      

          2、slice();截取数组中的某些项,如果有一个参数,则是截取这个参数开始到结束的项,如果是两个则截取这两个项之间的所有项,但不包括结束位置的项。

           

             例:
    
              var person = ["1"."3","5","6","7","9"];
    
              alert(person.slice(1,3));//3,5
    
              alert(person.slice(3));//6,7,9
    
              //如果参数是负数,则用数组的项数加上这个负数,用上面的那个例子举例:
    
              person.slice(-1,-2)和person.slice(5,4);的结果是一样的,如果结束位置小于开始位置则返回空数组
    

      

          3、splice();

            删除:指定两个参数,第一个参数要删除项的开始位置,第二个是要删除的个数。splice(0,2);会删除数组的前两项。

            插入:三个参数:开始位置,删除的项数,插入的项。插入的项是从开始位置开始插入的。

            替换:三个参数:开始位置,删除的项,插入的新项。splice(2,1,“hah”,"hhaha");//会删除当前数组位置2的项,然后插入“hah”和“hhaha”字符串

            注意slice()方法只返回被删除的项(返回的是一个新的数组),没有删除则返回一个空数组。

        f、位置方法

          返回要查找的项在数组中的位置

          indexOf();一个参数的话是获取这个项在数组中的位置,两个参数,第一个参数是要查找数组里的项,第二个参数是要开始查找的索引。

          lastIndexOf();和前一个方法一致不过它是从数组末尾开始向前查找。    

     例:
    
             var person = [3,1.2,4,3,7,4,6,7];
    
          alert(person.indexOf(4));//3
    
          alert(person.indexOf(4,4));//6
    
          alert(person.lastIndexOf(4));//6
    
          alert(person.lastIndexOf(4,4));//3
    
          
    
          var contan = {name:"cuzz"};
    
          var result = [{name:"cuzz"}];
    
          var company = [contan];
    
          alert(result.indexOf(contan));//-1   如果在数组中没有找到这个项,那么返回-1,查找的是数组项里的具体内容
    
             alert(company.indexOf(contan));//0 
    

      

        g、迭代方法

          (给某一项给定函数)for循环??   

          有五个方法,每个方法都给了两个参数,一个是数组每一项要运行的函数,另一个是运行该函数的作用域对象。(不用全写,可选)传入的函数会接收三个参数,数组项的值,数组项的位置,数组对象本身。数组的迭代方法有点类似于数组的遍历。

          1、every(),给数组中的每一项都给定一个函数,每一项都返回true,则返回对。

             some(),给数组中的每一项都给定一个函数,有一项返回true,则返回对。

    //数组包含一些运动员的信息,记录着运动员的姓名和是否签到的信息,如果哪个球员的签到信息isHell为空,就把isHell的值设置为'--'
    //name:姓名,isHell:是否签到
    
    var sporter=[{
        name:'aa',
        isHell:null
    },{
        name:'bb',
        isHell:null
    },{
        name:'bb',
        isHell:true
    }];
    

      

    //运动员进场如果需要每一个球员都必须签到,球队才能进场,实现这个需求就是
    //for:
        var isIn;
        for(var i=0,len=sporter.length;i<len;i++){
            if(!sporter[i].isHell){
                isIn=false;
                break;
            }
        }
    
    //every方法
    /*item为当前遍历到的项,和sporter[i]一样*/
        var arr=sporter.every(function (item){return item.isHell})
    
    //es6写法
        var arr=sporter.every(item=>{return item.isHell})
    //或者
        var arr=sporter.every(item=>item.isHell)
    
    //最后输出的结果都是false
    

      

    //运动员进场只需要球队任意一个运动员签到,球队就能进场,实现这个需求就是
    
    //for方式
    var isIn;
    for(var i=0,len=sporter.length;i<len;i++){
        if(!sporter[i].isHell){
            isIn=true;
            break;
        }
    }
    
    //some方式
    /*item为当前遍历到的项,和sporter[i]一样*/
    var arr=sporter.some(function (item){return item.isHell})
    
    //es6写法
    var arr=sporter.some(item=>{return item.isHell})
    
    //由于上面数组有个运动员签到了,所以返回true,可以进场
    

          2、filter():对数组中的某一项给定一个函数,返回会返回true的项组成的数组。

    //要拿到已经签到了的球员,不要没签到的球员。
    
    //for
    var arr=[];
    for(var i=0,len=sporter.length;i<len;i++){
        if(sporter[i].isHell){
            arr.push(sporter[i]);
        }
    }
    
    //filter
    /*item为当前遍历到的项,和arr[i]一样*/
    var arr=sporter.filter(function (item){return item.isHell})
    
    //es6写法
    var arr=sporter.filter(item=>{return item.isHell})
    //或者
    var arr=sporter.filter(item=>item.isHell)
    

          数组去重用法:

    //for
    var r=[],arr = ['apple', 'strawberry', 'banana', 'pear', 'apple', 'orange', 'orange', 'strawberry'];
    for(var i=0,len=arr.length;i<len;i++){
        if(r.indexOf(arr[i])===-1){
            r.push(arr[i]);
        }
    }
    
    //filter
    /*item为当前遍历到的项,和arr[i]一样,index为当前遍历到的项的索引,和i一样,self就是当前数组,和arr一样*/
    r=arr.filter(function(item,index,self){
        return self.indexOf(item) == index;
    });
    
    //es6
    var arr=sporter.filter((item,index,self)=>{return self.indexOf(item) == index;})
    

          3、forEach();给数组的每一项给定个函数,这个方法没有返回值。跟for没啥区别,就是写法不一样。

    //给每一个数字都加上一个属性sex,值都为‘男’
    /*item为当前遍历到的项,和arr[i]一样*/
    var arr=sporter.forEach(function (item){item.sex='男'})
    
    //es6
    var arr=sporter.forEach(item=>{item.sex='男'})
    

          4、map():对数组中的每一项运行给定一个函数,返回每次数组调用的结果组成的数组

    //如果哪个球员的签到信息isHell为空,就把isHell的值设置为'--'
    //for
    for(var i=0,len=sporter.length;i<len;i++){
        if(!sporter[i].isHell){sporter[i].isHell='--';}
    }
    
    //map()
    /*item为当前遍历到的项,和arr[i]一样*/
    sporter.map(function (item) {
        if(!item.isHell){item.isHell='--';}
    });
    
    //es6
    sporter.map(item=> {
        if(!item.isHell){item.isHell='--';}
    });
    

      

    //现在需要每一个球员的名字,不管他是否有签到。
    
    //for
    var arr=[];
    for(var i=0,len=sporter.length;i<len;i++){
        arr.push(sporter[i].name);
    }
    
    //map()
    /*item为当前遍历到的项,和arr[i]一样*/
    var arr=sporter.map(function (item){return item.name})
    
    //es6
    sporter.map(item=> {return item.name;});
    //或者
    sporter.map(item=>item.name);
    

        h、缩小方法

          1、reduce();会迭代数组所有的项,构建一个最终返回值,这个方法从数组的第一项开始逐个遍历到最后,传给它的函数接收四个参数,前一个值,当前值,项的索引,数组对象。这个函数返回的值会作为第一个参数传给下一项,,第一次迭代发生在数组的第二项上,因此第一个参数是数组的第一项,第二个参数是数组的第二项。

        

    //利用reduce()做求和操作
        var values = [1,2,3,4,5];
        var sum = values.reduce(function(prev,cur,index,array){
           return prev+cur;     
        })
        alert(sum);//15

    //第一次执行回调函数,第一个参数是1,第二个是2,第二次执行第一个参数是3,第二个是3,这个数组会持续到把每一项都访问一遍。

          2、reduceRight();用法和reduce()一样,只不过方向相反,它是从最后一个遍历到第一个。

       3、Date类型

        1、创建日期对象:

          var now = new Date();//如果不传递参数,会自动获取当前日期和时间

          a、Date.parse();接收一个表示日期的字符串参数,并根据这个字符串返回相应的日期毫秒数     

    //例:为2004年5月25日创建日期对象
        var someDate = new Date(Date.parse("May 25,2004"));
    

          上面的例子和下面的例子是等价的

           var someDate = new Date("May 25,2004");

           b、Date.UTC();返回日期的毫秒数。    

    //例:2000年1月1日午夜零时
        var y2k = new Date(Date.UTC(2000,0));//参数只有两个年和月,月是基于0开始算的,其他参数没有,都默认为0.
    //例:2005年5月5日下午5:55:55
        var allFives = new Date(Date.UTC(2005,4,5,17,55,55));、、接收的参数年,月,天,小时,分钟,秒
    

              c、用Date模仿:

    //例:本地时间2000年一月一日午夜零时
        var y2k = new Date(2000,0);
    //本地时间2005年5月5日,下午5:55:55
         var allFives = new Date(2005,4,5,17,55,55);
    

           d、Data.now();方法,返回调用这个方法时的时间日期的毫秒数 

        2、继承的方法

          a、toLocaleString():会按照浏览器设置的地区日期格式来返回日期时间

          b、toString():返回带有地区信息的日期和时间

          c、valueOf():返回日期的毫秒数

    toLocalString()
    -Thursday,February 01,2007 12:00:00 AM
    toString()
    -Thu Feb 1 00:00:00 PST 2007
    

          d、日期格式化方法,将日期格式化为字符串的一些方法:

            

        以上这些方法都是因浏览器而异。

      3、日期时间组件方法

        UTC日期指的是在没有时区偏差情况下的日期值

     总结:

      4、RegExp类型(正则表达式部分内容)

        1、创建正则表达式

          语法:var expression = /pattern / flages;

          patten:正则表达式。flages:标志,用来表示正则表达式的行为,有三个标志,g:全局模式。m:多行模式。i:不区分大小写模式。

        

    //匹配所有以at结尾的三个字符的组合,不区分大小写
    var patter1 = /.at/gi 
    

        2、exec()方法,接收一个要应用该正则模式的字符串,返回包含匹配项信息的数组。返回的数组包含两个属性:index,input。index表示匹配项在字符串中的位置,input是应用该模式的字符串,该数组的第一项同input的用法是一致的,其他项与模式中的捕获组匹配的字符串。

        3、text();方法,接收一个字符串参数,在模式与字符串匹配的情况下,返回true,否则返回false.

        以上用法在做正则判断,用户验证登录上面应用广泛。

        4、继承的方法:     

          a、toLocaleString();和toString();都会返回正则表达式的字面量(字符串)

          b、valueOf()方法则返回表达式本身。

      5、Function类型

        a、函数实际上是对象,每个函数都是Function对象的实例,函数名可以理解为指向函数对象的指针。声明函数的例子

          function sum(num1,num2){

            return num1+num2;

          }      

          var sum = function(num1,num2){

            return num1 + num2;

          };

          这两个在表达上几乎一样,第二个函数通过变量可以直接引用,在函数的末尾还有一个分号!!和引用一个变量差不多

        构造函数法:

          var sum = new Function("num1","num2","return num1 + num2");最后一个参数类似于一个函数体,不推荐

        b、函数名就是一个普通变量,就是说一个函数会有多个名字。

          例:上述例子可以写成var num = sum;

            使用不带括号的函数名是指向函数对象的一个指针,不是调用函数 !!!!!

        c、函数没有重载,就是后面的会覆盖前面的。

        d、函数声明和函数表达式

          函数声明:function sum(){}

          函数表达式:var sum = function(){};

          它们数据加载执行的过程不一样,函数声明会提前执行!!!,以确保在何时调用它时,都可以用。而函数表达式只有在运行到它的时候才会执行它。例:

          alert(sum(10,20));

          function sum(num1,num2){

            return num1 + num2;

          }//这个代码可以顺利执行。函数引擎会把函数声明放在源代码树的前面执行。

          alert(sum(10,20));

          var  sum = function(num1,num2){

            return num1 + num2

          }//这个代码回出错!!!调用的时候都没有解析函数表达式,在执行第一行就会触发expected identifier错误(意外标识符)错误。所以也不会执行到下面一行。

        e、作为值的函数

          因为函数名就是变量,所以可以当作值来使用,比如可用作参数后者用作函数的返回值。

          例:

          

          

          这个例子的最终结果就是执行someFunction的值,调用callsomeFunction这个函数其实也就是执行了someFunction的值。

          但是值得注意的是,不带括号的函数调用,调用的不是一个函数而是一个指针!!!,所以传递给通用函数参数的add1o是个指针不是结果。

          还有一种情况就是在函数里面在执行一个函数,这种情况在函数需要额外获取一个参数,就可以通过外面的函数来传递一个参数,用来调用。

        f、函数的内部属性

          这里主要讲arguments和this的用法

          1、arguments:表示函数传入的参数,它有一个callee的属性,是一个指针用来表示拥有这个arguments对象的函数。

            例:        

            function fall(num){
    
              if(num <=1){
    
                return 1;
              }else{
    
                return num*fall(num-1)
              }
            }
    

          上面是一个阶乘函数,但是后面调用了函数的名字,但是函数名字不会是永远不变的,所以为了消除这种耦合关系,可以这样写:

          function fall(num){
    
            if(num <=1){
    
              return 1;
            }else{
    
              return num*arguments.callee(num-1)
            }
    
          }
    

        2、this

          函数用来执行的环境对象,例如在全局作用域调用函数时,this指的就是window。

        

          记住,函数的名字是包含指针的一个变量而已。所以上述例子不管是全局执行的saycolor函数还是o对象引用的函数,它们指向的都是一个函数。

        3、caller

          用来保存调用当前函数的函数的引用(外部函数的引用)

          

          这个函数会返回outer()函数的源代码,应为outer()调用了inner()函数,所以inner.caller表示的是outer()函数

          理解:arguments.callee表示当前用这个参数的函数,而.caller相当于它的执行环境函数。所以为了消除耦合可以用argument.callee.caller来表示.caller

              所以以上这三个属性都是有内在联系的。

      g、函数的属性及方法

        函数是一个对象,那么它也具有属性和方法

        1、函数的属性

          a、length:表示函数的命名参数的个数。

            例:function sum(num1,num2){}

              alert(sum.length);//2

          b、prototype:有点老大哥的意味.

        2、函数的方法

          a、apple();在特定的作用域里调用函数,实际也就是修改函数体内this对象的值。

            有两个参数,一个是运行这个函数的作用域,一个是参数数组,这个参数数组可以用Array数组或者arguments来表示.

          b、call();和apple();作用相同,只是传递参数的形式不同,call()传递参数需要把参数一个一个列举出来。

          这两个方法作用相同,在不传递参数的情况下,使用哪个参数都无所谓。

          这两个方法的强大之处在于可以扩充函数运行的作用域

        上述例子函数在运行say.Color.call(o);时函数的运行环境就不同了,它里面的this指针就指向了o,于是结果显示的是blue,

        c、bind()

          这个方法会创建一个函数的实例,里面的this值会绑定到传给bind()函数的值(对象)。

        d、继承的toLocaleString(),toString(),valueOf()方法都是返回函数代码,但具体因浏览器而异。

        总结:

        

      6、基本包装类型

        基本包装类型用来操作基本类型的值,提供Boolean,Number,String三个特殊的引用类型。

        实现思路:1、var s1="haa";var s2 = s1.substring(2);

             2、s1不是对象按理说没有方法的,但是后台会完成创建实例,执行方法,销毁实例的过程。

            区别:生命周期不同,用new创建的实例当执行流在作用域内会一直保存在内存中,基本包装类型当下这行代码执行完就会被立刻消除。

            思考:1、运行时不能为基本包装类性值添加属性和方法。 

               2、typeof 基本包装类型;//object布尔值是true

        一、Boolean(不推荐使用)

            var booleanObject = new Boolean(true);

        二、Number

            var numberObject = new Number(10);

            拓展:1、继承了valueOf(),toLocalString(),toString();方法  

                  2、toFixed();数值格式转换字符串,参数的数值用来显示几位小数,会四舍五入.

                  3、toExponential();返回以指数表示法表示的字符串格式。

               4、toPrecision();接收一个参数,表示显示几位数的格式

        三、String

                 var stringObject = new String("hello");     

            拓展:1、length,返回字符串长度。

               2、操作字符方法:

                  a、charAt();截取单个字符。var sum = "hello",alert(sum.charAt(1));//e

                                                       b、charCodeAt();返回的是字符编码,作用和上面的一样  

               3、操作字符串:

                  a、concat();字符串拼接,类似于+。

                  b、slice();//截取,一个参数是开始位置,两个参数,第二个参数是结束位置,但不包括第二个参数所指的那个数。

                    参数为负,则会将字符串长度与参数相加,转化成正数执行。字符串长度从1开始算

                  c、substring();截取,同上。把负参数都转化为0.

                  d、substr();截取,第二个参数是返回的字符串个数。参数为负,则会将字符串长度与参数相加,转化成正数执行。字符串长度从1开始算。负的第二个参数将会自动转换为0,那么输出的就是个空字符串。

                   4、字符串位置方法(查找):

                  a、indexOf();从头搜索,返回位置的索引

                  b、lastIndexOf();从尾搜索,返回位置的索引

                5、trim();复制一个字符串副本,删除开始和末尾的空格。

                6、大小写转化:

                       a、toLowerCase();

                  b、toLocaleLowerCase();

                  c、toUpperCase();全大写

                  d、toLocaleUpperCase();全大写

               7、模式匹配方法

                  a、match();与正则的exec()方法相同。只接受正则或者正则对象一个参数。

                  b、search();z字符串第一次出现的位置

                  c、replace();替换方法

                  d、split();基于字符串里的分隔符,分割字符串组成数组,第二个参数是限制数组的长度。

               8、localeCompare();根据字母表作比较,排在前面返回-1,等于是0,后面是1,实际应用可以用<>=<1,o-1做判断执行代码。

               9、fromCharCode();接收字符编码转化为字符串,与charCodeAt()执行的是相反操作。

      7、单体内置对象

        内置对象:不依赖于宿主环境的对象,在程序执行前就已经存在了,例:Object,Array,String.单体内置对象:Global和Math.

        1、Global对象(全局对象),所有在全局作用域中定义的属性及方法都是Global的对象的属性。

          扩展:a、URL的编码方法,对url编码做解析。

             b、eval()方法!!!类似于一个ES解析器

              概念:执行以字符串形式表示的代码。只接受一个字符串参数,这个参数是要执行的代码,这个代码的执行环境是调用eval()时的执行环境,就像在一串代码外面穿了件衣服。

             c、window对象

              浏览器会将全局对象作为浏览器的一部分进行实现,所以在全局中声明的所有变量或函数,都成为了window对象的属性。可以用window.什么什么来访问。

        2、Math对象(实现数学计算功能)

          a、min();max();解析出一组数的最小值和最大值。Math.max(),    Math.min();

            例:

            

            

          b、四舍五入方法:Math.ceil();Math.ceil();Math.ceil(round);

          c、random();

            Math.random();返回介于0和1之间的随机数,常用与随机显示一些内容,给返回的值加一或者乘10可以很灵活的运用它。

    总结

    六、面向对象的程序设计

      1、对象:

        理解:基于一个引用类型创建,一组键值对的集合

        创建方法一:var obj = new object(); obj.age = 10;

        创建方法二:var obj = {obj:10,name:"名字"};

        属性类别:数据属性,访问器属性

          数据属性:以上的obj,name都是数据属性。修改方法:object.defineProperty();三个参数:对象,属性,描述符对象属性里的this值指向这个对象

          访问器属性:(有的属性名称前面是一个下划线,表示只能通过对象方法访问的属性)设置一个属性的值会导致其他属性发生变化,有get(读)和set(写)方法。

          区分类型:通过Object.getOwnPropertyDescriptor();查看属性描述符,有value的是数据属性,没有的是访问器属性

        a、定义多个属性的方法:

          Object.defineProperties();通过描述符定义多个属性,两个参数

          例:var obj={};

            Object.defineProperties(obj,{

              _year:{

                value:2004

              },

              edition:{value:1

              },

              year:{

              get:function(){return this._year},

              set:function(){return "hahaha"}

              }

             })

          _year和edition是数据属性,year是访问器属性

          Object.getOwnPropertyDescriptor()方法取得给定属性的描述符,一个参数是对象,一个是属性名。在.描述符名获取描述符

      2、创建对象

          a、工厂模式:利用封装函数给定特定接口来创建对象

            例:function person(name,age){

                var obj = new Object();

                obj.name= name;

                obj.age=age;

                obj.sun = function(){

                  alert(this.name)

                }

                return obj;//这个函数有返回

              }

              var per=person("hahah",10)

          b、构造函数模式:

            function Person(name,age){

              this.name = "cuzz";

              this.age=10;

              this.sum=function(){

                alert(this.name)

              }

            }

            ver per = new Person("cuzz",10);

            这个例子是上面例子的重写。不同在于:!!!构造函数函数名首字母大写!!!没有return语句

          构造函数的特点:

            1、调用方式不同

            2、任何函数只要通过new来调用 那它就是构造函数

          注:普通函数放在全局环境上,可以用window.属性名来访问这个函数的属性值

        c、原型模式

          (原型对象封装函数简化的作用)

          概念:每个函数都有一个prototype(原型)属性,它是一个指针,指向一个对象(原型对象),而这个对象包含了特定类型的对象所共有的属性和方法。所以说prototype就是调用构造函数创建的实例的原型对象,使用原型对象的好处是让所有对象实例包含它所拥有的属性及方法

          就是函数有个原型属性,这个属性可以抽象的理解成一个原型对象,这个对象包含了许多公共属性及方法。

          例:function Per(){

              this.prototype.name="haha"(给原型对象添加了一个name属性)

            }

            ver peroto=new Per(); 

            var per1=peroto.name

            var per2=peroto.name

            //per1和per2调用的是同一个属性,this指的是实例

            

         1、 新建的自定义构造函数的原型对象默认公共的属性只有constructor而其他的公共属性都来自object.

          实例    构造函数  原型对象 中间的连接的桥梁就是prototype(抽象的理解为原型链)

          per.prototype.constructor指向的是per

          per.prototype指向的是原型对象

           2、用isPrototypeOf()检查实例对象是否指向了原型对象,是返回true

          alert(per.phototype.isPrototyprOf(per1))//true

           3、创建的实例和原型函数间有个指针就是他们的桥梁[[prototype]],用Object.getProtoTypeOf()可以返回[[prototype]]的值

          例:alert(Object.getPrototypeOf(per1).name);//"haha"

           由上例可知,Object.getPrototypeOf(per1)就是per1实例的原型对象

          读取对象属性的查找顺序会先查找这个实例本身的属性没有找到在去原型对象里查找

           4、如果实例和原型对象有属性同名会使用实例中的属性(所以是删除实例中这个同名属性,就可以访问原型中的这个属性)

           5、hasOwnProperty()检测属性是存在于实例还是原型对象中,存在于实例中返回true

           用法:实例名称.hasOwnProperty("属性名")

         6、in与原型

          alert("name" in per1);//true 这个属性存在于原型或者实例中就会返回true,不论是原型还是实例

           7、枚举原型对象的属性名:Object.keys(per1.prototype);//"name"

           枚举实例的属性名:Object.keys(per1);

           枚举包含实例原型的所有属性名:Object.getOwnPropertyNames(per.prototype);在构造函数名上使用

         8、简单常用的封装原型属性的写法:

            function per(){

              Person.prototype={

                name:"haha",//这个name没有加引号!!

                age:10,

                say:function(){}

              }

            }

          var per1 = new per();

          上述写法无法用constructor确定对象的类型alert(per1.constructor==per);//就是说无法在指向构造函数

          但是解决办法是在原型对象中从新改写属性值,添加constructor == per

        9、松散性,不论实例的调用是在原型属性修改前还是修改后,只要是存在就能访问到。而这个对封装原型属性的这种写法无效。

        

        10、给原生对象(Object,Arrey,String等)定义原型属性

          String.prototypt.per=function(text){alert(text)}

          var sum="haha";

          sum.per("hahha")//!!!这里sum是字符串,多以sum能访问到定义在字符串原生对象上的原型属性。为什么sum能.一个属性,我想是应为它是基本包装类型有方法。

        11、原型对象的缺点

          function Person(){

            Person.prototype={

              arr:["haha","hihi"]

            }

          }

          var per1 = new Person();

          var per2 = new Person()

          per1.arr.push("heihei");

          alert(per1.arr);//"haha,hihi,heihei"

          alert(per2.arr);//"haha,hihi,heihei "//!!!这里的重点是从per1修改了arr属性,但是per2访问到的是修改之后的属性。所以问题就在于,实例想要有个自己的属性,这样就GG

        12、构造函数模式用来定义实例属性,原型模式用于定义共享属性

        13、组合构造函数模式和原型模式可以改进11里的问题!!!常用

          function Person(name){

            this.name=name;

            this.arr=["haha","huhu"]

            this.prototype={

              sum:function(){}

            }

           }

          var per1=new Person(“haha”);

          var per2=new Person("haha");

          alert(per1.arr.push("heihei"));//"haha,huhu,heihei"

          alert(per2.arr);//"haha,huhu"//!!!这里重点是从per1实例中修改了arr的值,但没有影响per2的arr的值。

          但是:alert(per1.sum===per2.sum)true,//实例修改引用的构造函数的值是不会相互影响的,只有修改原型的值会互相影响

        14、如果在已经创建了实例的情况下,重写prototype对象,那么这个实例与新原型间就没有什么关系了。

        15、寄生构造函数模式,就是把一个对象封装成一个构造函数,在函数里面新建一个对象,并返回这个对象 

          例:创建一个具有额外方法的特殊数组:

            function Person(){

              var obj = new Array();//新建一个数组对象

              obj.push.apple(obj,argument);//为数组对象添加元素,用apple方法就是将作用域放在这个对象上

              var per=function(){//定义了per方法

                alert(obj.join("|"));

              }

              return obj;

            }

            var per2 = new Person("haha","haihai");

            alert(per2.per());给per2调用per方法

            构造函数返回的对象与构造函数外部创建的对象一样,这种写法不推荐

        16、稳妥构造函数模式(安全模式)用法和上述例子一样,但不能使用this 函数之后也不能new实例

      3、继承

        1、原型链:

          让一个实例的原型等于另一个实例,那么这个实例访问原型的关系是怎样的:

          function Per(){};//构造函数Per    Per.prototype.sub=function(){};//Per的原型

          function Por(){};//构造函数Por    Por.prototype=new Per();//!!!这里注意Por构造函数的原型复写给了Per的实例,所以Por原型继承了Per和Per原型的属性方法

          var sup = new Por();//!!!这个实例可以获取到的属性有Por构造函数属性,per()构造函数属性,Per原型对象属性

          sup.sub;//true;//搜索过程是:sup实例,per实例,per原型

          但是!!!sub.constructor指向的是Per,应为sub的原型属性constructor重写了。

        2、默认原型Object,所有函数的默认原型都是Object,应为原型也是个对象,所以默认原型内部会有一个指针指向Object.prototype

        3、判断原型与实例的关系:

          a、instanceof测试实例在原型链中是否出现的构造函数

            alert(sup instanceof Per);//true  alert(sup instanceof Object);//true    alert(sup instanceofPor);//true

          b、isPhototypeOf():判断一个对象是否存在于另一个对象的原型链中

            alert(Object.prototype..instanceof(sup));//true

        4、通过原型链实现继承时不能使用对象字面量创建原型方法,应为这样会重写原型链。

        5、说法:Por.prototype=new Per();Por通过原型链继承了Per.

        6、给一个构造函数定义了两个实例,实例1修改了原型中的值,实例2访问到的是修改后的值。这算是原型链的问题。还有个问题是实例(子类型)不能向构造函数(超类型)传递参数。

        7、借用构造函数(解决上述原型链问题提出)

          1、概念:在子类型构造函数的内部调用超类型构造函数(可以用apply()和call()自执行函数

              

           2、用构造函数传递参数

              

              上述例子就是用构造函数保存了个name属性传达给其他函数。

         8、组合继承

            1、组合原型链和借用构造函数,想让他们拥有继承的属性还有让每个构造函数拥有自己的属性

              思想:a、在构造函数A里面引入一个构造函数B,并让构造函数A的原型对象等于构造函数B

                 b、这样构造函数A的实例就继承了构造函数A的方法,构造函数A的原型属性,构造函数B的方法,构造函数B的原型属性

                 c、引用构造函数的方法不会在每个实例间相互影响,但是在原型定义的方法是一致的。

           9、原型式继承

            思想:创建一个构造函数,传递一个对象参数,在这个构造函数里面创建一个实例,将这个传递进来的对象当做这个实例的原型,返回这个实例。

            Object.create();一个参数:引入的对象。两个参数:第一个是引入的对象,第二个是需要添加的属性

         10、寄生式继承。==怎么说

         11、寄生组合式继承

          继承重新总结在我的另一篇博客中。

      

    七、函数表达式

      一、函数声明和函数表达式。

        1、函数声明:function name(){}

             特点:声明提升,这个函数放在执行语句的前后都是没有问题的。

        2、函数表达式:var functionName = function(){}

             特点:1、变量赋值,属于匿名函数,因为function后面没有跟函数名。

                2、函数体必须在表达式之前被声明。

             

        3、createComparisonFunction(){}

      二、递归函数,在函数里面用到该函数

        

      三、闭包

        1、里面的函数能够访问外面的函数,通过作用域链层层向外访问,这个里面的函数就是闭包。

        2、js有个特点就是里面的函数可以访问外面但外面不能访问里面。(链式作用域结构)

        3、如何让外面的函数访问到里面,把里面的函数返回,或者执行在外部作用域

        用途:1、匿名自执行函数,不会污染全局变量

            例:自执行函数:(function(data){})(data)

           2、结果缓存。不会释放外部的引用,所以内部的值也因此保留了下来

           3、封装。外部不能直接访问内部

        作用域链实质:指向变量对象的指针列表(一层一层递进),引用但是不包含变量对象。

        变量对象:一个作用域里变量所属的环境对象,比如说在全局声明的变量,它们的变量对象就是全局变量。

        知道了为什么有的函数在内部执行完后要return返回,就是为了外部函数能够调用

        4、闭包与变量

    function createFunctions(){
                var result = new Array();
                for (var i = 0;i<10;i++){
                    result[i] = function(){
                        return i;
                    };
                }
                return result
            }
            var arr = createFunctions();
            console.log(arr)
    
            function createFunctions(){
                var result = new Array();
                for (var i=0; i <10;i++){
                    result[i] = function(num){
                        return function(){
                            return num;
                        }
                    }(i);
                }
                return result
            }

         以为闭包保存的是整个变量对象,所以它取得的值是包含函数中任何变量的最后一个值,所见的场景是一个循环+1下来输出循环,它保存的都是最后一个值

       5、关于this对象

        本意:1、运行时函数的执行环境对象。

           2、被当做对象方法调用时,指向的是该对象

        但是闭包的this值会有变化,将this值赋值给另一个闭包,调用的时候才能取得包含赋值闭包的那个对象里的属性

          1、每个函数被调用的时候,活动对象都会自动获取两个值,arguments 和this。

          2、活动对象,某种意义上来说和变量对象一样。函数活动时所能访问到的参数啊变量啊

         6、内存泄漏

        外部函数包含内部函数的引用,所以内部函数(闭包)在执行完毕后不会被销毁,造成内存泄漏。

         7、模仿块级作用域

        格式:(function(){})()

        含义:这是一个自执行函数,表达式后面的括号代表的是执行函数。前面括号里的函数实际上是一个函数表达式。

        var con = function(){}

        con();

        这个块级作用域函数的实现目的和上述例子是一样的

        特点:1、任何时候临时需要一些变量就可以使用私有作用域,在匿名函数中定义的变量在执行完毕后就会被销毁。就是给里面的执行语句创建了个私有空间

           2、这种写法一般用在全局作用域函数的外部,从而防止污染全局变量。

       根据类名做判断hasClass()

        8、私有变量

        概念:在函数中定义的变量都可以称为私有变量。

        特权方法:

          概念:有权访问私有变量和私有函数的公有方法叫特权方法。

        有两种在对象上创建特权方法(在对象上可以访问函数的内部变量方法)的方式:

        1、用构造函数      

    function Con(){
      var age = 10;
      function sub(){
          return false  
        } 
      this.sup = function(){//重点。它是一个闭包
          age++
         return sub()
         }        
    }
    //当创建了Con的实例后只有用sup函数来访问age和sub,没有其他办法

      9、静态私有变量

      (为了弥补构造函数创建特权方法的缺点:在每个实例上都会创建同样的一组新方法)

      在私有作用域中创建特权方法,模式:

         

     (function(){
            function per(){
              return false;
            }
            Myobject = function(){}//定义的函数表达式,是一个全局函数在私有作用域之外可以访问到
    //特权公有方法
                           Myobject.prototype.con = function(){
                            return per();
                          }  
          })();    
            
    

      10、模块模式

        1、概念:为单例创建私有变量和特权方法。

          单例:只有一个实例的对象。

          创建单例:var sum = {age:10,person:function(){}}

        例子...

        

      总结:闭包为什么可以访问它外部的执行环境:

         答:应为闭包的作用域链包含着它自己的作用域,包含函数的作用域,全局作用域。

        创建私有作用域(模仿块级作用域)优点:既可以立即执行代码又不会留下函数在内存中的引用。(应为闭包有内存泄露的问题),但是在执行完毕后,函数就会被销毁,但是如果将数据赋值给包含作用域的变量,就可以将其保存下来。

        私有作用域:特点:和对象没关系,就是创建一个类似闭包的模块,隔绝外部环境,防止变量污染

         

    八、BOM

      掌握窗口和一些页面属性

      8-1、window对象

        概念:它是BOM的核心,代表了浏览器的一个实例(也是全局对象)

      8-1-1、全局作用域

        特点:1、在全局中声明的属性及方法,都会变成window的属性及方法

           2、全局变量不能通过delete删除,但是在window上定义的属性可以删除

           3、有些IE浏览器不允许直接在window上直接创建属性,但是在全局上定义的属性都会成为window对象的属性

      8-1-2、窗口及框架

        1、框架、

          概念:1、如果页面包含框架那么每个框架都会包含一个window对象,每个对象都有一个name属性,包含了框架名称。

        2、窗口

          2-1、窗口位置:screenTop,screenLeft或者screenX,screenY

          2-2、窗口大小:页面视图区大小:innerWidth,innerHeight,

                   浏览器窗口的大小:outerWidth,outerHeight

                  注:在谷歌浏览器中他们返回相同的值

                  取得页面视口信息:document.documentElement.clientWidth,document.documentElement.clientHeight

                   移动端屏幕上页面可见区域大小(随着页面缩放这些值会相应的得到变化):window.innerHeight,window.innerWidth

            2-3、调整页面窗口大小,以下方法都是window的属性

            2-3-1、resizeTo();接收浏览器的新宽度和新高度,两个参数

                window.resizeTo(100,100);//将浏览器窗口调整为100x100

            2-3-2、window.resizeBy();接收新窗口和原窗口的高度之差;

                windo.resizeBy(100,50),//又将窗口调整为200x150,在原窗口宽度的基础上增加了长度。

           2-4、导航和打开窗口

            2-4-1、window.open():打开新的窗口链接,有四个参数        

    //<a href="http://www.baidu.com" target="_blank"></a>
    //上述代码和以下例子是一样的
    window.open("http://www.baidu.com","_blank")//第二个参数也可以是框架或窗口名

                

              

              window.close()关闭窗口,不过只适用于用window.open();打开的窗口。

              新创建的窗口对象都有一个opener属性,指向原窗口

              wrow.opener = null;//切断新窗口与原窗口的通信,可以用这个方法检测浏览器是否将新窗口视作恶意窗口屏蔽了。

              拓展:

    try
    
    {
    
    //有可能出现错误的代码写在这里
    
    }
    
    catch
    
    {
    
    //出错后的处理
    
    }
    

      

        2-5、超时调用

          2-5-1、window对象的serTimeout()方法,两个参数,一个是执行的代码,一个表示在多长时间后执行这个代码

    setTimeout("alert('haha')",6000);

            2-5-2、取消超时调用:clearTimeout();

          

        2-6、间歇调用(不推荐使用)

          2-6-1、setInterval();俩个参数,用法和setTimeout()用法一样。

          2-6-2、clearIntval();取消间歇调用

        2-7、用超时调用模拟间歇调用(推荐)

          

        2-8、系统对话框

          alert();confirm();prompt();样式都是由浏览器决定,弹出后代码会停止执行,关闭会继续

          confirm();包含确认和取消(关闭x)按键会返回true或者false,多在删除中使用

          

          prompt();//显示三个元素,确认取消和一个文本框

          第二个参数是代表文本框里的value值 

          

          

        window.print()打印,window.find();查找

      3、location对象

        3-1、特点:特供了当前加载文档的信息还有导航信息。既是window的属性,又是document的属性,window.location 和document.location指向的是同一个对象

          

        3-2、位置操作。

          下面三个代码是一个效果,前面都可以加window.也可以不用添加

          

          

          

          除了hash外其他都会重新打开一个页面。

          这些打开的页面都可以退回上一个页面,如果想禁止退回:方法:replace();

            location.replace("www.baidu.com");//重新打开百度后不会再退回上一个页面

          重新加载页面:window.location.reload();

            window.location.reload();//从缓存加载

            window.location.reload(true);//强制从服务器加载

      4、navigator对象

        关于浏览器的特殊标准,包含了检测插件,注册处理程序的方法

      5、screen对象;大多是用来获取浏览器的外部窗口信息。

      6、history

        6-1、go()方法

          

          跳到有包含某个字符串参数的链接

          

          history.back();//后退一页,

          history.forward();//前进一页

        6-2、length属性

          if(history.length == 0){

            //判断是否是新打开的页面

          }

    九、客户端检测

    十、DOM

      10-1-1、node类型

          js中的所有节点类型都继承自node类型,所以所有节点都有着一些相同的基本属性和方法。

        10-1-1.nodeType:节点类型。

          10-1-1-1、Nodelist,类数组,但不是数组类型

              将Nodelist转化为数组:

              (将arguments转化数组方法:Array.prototype.slice())

              var arr = Array.prototype.slice.call(someNode,childNodes,0);//ie8之前不适用

          10-1-1-2、parentNode:父节点

              childNodes:子节点

              通过节点列表中的每一个节点的previouSiblings和nextSibling属性可以访问列表中的其他节点

              someNode.firstChild == someNode.childNodes[0];

              someNode.lastChild == someNode.childNodes[someNode.childNodes.length-1];   

          10-1-1-3、hasChildNodes();判断一个元素节点是否有子节点,有返回true

              所有节点的最后一个属性ownerDocument指向整个文档,不用在层层节点追溯至跟文档

        10-1-2、操作节点

          插入

          10-1-2-1、appendChild(),向节点末尾添加元素

          var under = someNode.appendChild(underX);//这个方法返回的是传入的新值。

          alert(under == underX);true;

          10-1-2-2、insertBefore();将新节点插入到childNodes列表的某个特定位置。两个参数,第一个:要插入的节点,第二个参照节点(插到前面)。

            但是参照节点若是null:someNode.insertBefore(newNode,null);

              newNode == someNode.lastChild

          替换

          10-1-2-3、replaceChild();替换节点,两个参数,第一个是新节点,第二个是要替换的节点

              someNode.replaceChild(newNode,someNode.firstChild);//替换第一个节点

          移除

          10-1-2-4、removeChild();一个参数,移除节点,方法返回被移除的节点元素

             复制 

          10-1-2-5、cloneNode();接收一个布尔值参数,true为深复制,false为浅复制,只复制节点。

      10-1-2、Document类型

          表示文档,document对象是window对象的属性

        文档的子节点

        10-2-1、documentElement属性,它始终指向html元素

            document.documentElement == document.firstChild == document.childNodes[0];

        10-2-2、body属性,documen.body指向body元素

        10-2-3、document.doctype;//取得对<!DOCTYPE>的引用

        文档信息

        10-2-4、title属性,获取或修改title的值,

            获取title标签的值,var txt = document.title;

            设置title标签的值,document.title=“this is title name”;

        网页信息

        10-2-5、

        

        取得某个特定元素

        10-2-6、getElementById();取得元素的某个id

        10-2-7、getElementsByTagName();取得标签名,这个取得的值和NodeList对象类似,可以用[]操作,会返回一个HTMLCollection对象

            HTMLCollection还有个namedltem()方法,根据元素name属性的值取得元素

            传入“*”可以获得整个文档中的元素。

        10-2-8、getElementsByName();根据name属性值返回所有元素,常用于单选按钮中

        文档写入  

        

        write可以包含标签的字符串

      10-1-3、Element类型

        访问元素的标签名,nodeName或tagName

        

        10-1-3.1、html元素

          className类名...直接跳!!

    十三、事件

      事件流

         冒泡:由事件元素层层向上传播到dom

        捕获:和冒泡相反

        dom事件流:先捕获,在处于目标阶段,事件冒泡

        

              捕获阶段不会接收事件,接收事件冒泡传播到文档

      事件处理程序

        响应事件的函数叫做事件处理程序,以on开头。

        1、html事件处理程序

            添加方式:onclick="alert("haha")",或onclick = "show()",this值等于事件的目标元素

            缺点:1、时差,没解析到函数,就执行了事件。2、js和html紧密耦合,改动的话要改两个地方

            解决缺点1:onclick = "try{show()}catch(){}";

        2、dom0级事件处理程序

            每个元素都有自己的事件处理程序属性,属性名几乎都为小写

            div.onclick = function(){},函数中的this指向当前元素

            删除:div.onclick = null;

        3、dom2级事件处理程序

            addEventListener();三个参数,事件名,事件处理函数,布尔值

                布尔为true表示在捕获阶段调用事件处理函数,false是在冒泡阶段调用

                例:div.addEventListener("click",function(){alert("haha")},false);表示在冒泡阶段触发,!!注意这里写的是click不是onclick

                这个方法的好处是可以多次调用时间处理函数,不会被复写,会依次执行

            removeEventListener();同上

            建议在事件冒泡阶段触发函数

        4、ie事件处理程序

            attachEvent();两个参数,事件处理名,处理函数

                例:div.attachEvent("onclick",function(){});为元素添加一个点击事件,!!这个参数是加on的

                特点:用这个方法,函数里的this指向window,!!这点在跨浏览器编程是很有用,多个添加的事件函数,会以相反的顺序调用。

            detachEvent();移除attachEvent();调用的事件

        5、跨浏览器的事件处理程序

            addHandler();视情况使用某种类型的事件处理程序,它属于一个叫EventUtil的对象(用来处理浏览器间的差异),三个参数,操作的元素,事件名,事件处理程序

              EventUtil.addHandler();常用!!!

              保险的做法:event = EventUtil.getEvent(event);

            removeHandler()

      事件对象

          每次触发事件,都会产生一个event事件对象,保存了与事件相关的信息。这一小节就是围绕各种环境下如何使用event对象的知识

          1、dom中的事件对象

              event.type:事件类型,event.target:触发事件的那个目标元素

              event.preventDefault();取消元素的默认行为,例如a标签的href跳转事件

              event.stopPropagation();立即停止事件的传播

              。。。很多属性方法

              event只有在事件执行时才存在,执行完毕会立即删除

          2、ie中的事件对象

              在使用dom0级事件调用函数时,event对象作为window对象的一个属性存在:window.event.type

              event.srcElement == this

              window.event.returnValue = false;等同于dom中的preventDefault();

              window.event.cancelBubble =true;等同于dom中的stopPropagation();             

          3、跨浏览器的事件对象

              针对以上两种兼容性的折中方法,可以借助Eventutil对象

      事件类型

          1、UI事件

                load:页面完全加载后,在window上面触发

                    用法1、EventUtil.addHandler(window,"load",function(){});event.target = document

                    用法2、为body元素添加<body onload = "show()"></body>

                    在处理图片加载问题中们可以使用new image()实例,但是image对象不属于dom树,只有指定了src才代表开始加载图片

                unload:页面完全卸载后,在window上触发,用户从一个页面切换到另一个页面就会触发

                    用法1、EventUtil.addHandler(window,"unload",function(){});

                    用法2、<body onunload="show()"></body>

                abort:停止加载时触发

                select:选择文本框时触发(input texterea)

                resize:窗口大小发生变化后的事件,在window上面触发,event.target = document

                    EventUtil.addHandler(window,"resize",function(){})

                scroll:滚动滚动条触发,在window对象上发生

            2、焦点事件

                blur:失去焦点触发

                focus:获得焦点触发

                focusin:等于focus

                focusout:blur的通用版本

            3、鼠标与滚轮事件

                click:点击鼠标,或者enter时也可以

                dblclick:双击鼠标

                mousedown:按下任意鼠标按钮时,键盘不能触发,这个事件下有一个event.button属性,有许多值,表示了不同用法             

                mouseup:释放鼠标按钮,这个事件下有一个event.button属性,有许多值,表示了不同用法

                mouseenter:鼠标移入,兼容差,谷歌不支持

                mouseleave:移出,兼容差 

                mousemove:在元素上移动

                mouseout:移出某元素

                mouseover:移入某元素

                客户区(视口区域)坐标位置:

                  event.clientX;event.clientY;告诉你事件是在视口的哪个位置触发的

                页面坐标位置

                  event.pageX;event.pageY;告诉你事件是在页面的哪个位置触发的

                屏幕坐标位置

                  event.screenX和event.screenY

                某些特定的修改按键,按下是true,否则是false

                  event=EventUtil.getEvent(event)

                  shift:event.shiftKey

                  ctrl:event.ctrlKey

                  alt:event.altKey

                  meta(win).event.metaKey

                滚轮事件

                  mousewheel;这个事件里的event.wheelDelta,向前滚动是120的倍数,向后滚动是-120的倍数,只需要知道它的正负号,来确定滚动的方向就可以了

            4、键盘与文本事件

                keydown:按下任意键触发,里面有一个event.keyCode属性,代表了按下的那个键的编码,回车是13,回格是8,退出是27

                keyup:释放按键

                keypress:按下字符键触发,有个event.charCode

                   dom3里的变化(兼容差,不推荐使用)             

                    用key和char取代keyCode和charCode

                    key是直接返回键的名字  

                textInput:文本事件,文本插入文本框之前触发,输入文字触发

                    event.data:输入的文本,event.inputMethod:输入的方式

            5、变动事件,在dom上的任何操作产生的事件,包括输入,删除节点,添加等等

            6、HTML5事件

                contextmenu事件:显示上下文菜单事件,类似于鼠标右击显示的上下文菜单

                beforeunload事件:页面卸载前触发的事件,给一个询问卸载框,将选择权交给用户

                DOMContentLoaded事件形成完整的dom树时就触发,不会理会图片,js是否加载完成,让用户尽早的与页面交互,它的target是document

                readystatechange事件,加载状态有关的,支持这个事件的对象有个readyState属性,根据不同属性值(状态)给定函数(兼容差)

                pagesshow和pagehide事件,事件的目标是document但是要将它添加到window,页面缓存前后文相关事件

                hashchange事件,url发生变化时,调用对象是window(兼容差)

                    该事件有两个属性even.oldURL和newURL保存着变化前后的完整URL

            7、触摸手势事件

      内存和性能

        事件委托

            用一个事件来管理某一类型的所有事件

            场景:在一列li列表中,如果每个li都有一个点击事件,每次调用点击事件,都会冒泡查找一次dom节点,很耗性能,所以解决办法在父元素ul里定义点击事件,然后为点击的元素添加函数,这样就只查找了一次dom。

          

          

       移除事件占用

          场景:一个元素被添加了点击事件,但是这个元素之后被别的内容替代了,不存在了,但是它的点击事件还存在与内存中,那么这个时候就要手动解除引用,方便被垃圾回收机制回收。

          例:

    var div = document.getElementById("id");
    div.onclick = function(){
        div.onclick = null;//解除引用  
        div.innerHTML = "new page";   
    }

      模拟事件

        dom中的事件模拟

            创建:

                document.createEvent();创建一个event对象,传递一个字符串参数

                  参数可以是:UIEvents,UI事件,MouseEvents,鼠标事件(initMouseEvent()),KeyboardEvent,键盘事件(initKeyEvent())MutationEvents,dom变动事件(initMutationEvent()),HTMLEvents,一般的html事件(initEvent()),每个特定事件都有一个特有属性及方法。

            触发:

                dispatchEvent(),一个参数,触发事件的event对象(创建的那个event对象),dom节点的方法

           

          自定义dom事件(兼容差)

            创建:var event = document.createEvent("CustomEvent");

            特有方法:event.initCustomEvent();四个参数

        IE中的事件模拟

            创建:document.createEventObject();不接受参数,返回一个通用的事件对象

    十四、表单脚本

       表单基础

          HTMLFormElement类型,继承自HTMLElement         

               获取:<form>表单:document.getElementById("formId");

                  页面中的<form>表单集合:document.forms

                     集合中查找表单:document.forms[0];

                          document.forms["表单的neme名字"]

          提交表单

              将<input>或者<button>的type属性设置为submit即可,只要存在这种表单提交按钮,输完值按回车就可以提交了。或者form.submit();

              阻止提交

                  EventUtil.preventDefault(event);

              解决重复提交出错问题:在第一次提交后就禁用提交按钮,或者用onsubmit事件取消后续操作。

          重置表单

              将input或button的type设置为reset就可以,或者form.reset();

              阻止重置事件:       

    var form = document.getElementById("myform");
    EventUtil.addhandle(form,"reset",function(event){//注意这里有参数,事件名是字符串
          var event = EventUtil.getEvent(event);
          EventUtil.preventDefault(event);//!!阻止操作是EventUtil对象的方法
    });

         表单字段(元素)

              1、elements属性,它是表单form元素的属性,表示表单中所有元素(input,textarea。。。)的集合。

                使用:

                  var field = form.elements[0];//取得表单中第一个字段

                  var text = form.elements["textarea1"];//取得名为textarea1的表单字段

                  var num = form.elements.length;

                NodeList:如果有多个name相同的元素, form.elements["textarea1"]则会返回一个NodeList集合

                  var text = form.elements["textarea1"];

                  text[0],集合里的第一个元素,前面没有属性或对象,直接调用

              2、共有的表单字段属性(除<fieldset>)

                  disabled:布尔值,表示当前字段是否被禁用

                  form:指向当前字段所属表单,只读

                  name:字段名字

                  readonly:布尔值,字段是否只读

                  type:字段类型

                    tabIndex:的切换tab序号

                  value:将被提交给服务器的值,字段.value = "",修改

              

    //提交一次后禁用提交按钮,注意submit事件只在有提交按钮时才存在
        EventUtil.addHandle(mysubmit,'submit',function(event){
            event  = EventUtil.getEvent(event);//获取event对象
            var target = EventUtil.getTarget(event);//这个是EventUtil的方法
            var tar = target.elements['subimit']//获取提交按钮    
            tar.disabled = true;运行之后禁用提交按钮            
        })
       //注意不能用onclick事件 
    

                3、共有的表单字段方法

                      获得焦点:1、focus()方法   

    页面载入后在第一个表单框使用焦点
    EventUtil.addHandler(window,'load',function(event){
           document.forms[0].elements[0].focus(); 
    })//如果第一个字段的属性是hidden,那么会报错
    

                         2、autofocus属性(h5新增)返回的是个布尔值

                  移出光标:blur();

              4、共有的表单事件

                  blue:移出焦点

                  change:对于input和textarea字段是,从获得焦点移出焦点后value改变时会触发

                      对于select是在元素改变时触发

                  focus:获得焦点 

        文本框脚本

           <input>

              type:text;size:文本框显示的字符长度;maxlength:限制最大输入的字符数

           <textarea>

              用rows行数和cols列数限制大小<textarea>内容内容</textarea>  

           选择文本

                select():选择文本框中的所有文本,没有参数

                select(选择)事件:选择了文本框里的文本,就会触发select事件

                获取选择的文本(h5的方法) value.substring(元素.selectionStart,元素.selectionEnd)

                获取部分文本:

                  

           过滤脚本

              1、屏蔽字符

                联系键盘事件keypress,来响应操作,其中preventDefault(event)可以用来阻止按键输入

              2、操作剪贴板

              3、自动切换焦点

                场景:当用户输入足够长度的字符后,自动跳转下一个文本框,能用到maxlength特性

              4、h5约束验证api

                required:必填字段

                type="email",规定输入的字段必须为邮箱

                type = "url",url模式字符

                数值范围:兼容差,略过

                   输入模式:pattern = “d+”;只允许在文本中输入数值

                禁用验证:添加novalidate属性

        选择框脚本

          add(newOption,relOption),在relOption前插入newOption

          multiple:布尔值,允许多项选择

          options:元素中所有的option元素的集合

          remove(index);移除给定位置的选项

          selectedIndex:基于0的选中项的索引,没有则为-1

          size:选择框中可见的选项数

          选择框的值:

              有一个选项:选择框的value是选择项的value

              多个选项:选择框的value等于第一个value

              如果选中项的value等于空,那么选择框的value是null.如果选中项的value没有指定,那么就取选中项的选项的内容。

          每个<option>元素都有着一个HTMLOptionElement对象表示

          HTMLOptionElement属性:

              index:当前选项在options中的索引

              label:当前选项的标签

              selected:布尔值,表示哪个项被选中

              text:选项的文本select.options[0].text

              value:选项的值select.options[0].value

          选择选项

              访问选中项:var sel = myselect.options[myselect.selectedIndex]

                 设置选中项:myselect.options[0].selected = true;在允许多选的情况下,可以多次使用该属性,创建多项选中。

                 添加选项:dom方法:

    var opn = document.createElement("option");
    opn.appendChild(document.createTextNode("option text"));
    selectbox.appendChild(opn);
    

                         构造函数法

    var opn = new opn('text','value');//接收两个参数,text和value
    myselect.appendChild(opn);
    

                     add('新项',‘位于新选项之后的项,若是之后没项,则填写null’)

            移除选项

              1、dom方法:removeChild()

              2、selectbox.remove(0);要删除值的索引

              3、selectbox.options[0] = null;

           移动和重排选项

               insertBefore('移动的元素','移动到某元素之前');

        表单序列化

          serialize();就是自动获取表单需要提交到服务器的值,每个值之间用&分割。

        富文本编辑

          通俗理解就是在一个框架元素<iframe>里嵌套一个页面,有个designMode的属性让它们可编辑。另一种方式是给div给个contenteditable属性,就可以编辑了,它的值有三个true打开,false关闭,inherit继承

              操作富文本:document.execCommand()

      

              

          

          

          

                

          

              

                

                  

          

                

                

                

        

      

            

            

      

           

          

      

          

  • 相关阅读:
    asp.net linux 环境部署, jexus
    SAP选择屏幕下拉框实现
    SAP 选择屏幕的上方 (sscrfields) 按钮设置
    SAP笔记
    SAP导出内表数据到excel
    SAP笔记---非-现存任务/请求XXX上的请求锁定
    ABAP知识点笔记
    关联带出字段内容
    REUSE_ALV_GRID_DISPLAY详解
    django发送邮件send_mail&send_mass_mail
  • 原文地址:https://www.cnblogs.com/Grace-zyy/p/7769175.html
Copyright © 2011-2022 走看看