• javascript总结


    一 简介
    1.JavaScript是一种脚本语言,由LiveScript改名而来,Netscape公司为了推广这个脚本语言,利用了java的知名度,两者并没有什么关系。JavaScript是一种基于客户端浏览器的,基于对象、事件驱动式的脚本语言。
    2.java和javaScript的关系
    (1)完全是两个不同的产品,Java是Sun公司推出的面向对象的程序设计语言;JaaScript是Netscape公司的产品,目的是为了拓展Netscape浏览器功能。javaScript是一种可以嵌入Web页面中的解释性语言。
    (2)Java语言最小的程序单位是类定义,JavaScript中充斥着大量函数。
    (3)Java是强类型变量语言,所有的变量必须先声明,才可以使用,所有的变量都有其固定的数据类型;JavaScript是弱类型变量语言,变量在使用前无需声明,由解释器在运行时检查其数据类型。
    3.在实际的使用过程中,还有另一种脚本语言:JScript,由Microsoft公司开发。由于早期JScript和javaScript差异较大, 程序员要为两种浏览器分别编写脚本,后来就诞生了ECMAScript,这是一个国际标准化的JavaScript版本,现在的主流浏览器都会支持这个版 本。
    二 变量
    1.全局变量和局部变量
    在JavaScript中同一个变量可以反复赋值,而且可以是不同类型的变量,但是要注意只能用var声明一次。这种变量类型不固定的语言称为动态语言,与之对应的静态语言,如java,赋值时类型不匹配会报错。
    全局变量:(1)在方法外部声明的变量(2)方法内部,没有加var关键字声明的变量
    局部变量:方法内部,使用var声明的变量
    <script type="text/javascript">
    var a=3; //全局变量
    function test(){
    var a=2; //局部变量
    alert(a);
    }
    test();
    </script>
    结果:2
    如果注释掉var a=2;
    <script type="text/javascript">
    var a=3; //全局变量
    function test(){
    // var a=2; //局部变量
    alert(a);
    }
    test();
    </script>
    结果:3
    若将程序改为:
    <script type="text/javascript">
    function test(){
    c=5; //相当于全局变量
    }
    alert(c);
    test();
    </script>
    结果为:c is not defined
    c虽然是全局变量,但是要先执行函数test(),才能执行到c。也就是说,javascript是由上而下执行的。
    2.变量提升
    JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部:
    function foo() {
        var x = 'Hello, ' + y;
        alert(x);
        var y = 'Bob';
    }
    foo();
    语句var x = 'Hello, ' + y;并不报错,原因是变量y在稍后申明了。但是alert显示Hello, undefined,说明变量y的值为undefined。这正是因为JavaScript引擎自动提升了变量y的声明,但不会提升变量y的赋值。
    对于上述foo()函数,JavaScript引擎看到的代码相当于:
    function foo() {
        var y; // 提升变量y的申明
        var x = 'Hello, ' + y;
        alert(x);
        y = 'Bob';
    }
    由于JavaScript的这一怪异的“特性”,我们在函数内部定义变量时,请严格遵守“在函数内部首先申明所有变量”这一规则。最常见的做法是用一个var申明函数内部用到的所有变量。
    3.变量的作用范围
    JavaScript的变量没有块范围。
    <script type="text/javascript">
    function test(o){
         var i=0;
         if(typeof o=="object"){
              //定义变量j,变量j的作用范围是整个函数内,而不是if块内
              var j=5;
              for(var k=0;k<10;k++){
                   //k的作用范围是整个函数内,而不是循环体内
                   document.write(k);
              }
         }
         //即使出了循环体,k的值依然存在
         alert(k+" "+j);
    }
    test(document);
    </script>
    结果:10   5
    再如:
    <script type="text/javascript">
    //定义全局变量
    var scope="全局变量";
    function test(){
         //全局变量被局部变量覆盖,而此时scope局部变量尚未赋值,故此处输出undefined
         document.writeln(scope+"<br />");
         //定义局部变量,其作用范围为整个函数内
         var scope="局部变量";
         document.writeln(scope+"<br />");
    }
    test();
    </script>
    结果:undefined 局部变量
    三 数据类型
    1.基本数据类型:Number,Boolean,String,Undefined,Null
    Number:整数,小数,NAN,Infinity(正无穷),-Infinity(负无穷)
    Undefined:表示变量声明但是未赋值
    Null:表示一个空的对象引用
    注意:NaN是一个特殊的数值,它是Not a Number三个单词的首字母,表示非数。NaN==NaN返回false。isNaN()函数就专门用来判断某个变量是否为NaN
    例:var a=1/0;并不会报错,会返回Infinity
    2.复合类型
    复合类型是由多个基本数据类型组成的数据体,JavaScript中的复合数据类型有大致3种:Object:对象;Array:数组;Function:函数
    对象:JavaScript是基于对象的脚本语言,它提供了大量的内置对象供用户使用。除了Object外,还有如下常用的内置类:
    Array  Date  Error  Function  Math  Number  Object  String
    数组:数组长度可变,同一数组中的元素类型可以互不相同,访问数组元素时不会越界,访问并未赋值的数组元素时,该元素的值为undefined
    函数:JS的函数声明中,参数列表不需要数据类型声明,函数返回值也不需要数据类型声明,函数可以单独存在,无需属于任何类,函数必须要用function关键字定义
    3.typeof和instanceof
    typeof用来判断数据变量的数据类型,instanceof用来判断某个变量是否为指定类的实例。
    如:
    var a=5;
    alert(typeof(a));   //number
    var b=[1,2];
    alert(b instanceof Array);   //true
    四 数组
    js数组类似于java容器,长度可变,元素类型也可以不同
    <script type="text/javascript">
        var arr=[1,false];
        var result=arr.push(2,true,"abc");
        alert(arr);
        alert(result);
    </script>
    结果为:1,false,2,true,abc            5
    其中,push()函数会向数组中添加元素,并会返回新数组的长度
    <script type="text/javascript">
        var arr=[1,false,2,"dfr"];
        var obj=arr.pop();
        alert(arr);
        alert(obj);
    </script>
    结果:1,false,2                   dfr
    其中,pop()函数可以从数组的尾部移除一个元素,并返回移除的元素值
    shift()函数从头部移除一个元素,unshift()函数从头部插入多个元素,并返回新数组的长度
    <script type="text/javascript">
        var arr=[1,2,4,6,3];
        arr.splice(1, 2,3,4,5);
        alert(arr);
    </script>
    结果:1,3,4,5,6,3
    其中,splice()的第一个参数表示起始位置,第二个参数表示截取的个数,第三个参数以后表示要追加的新元素
    若是只有两个参数,arr.splice(1,2);结果为:1,6,3
    程序若改为:
    <script type="text/javascript">
        var arr=[1,2,4,6,3];
        arr.slice(2,4);
        alert(arr);
    </script>
    结果:1,2,4,6,3
    slice()函数截取范围:左闭右开区间,不操作数组本身,返回截取的内容,而splice方法会操作数组本身
    修改程序:
    <script type="text/javascript">
        var arr=[1,2,4,6,3];
        var result=arr.slice(2,4);
        alert(result);
    </script>
    结果:4,6
    <script type="text/javascript">
        var arr1=[1,2,3];
        var arr2=[2,3,4];
        var result=arr1.concat(arr2);
        alert(result);
    </script>
    结果:1,2,3,2,3,4
    同理,concat()合并粘贴,不操作数组本身
    <script type="text/javascript">
        var arr1=[1,2,3];
        var result=arr1.join('-');
        alert(arr1)
        alert(result);
    </script>
    结果为:1,2,3       1-2-3
    join()方法在每个元素之间加入内容,也不操作数组
    sort()方法正序排序,reverse()方法倒序排序
    五 strict模式
    javaScript在设计之初,为了方便初学者学习,并不强制要求用var申明变量。这个设计错误带来了严重的后果:如果一个变量没有通过var申明就 被使用,那么该变量就自动被申明为全局变量。在同一个页面的不同的JavaScript文件中,如果都不用var申明,恰好都使用了变量i,将造成变量i 互相影响,产生难以调试的错误结果。
    为了修补JavaScript这一严重设计缺陷,ECMA在后续规范中推出了strict模式,在strict模式下运行的JavaScript代码,强 制通过var申明变量,未使用var申明变量就使用的,将导致运行错误。启用strict模式的方法是在JavaScript代码的第一行写上: 'use strict';
    这是一个字符串,不支持strict模式的浏览器会把它当做一个字符串语句执行,支持strict模式的浏览器将开启strict模式运行JavaScript。
    六 函数
    JavaScript是一种基于对象的脚本语言,JavaScript代码复用的单位是函数。函数可以独立存在,JS中的函数完全可以作为一个类使用,并且它还是该类唯一的构造器。函数本身也是一个对象,它是Function实例。
    1.函数的定义
    (1)定义命名函数
    格式:function 函数名(x){ 函数执行体; }
    举例:
    <script type="text/javascript">
    hello('lly');
    function hello(name){
         alert(name+",hello");
    }
    </script>
    函数的最大作用是提供代码复用,将需要重复的代码块定义成函数,可以提供更好的代码复用。
    上例中可以看出,javascript允许先调用函数,然后再定义该函数。在不同的<script>中,必须要先定义,然后再调用。
    实际上采用命名函数的方式,代码的可读性并不好,因为在定义函数时也得到了一个对象。
    (2)定义匿名函数
    var 函数名=function(x){ 函数执行体; };
    程序使用function关键字定义一个函数对象,再将这个对象复制给变量,以后就可以通过该变量来调用这个函数。很多优秀的JS源代码,如jQuery,Prototype.js等等,都是采用这种方式来定义函数的。
    这种方法说明,在javascript中,函数就是一种对象,也就是说,函数也是一种数据类型,参数列表相当于函数的入口,return相当于函数的出口。
    如:
    var abs = function (x) {
        if (x >= 0) {
            return x;
        } else {
            return -x;
        }
    };
    abs(2);
    上述两种定义完全等价,注意第二种方式按照完整语法需要在函数体末尾加一个;,表示赋值语句结束。
    2.函数  方法  对象  类
    函数是javascript编程里非常重要的一个概念,当使用javascript定义一个函数后,实际上可以得到以下4项:
    函数:像java的方法一样,这个函数可以被调用。
    对象:定义一个函数时,系统会创建一个对象,该对象是Function的实例。
    方法:定义一个函数时,该函数通常会附加给某个对象,作为该对象的方法。
    类:定义函数的同时,也得到了一个与函数同名的类。
    如:
    <script type="text/javascript">
    var hello=function(name){
         return name+",hello";
    }
    alert("hello是否是Function对象:"+(hello instanceof Function)+" hello是否是Object对象:"+(hello instanceof Object));
    alert(hello);
    </script>
    结果:true true 直接输出函数本身,则会输出函数的源代码。
    由上可知,在定义一个函数后,有两种方式来调用函数:
    (1)直接调用:总是返回该函数体内最后一条return语句的返回值,若没有return则没有返回值。
    (2)使用new关键字调用:这种方式总有一个返回值,返回值就是一个JavaScript对象。
    <script type="text/javascript">
    function Person(name,age){
         //被this修饰的关键字不再是局部变量,而是该函数的实例属性
         this.name=name;
         this.age=age;
         this.info=function(){
              document.writeln("my name is:"+this.name);
              document.writeln("my age is:"+this.age);
         };
    }
    var p=new Person("lyy",20);
    p.info();
    </script>
    由上可知,js定义的函数可以附加到某个对象上,作为该对象的方法。实际上,如果没有明确指定将函数附加到哪个对象上,则默认将其附加到window对象上,作为window对象的方法。
    <script type="text/javascript">
         //直接定义一个函数,不指定该函数属于哪个对象
         var hello=function(name){
              document.writeln(name+'hello');
         }
         //window调用hello函数
         window.hello('lyy');
        
         //定义一个对象
         var p={
              walk:function(){
                   document.writeln("walk....");
              }
         }
         p.walk();
    </script>
    3.函数的实例属性和类属性
    js中函数不仅仅是一个函数,还是一个类,该函数还是此类唯一的构造器,调用函数时使用new关键字可以返回一个Object对象,该Object不是函数的返回值,而是函数本身产生的对象。因此在JS中,不仅有局部变量,还有实例属性和类属性。
    局部变量:以普通方式声明的变量,包括以var和不加任何前缀声明的变量。
    实例属性:以this前缀声明的变量。
    类属性:以函数名前缀修饰的变量。
    其中,实例属性和类属性是面向对象的概念:实例属性是属于单个对象的,因此必须通过对象来访问;类属性是属于整个类(即函数)本身的,因此必须通过类(函数)来访问。
    <script type="text/javascript">
    function Person(name,national){
         this.name=name;
         var a=0;
         Person.national=national;
    }
    var p=new Person("lyy",''China");
    document.writeln(p.name+Person.national+p.a)
    </script>
    结果:lyy China undefined
    4.调用函数
    JavaScript提供了三种方式来调用函数:
    (1)直接调用:以函数附加的对象作为调用者,在函数后括号内传入参数来调用函数,如上面的p.walk();这种方式也是最常见的方式
    (2)以call()方法调用函数
    直接调用函数比较简单,但是不够灵活,有时在调用函数时还需要动态的传入一个函数引用,为了动态调用函数,就需要使用call方法。
    调用者.函数(参数列表)=函数.call(调用者,参数列表)
    <script type="text/javascript">
         //定义一个each函数
         var each=function(array,fn){
              for(var index in array){
                   //以window为调用者来调用fn函数,将index,array[index]作为参数传递给fn函数
                   fn.call(null,index,array[index]);
              }
         }
         //调用each函数
         each([2,3,4,5],function(index,ele){
              document.write("第"+index+"个元素是:"+ele);
         });
    </script>
    (3)以apply()方法调用函数
    apply()方法和call()方法都可以动态的调用函数,功能基本相似,在用法上有以下区别:
    通过call()调用函数时,必须在括号中详细的列出每个参数;通过apply()动态调用函数时,可以在括号中以arguments来代表所有参数。它 只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数,arguments类似Array但它不是一个Array。
    function foo(x) {
        alert(x); // 10
        for (var i=0; i<arguments.length; i++) {
            alert(arguments[i]); // 10, 20, 30
        }
    }
    foo(10, 20, 30);
    实际上arguments最常用于判断传入参数的个数。你可能会看到这样的写法:
    // foo(a[, b], c)
    // 接收2~3个参数,b是可选参数,如果只传2个参数,b默认为null:
    function foo(a, b, c) {
        if (arguments.length === 2) {
            // 实际拿到的参数是a和b,c为undefined
            c = b; // 把b赋给c
            b = null; // b变为默认值
        }
        // ...
    }
    要把中间的参数b变为“可选”参数,就只能通过arguments判断,然后重新调整参数并赋值。
    5.函数的独立性
    在定义函数时可以将函数定义为某个类的方法或某个对象的方法,但是实际上,函数是独立的,并不属于其他类或对象。
    <script type="text/javascript">
         function Person(name){
              this.name=name;
              this.info=function(){
                   alert("name是:"+this.name);
              }
         }
         var p=new Person("lyy");
         p.info();  //name是:lyy
         var name="lulu";
         p.info.call(window);  //name是:lulu
    </script>
    6.函数的参数传递
    基本类型:值传递。当通过实参调用函数时,传入函数里的并不是实参本身,而是实参的副本,因此在函数中修改参数值并不会影响到实参。
    <script type="text/javascript">
         function change(arg1){
              arg1=10;
              document.write("函数执行中的arg1的值为:"+arg1);
         }
         var x=5;
         document.write("函数调用前的arg1的值为:"+arg1);
         change(x);
         document.write("函数调用后的arg1的值为:"+arg1);
    </script>
    函数调用前的arg1的值为:5
    函数执行中的arg1的值为:10
    函数调用后的arg1的值为:5
    复合类型:值传递。
    <script type="text/javascript">
         function changeAge(person){
              person.age=10;
              document.write("函数执行中person的age值为:"+person.age);
              person=null;
         }
         var person={age:5};
         document.write("函数调用前person的age值为:"+person.age);
         changeAge(person);
         document.write("函数调用后person的age值为:"+person.age);
         document.write("person对象为:"+person);
    </script>
    函数调用前person的age值为:5
    函数执行中person的age值为:10
    函数调用后person的age值为:10
    person对象为:[object Object]
    注意:函数最后一行将person对象直接赋值为null,但是在函数执行结束后,person依然是一个对象,而不是null,这说明person本身 并未传入到changeAge()函数中,传入函数的依然是副本。复合类型的变量本身并未持有对象本身,只是一个引用,该引用指向实际的 javascript对象。当把person复合类型的变量传入changeAge()函数中时,传入的依然是person对象的副本,只是该副本和原 person变量指向同一个javascript对象。
    七 对象
    1.对象
    由于javascript的函数定义不支持继承语法,因此javascript没有完善的继承机制,所以我们习惯上称javascript是基于对象的脚本语言。
    javascript中的对象本质上是一个关联数组,或者说更像是java里的Map数据结构,由一组key-value对组成,这里的value,不仅可以是值(包括基本类型和复合类型),此时的值是函数的属性;还可以是函数,此时的函数就是该对象的方法。
    当访问对象的属性时,可以使用obj.propName的形式,也可以采用obj[propName]的形式,有时必须采用这种形式,如:
    <script type="text/javascript">
         function Person(name,age){
              this.name=name;
              this.age=age;
              this.info=function(){
                   alert('info method!');
              }
         }
         var p=new Person('lyy',20);
         for(propName in p){
              document.writeln('p对象的'+propName+'属性值为:'+p[propName]);
         }
    </script>
    这里必须用p[propName],因为如果用p.propName,会直接访问p对象的propName属性,但是实际上并没有propName属性。
    2.继承和prototype
    javascript虽然也支持类、对象的概念,但是并没有继承的概念,只能通过特殊的方式来扩展原有的javascript类。
    javascript是一种动态语言,它允许自由的为对象增加属性或方法,当程序为对象的某个不存在的属性赋值时,就可以认为是在为该对象增加属性。
    <script type="text/javascript">
    function Person(name,age){
         //被this修饰的关键字不再是局部变量,而是该函数的实例属性
         this.name=name;
         this.age=age;
         this.info=function(){
              document.writeln("my name is:"+this.name);
              document.writeln("my age is:"+this.age);
         };
    }
    var p1=new Person("lyy",20);
    p1.info();
    var p2=new Person("lulu",23);
    p2.info();
    </script>
    上面这种为Person类定义info方法相当不好,主要有两个原因:
    性能低下:每次创建Person实例时,程序依次向下执行,每次都会创建一个新的info函数,会造成系统内存泄漏,引起性能下降。
    使得info函数中的局部变量产生闭包:闭包会扩大局部变量的作用域,使得局部变量一直存活到函数之外的地方。
    <script type="text/javascript">
    function Person(){
         var locVal="lyy";
         this.info=function(){
              //此处形成闭包
              document.writeln("locVal的值为:"+locVal);
              return locVal;
         };
    }
    var p=new Person();
    var val=p.info();
    //输出val返回值,该返回值就是局部变量locVal
    alert(val);
    </script>
    程序的最后一行可以发现,即使离开了info函数,程序也可以访问到局部变量的值。为了避免这种情况,通常不建议在函数定义中直接为该函数定义方法,而是 建议使用prototype属性。javascript的所有类都有一个prototype属性,当我们为javascript类的prototype属 性增加函数、属性时,可以视为对原有类的扩展。增加了prototype属性的类继承了原有的类,这就是javascript所提供的伪继承机制。
    <script type="text/javascript">
    function Person(name,age){
         //被this修饰的关键字不再是局部变量,而是该函数的实例属性
         this.name=name;
         this.age=age;
         this.info=function(){
              document.writeln("my name is:"+this.name);
              document.writeln("my age is:"+this.age);
         };
    }
    var p1=new Person("lyy",20);
    p1.info();
    Person.prototype.walk=function(){
         document.writeln(this.name+'慢慢走');
    }
    var p2=new Person('lulu',23);
    p2.info();
    p2.walk();
    //此时p1也具有了walk方法
    p1.walk();
    </script>
    上面的程序实际上是用prototype为Person类增加了一个walk方法,这样会让所有的Person实例共享一个walk方法,而且该walk 方法还不在Person函数之内,因此不会产生闭包。注意:javascript并没有提供真正的继承,当通过某个类的prototype属性动态的增加 属性或方法时,其实质是对原有类的修改,并不是产生一个新的子类。
    <script type="text/javascript">
         Array.prototype.indexof=function(obj){
              var result=-1;
              for(var i=0;i<this.length;i++){
                   if(this[i]==obj){
                        result=i;
                        break;
                   }
              }
              return result;
         }
         var attr=[4,5,7,-2];
         alert(arr.indexof(-2));
    </script>
    3.创建对象
    主要有3种方式:
    (1)使用new关键字调用构造器创建对象
    <script type="text/javascript">
    function Person(name,age){
         this.name=name;
         this.age=age;
         this.info=function(){
              document.writeln("my name is:"+this.name);
              document.writeln("my age is:"+this.age);
         };
    }
    var p1=new Person("lyy",20);
    p1.info();
    </script>
    (2)使用Object直接创建对象
    <script type="text/javascript">
         var myObj=new Object();
         myObj.name="lyy";
         myObj.age="20";
         myObj.info=function abc(){
              document.writeln("my name is:"+this.name);
              document.writeln("my age is:"+this.age);
         }
         myObj.info();
    </script>
    (3)使用JSON语法创建对象
    JSON:JavaScript Object Notation,使用JSON可以避免书写函数,也可以避免使用new关键字,可以直接创建一个javascript对象。
    person={
         name:'lyy',
         age:20,
         info:function(){
              document.writeln("my name is:"+this.name);
              document.writeln("my age is:"+this.age);
         }
         schools:['小学','中学','大学'],
         parents:[{name:'father',age:60,address:'江苏'},{name:'mother',age:58,address:'上海'}]
    }

  • 相关阅读:
    c++调用win32API控制打印机打印
    php socket 通信
    [SDOI2015][BZOJ3991] 寻宝游戏|set|dfs序|虚树|树上倍增LCA
    [NOI2015][BZOJ4195] 程序自动分析|并查集|离散化
    [NOI2015][BZOJ4196] 软件包管理器|树链剖分
    [HEOI2014][BZOJ3611] 大工程|虚树|树型dp|dfs序|树上倍增LCA
    [Usaco2007 Mar][BZOJ1638] Cow Traffic 奶牛交通|动态规划
    [HDU2222]Keywords Search|AC自动机
    [POI2007][BZOJ1103] 大都市meg|dfs序|树状数组
    [Usaco2007 Dec][BZOJ1690] 奶牛的旅行|分数规划|二分|SPFA
  • 原文地址:https://www.cnblogs.com/lyy-2016/p/5944555.html
Copyright © 2020-2023  润新知