Javasript高级程序设计学习笔记一



 1、复制变量值与参数传递

 

函数都有一个arguments对象,函数的参数就是这个对象的一个元素,该对象类似数组,可以通过数组访问的方式访问其中的元素。而所谓的函数的参数定义,就是将对应位置的arguments起了一个名字,便于在函数中引用,因此:

函数的参数是函数的局部变量。

函数传值的过程,就是将 外部变量的值 复制到 arguments的某个元素 中,该元素是函数的局部变量。
换言之,JS函数都是按值传递,无论是基本类型还是引用类型。虽然引用类型是按值传递给函数内部,但是在函数内部访问对象时依然按引用访问。

举个例子:

object1=object2.将object2复制给object1,此时是将object2的指针创建一个副本,然后将这个副本赋值给object1,此时object1,object2指向同一个对象。

function f (o){
   o.name="a";
   o=new Object();
   o.name="b";
}
   var p=new Object();
   f(p);
   alert(p.name);//"a"

因为对象p将值传给了o,即将对象p指向堆空间的指针创建了一个副本,并赋值给了o,这样在给o的属性赋值时,会按引用找到对象,从而改变了那个对象的属性的值。此时,p的属性name也同样被改变了,因为p本来就跟o对应的同一个对象。

而当o=new Object时,又将新创建的Object的指针创建了一个副本,将这个副本给了o,此时o.name,按引用找到的对象就是new Object新创建的对象了。由于函数的参数是函数的局部变量,函数执行完后,该参数就被清除了。

 

基本变量赋值时,也是给其创建一个副本,然后进行赋值,两个变量虽然值相同,但是没有什么关系。而传递参数时也是一样,因为函数传参的本质是将 外部的值 复制到 参数变量中。I

 

 

2、执行环境和作用域

执行环境定义了变量或函数有权访问的其他数据。每个执行环境都有一个环境变量,称之为变量对象,环境中所定义的变量和函数都保存在其中。有一个最外围的执行环境称为全局环境。其他环境都是在一个函数内的局部环境。在Web浏览器中,最外围的环境是window,每个函数都有一个自己的环境。

作用域链】当代码在环境中执行时,会创建一个变量的作用域链,当访问一个变量或函数时,会沿着当前执行环境向外查找,直到找到最外层,如果没有找到,则报错。

 

 Javasript高级程序设计学习笔记一

 

 

   var 变量=1;

   fuction 函数1(){

      var 函数1里的变量=变量;

      function 函数2(){

         var 函数2里的变量=函数1里的变量;

         函数1里的变量=变量;

         变量=函数2里的变量; 

    }

    函数2();

  };

  函数1(); 

  最里层的函数2可以访问该函数外部环境中的所有变量。但是外部环境不能访问内部环境的变量。即只能从里往外检索。

 

   【函数赋值】如果用var定义,则将变量存入最近的执行环境的变量对象中,其作为局部变量。没有用var定义的变量,会存入全局执行环境的变量对象中,该变量就是全局变量。

 

3、没有块级作用域

   类似于if(){  }, for(){} 这样的块,其内部定义的变量,比如for(var i =0;i<10;i++)中的i,在for循环之外还是有效的,这点与Java不同

 

4、引用类型的值和引用类型

      引用类型的值(对象)是引用类型的一个实例。引用类型是一种数据结构,包含数据和功能。引用类型 相当于类,但是不具有其他oo语音的特征,因此被称为 对象定义 更确切,因为它描述的是 一类对象 所具有的方法和属性。

 

      Object类型是JS内置的一种引用类型。

    【对象创建】  

     var p=new Object();//()可省略,但不推荐

      p.name="可以";// 给对象增加属性。

      如果需要定义大量属性,可以使用对象字面量表示法:

     var p={

      name:"Nike",

      age:"18"

    };

 

    var p={};与var p=new Object()等价。但不会调用Object的构造函数。

    【访问属性的方法】访问属性除了使用圆点法——object.propertyname外,还可以使用方括号 object[propertyname],使用场景是当propertyname是动态的,比如通过遍历对象属性赋值或取值时。

 

 

     Array类型

     【创建数组】 var a=new Array();

              参数可以是n个:

              n=1:如果是数字,表示创建数字表示的长度的数组。如果是非数字,表示只包含这个值的单值数组

               n>1:表示包含n个值的数组,这n个值就是这n个参数,比如new Array("a","b","c")

               n=0:数组是动态可扩展的。

             其中new 可以省略,变成 var a=Array;

 

          数组字面量:var a=["a","b",""];

          数组的length不是只读的

 

         【栈方法】 a.push("a","b");在数组末尾追加;a.pop() 返回数组最后一项,该项从数组中被去掉。

          【队列方法】a.shift();返回数组第一项,该项从数组中被去掉;a.unshift(“a”,"b")在数组前面添加。

         【反转数组】a.reverse();

          【数组排序】a.sort默认升序排列。 a.sort(compare)  其中compare可以实现比较方法function compare(value1,value2)

            【操作方法】concat slice  splice 

    

     Function类型

     Function类型也是引用类型,那么每个函数都是Function类型的实例。而且有自己的属性和方法(所以函数里也可以定义函数)。由于函数是Function类型的对象,对象可以赋值给不同变量,因此同一个函数可以有不同的名字(赋值给不同变量),这个名字是找到函数去执行的指针而已。

    函数声明语法定义  function f(){

 

    }与 函数表达式定义(将函数的指针复制给变量f)

    var f=function(){

 

    }相同。区别是:在全局执行环境加载数据时,会首先加载函数声明,因此函数的执行在函数声明前后没有关系。而函数表达式是代码执行到表达式时才会加载,因此函数执行必须在表达式之后。

 

     f传递的是函数的指针。f()表示函数执行。

 

    【this】函数内部有一个特殊对象this,其值与函数执行环境有关。this引用的是执行函数操作的对象。如果在全局环境中执行,那么this就引用的是全局环境中的变量;如果在函数是一个对象的方法,那么this引用的就是对象的属性。

              c="a";

              function   f(){alert(this.c);};

              f(); //相当于window对象执行f,因此其中的this引用的是window,this.c="a"

              var o={c:"b"};

              o.f=f;  //将f的指针赋给o的函数f

              o.f();  //执行时指向f函数,此时this引用的是o,因此this.c=“b”

              由于函数是Function类型的对象,因此无论是在哪个环境下执行的f,都是同一个函数。

              

     

5、原型(Prototype)

     每个函数都有一个原型属性,该属性是一个对象。用途是包含可以由特定类型的所有实例共享的属性和方法。每个原型属性都会自动获得一个constructor(构造函数)属性,这个属性包含一个指针,该指针指向Prototype属性所在的函数。(这样函数和原型属性双向引用)

     当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性__proto__),指向构造函数的原型属性。(这样实例可以找到构造函数的原型属性,间接与构造函数关联)

 

    函数都是对象。构造函数是对象,构造函数通过new创造出的函数也是对象。

   //函数表达式法定义函数,

    var f=function(){}; //f是一个对象。等价于 var f=new Function(参数0-n,函数体);  函数是一个对象,函数名是一个指针

    f();//执行在window环境下。

    function F(){}; //与var F=function(){}等价

    F.prototype.name="a";

    F.prototype.sayName=function(){alert(this.name)};

    F();//F自己本身就是个函数,可以执行,这样执行就是成为window的对象

    var o=new F();

    o.sayName(); //o是一个对象,o执行F的内部的一个函数sayName

 

    JS原生的Function函数也是个对象,也是通过new Function可以实例化成一个个function函数对象。

 

  6、闭包和私有作用域

       闭包就是能够访问外部变量,但是其内部变量对外部不可见。

    (function(){

        私有作用域

    })();   

    上面这个表示一个匿名函数,后面那对括号表示函数立即执行,和var f=function(){}; f();一样。只是这个函数没有名字,也就没法调用,在函数外加上括号后,变成了表达式,就可以执行了。

  

     var f=(function(){})();同理。

     这个用法很普遍,特别对于大型项目,防止过多变量污染全局空间,也可以解决没有块作用域的情况(前面讲的for语句的例子):http://segmentfault.com/q/1010000000135703

 

   

 

你可能感兴趣的:(javasript)