javascript高级程序设计 读书笔记1

时间:2023-03-08 15:59:48
javascript高级程序设计 读书笔记1

第二章  在HTML中使用JS

  加载JS有三种:行内,head头部和外部链接JS   最好使用外部链接<script src="example.js" ></script>(推荐),在script标签中不需要放任何代码,放了也会被忽略。也可以使用<script src="example.js" /> 但是语法不符合HTML规范  所以不要这样写。

  在传统做法中,script放在head中,但是会等到加载完JS再执行DOM,页面会延迟和遇到影响执行条件的语句,所以可以用defer,async设置属性 和window.onload来延迟执行,defer,async属性只适用于外部脚本,标记为async的脚本不一定回按照指定他们的先后顺序执行,现在web应用程序一般把全部的JS引用放在body元素中页面内容的后面。 <body>………………<script src="##"></script></body>。在不支持JS的浏览器中加入<noscript>内容</noscript>,可是在给在浏览器上显示提示内容

  使用外部链接JS代码的优点: 可维护性   可缓存   适应未来。

第三章 基本概念

  1.ECMAScript中的一切都区分大小写。

  2.标识符的第一个字符必须是字母、下划线或$,其后可以试字母、下划线、美元符号、或数字。标识符采用驼峰大小写格式(第一个字母小写,剩下的每个单词的首字母大写),不得使用关键字和保留字

  3.注释    单行注释   //注释内容     多行注释/*内容*/

  4.语句一一个分号结尾。没有分号也是可以的,但是为了程序的长远考虑,要求必须在语句的结尾加上分号。

  5。ES中变量是松散类型的,可以保存任意数据类型。var定义的变量是定义该变量的作用域中的局部变量。如果没有用var就为全局变量,全局变量是魔鬼,一定要避免。

  6.ES中有5种简单数据类型:Undefined、Null、Boolean、Number、String和一个复杂的数据类型Object,typeof操作符可以用来检测基本类型数据。typeof null会返回object,因为null被认为是一个空的对象的引用。

  7.使用var声明变量但是没有初始化,其值为undefined。但是未定义的变量的值与undefined的值是不一样的。使用未定义的变量会为not defined,但是用typeof检测的时候他们的值是相等的,

    var a; alert(typeof a);//undefined    alert(typeof b); //undefined

  8.Null的值表示一个空对象指针,如果定义的变量准备用于保存对象,则最好将该值赋值为null。实际上undefined是派生与null的 用typeof检测的时候两个值相等。

  9.Booloean类型的字面值是true和false (区分大小写),True 和False则为普通 的标识符,对任意数据调用Boolean()函数总会返回一个布尔值。其中 false 、""(空字符串)、0和NaN、 null undefined在转为布尔值的时候是false

  10.Number类型不区分整数与浮点数,认识八进制、十进制和十六进制、默认为十进制。小数点前面可以没有整数但是不推荐使用,由于浮点数占用内存是整数的两倍,所以ES会将数据值尽量转换为整数。数值范围在Number.MIN_VALUE到Number.MAX_VALUE之间,其他的为正无穷或者负无穷(=-  Infinity),可以用isFinity( num )函数来检测num是否是有穷数

  11.NaN(Not a number)用于表示一个不是数值的值。 任何值除以0返回NaN,(实际上只有0/0的时候返回NaN,正数除以0得Infinity,负数除以0得-Infinity)任何涉及NaN的操作用都会返回NaN,并且不与任何值相等,包括本身、可以用isNaN(num) 来确定参数是否“不是数值”。

  12.ES中有3个函数可以把非数值转换为数值:Number(),parseInt(),parseFloat().

    Number()可以用于任何数据类型,另外两个函数用于讲字符串转换为数值。Number()转换undefined值的数字的以后返回NaN,忽略前导0;可以转换十六进制,如果是对象,依次调用valueOf(),toString()直到得出数值。Number()转换的时候比较复杂且不合理,所以经常用parseInt()和parseFloat().

    parseInt()忽略前面的空格,直到找到非空格字符串,如果第一个字符不是数字或者符号,返回NaN。如果是数字或符号,会一直解析下去,直到不满足要求。能识别八、十、十六进制,可以加入第二个参数作为进制数   var num = parseInt("AF",16);//175        var num = parseInt("10",2);//2

    parseFloat()从第一个字符开始解析每个字符,一直解析到末尾,或者遇到一个无效的浮点数字字符为止。忽略前导0;只识别十进制。

  13.String由单双引号表示“ ”,‘’,但是左右引号必须要相同匹配。要将一个值转换为字符串有两种方式:toString()、String()

    toString()返回相应值的字符串表现,null 和undefined没有这个方法。一般不需要传递参数,但是可以传递一个参数来表示要转换成的进制。10.toString(2);//"1010",默认为10进制

    在不知道是否为null或者undefined的情况下,可以用String();null 和undefined返回null和undefined。

  14.Object是一组数据和功能的集合,通过执行new操作符后跟要创建的对象类型名称来创建,并可以为其添加属性和方法。由于ES中一切都是基于对象的,所以Object是所有它的实例的基础,Object类型所具有的任何属性和方法也同样存在与更具体的对象中。
   constructor 保存着用于创建当前该对象的函数(构造函数)

   hasOwnProperty(propertyName)  用于检查给定的属性在当前对象实例中是否存在,property必须以字符串形式指定。eg:o.hasOwnproperty("name");

   isProperty(object) 检查传入的对象是否是传入对象的原型(是否是原型)。

   propertyIsEnumerable(propertyName)"检查给定的属性能否用for in来枚举,参数必须是字符串。

     toLocaleString()

     toString()

   valueOf()返回对象的字符串、数值或者布尔值表示

以上属性是所有对象都具有这些基本的属性和方法。
  操作符+语句 (略);

  15.函数是核心的概念。通过函数可以封装任意多条语句,可以在任何地方、任何时候调用。ES通过关键字function来声明,eg:

                            function functionName(arg0,arg1,.....,argN){

                   statements;

                }

  函数通过函数名来调用,要加上(),eg:functionName(arguments[]);不需要指定是否返回值,但是任何时候任何地方都可以通过return 语句来现实返回值,执行完return语句之后停止并立即退出,return语句之后的语句不会执行。return也可以不带有返回值,此情况下返回undefined,这种用法一般用在需要提前停止函数而又不需要返回值的情况。推荐的做法是要么让函数始终都返回一个值,要么永远都不要返回值,否则会给调试代码带来不便,

  函数不在乎参数的类型和数量,原因是ES中的 参数在内部是用给一个类数组来表示的,函数体内可以通过arguments对象来访问这个参数的数组。第一个参数为arguments[0],第二个为arguments[1]……………,可以使用arguments.length来查看参数的个数,arguments的值永远与对应命名参数的值保持同步,而且其长度是由实际传入参数的个数决定的,与定义函数时的命名参数无关。命名的参数只提供便利,但是不是必需的。

  ES中,函数是没有重载概念的,同名函数的后一个会覆盖前面的一个。

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

  1.ES变量分为两种:基本类型值和引用类型值。基本类型值是指简单的数据段,而引用类型值指那些可能由多个值构成的对象。基本类型值在内存中占固定大小的空间,所以保存在栈中,而引用类型的值是对象,保存在堆内存中,指向其的指针保存在栈中,

  2.5中基本数据类型:number string boolean null undefined是按值访问的,可以操作保存在变量中的实际的值;引用类型的值是保存在内存中的对象。JS不能直接操作对象的内存空间,只能操作对象的引用,引用类型是按引用访问的。 

  3.对于引用类型的值可以增删属性和方法,如果对象不被销毁或者这个属性/方法不会删除,则这个属性/方法将一直存在。但是不能给基本类型值添加属性和方法,因为添加属性后,在执行下一行代码的时候这个属性就会被立即销毁。只能给引用类型值动态的添加方法和属性。

  4.在复制变量值的时候,基本类型值会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。

      eg:  var num1 = 5;  var num2 =num1;

  num1和num2是完全独立的,这两个变量可以参与任何操作而不互相影响。javascript高级程序设计 读书笔记1

  当复制引用类型的时候,同样也会将存储在变量对象中的值复制一份放到为新变量分配的空间中,只不过这个值是一个指向对象的指针,复制操作结束后,两个变量实际上将引用同一个对象,其中一个变量的改变,会影响到另外一个对象。

      eg: var obj1 = new Object();

        var obj2 = obj1;

        obj1.name = "Andy";javascript高级程序设计 读书笔记1

        alert(obj2.name);//Andy

  5.传递参数 

    ES中所有函数的参数都是并且只能是按值传递的,把实参复制给形参就和把一个变量值复制到另外一个变量一样。在向参数传递基本类型的值时,被传递的参数会被复制给一个局部变量(就是arguments对象中的一个元素);在向参数传递引用类型的值时,会把这个值的内存中的地址复制给一个局部变量,因此这个局部变量的变化会反映到函数的外部。

          function addTen(num){      //num实际上是函数的局部变量

               num+=10;          

              return num;

            }

          var count = 20;

          var result =addTen(count);  //num = count; addTen(num);

          alert(count);//20       //num和count是互相独立的

          alert(result);//30

 当传递的参数为引用类型时: function setName(obj){

                obj.name = "Andy";

              }

              var person = new Object();  //创建一个person对象

              setName(person);      //obj = person 传递的是指针 这个对象是按值传递的 但是obj也会按引用来访问同一个对象

              alert(person.name);//Andy

             function setName(obj){

                obj.name = "Andy";

                obj = new Object(){

                  obj.name="zhou";

                }

              }

              var person = new Object();  

              setName(person);     

              alert(person.name);//Andy

         如果person是按引用传递的,那么person就会自动修改name指针,指向zhou。这说明即使在函数的内部修改了参数的值,但是原始的引用仍然没有改变,实际上,当在函数内部重写obj的时候,这个变量引用的就是一个局部对象,而这个对象会函数执行完毕以后会被立即销毁,所以无法访问到zhou.

  6.检测操作符typeof是确实一个变量是字符串、数值、布尔值还是undefined的最佳工具。通常想要知道某个值是什么引用类型用instanceof    eg:     person instanceof Object//变量person是Object吗     colors instanceof Array//color是数组对象吗

  所有的引用类型都是Object的实例,instanceof始终返回true  而检测基本类型的时候始终返回false  因为基本类型不是对象

  7.执行环境定义了变量或者函数有权访问的其他数据。每个执行环境都有一个独立的变量对象,环境中所有的变量和函数都保存在这个对象中,这个对象无法访问,但是解析器在处理数据的时候会在后台用到它。全局执行环境是最外围的执行环境,在web浏览器中,window为全局环境。某个执行环境中的所有代码执行完以后,该环境就会被销毁,保存在其中的所有变量和函数的定义也随之销毁。

  执行环境用栈来表示,执行流进入一个函数,函数的环境就被push到环境栈中,执行完毕以后就会被POP出来,把控制权交还给之前的执行环境。

  当代码在一个环境中执行的时候,会创建变量对象的一个作用域链,保证对执行环境有权访问的所有变量和函数的有序访问。

  标识符解析是沿着作用域链一级一级地搜索标识符的过程,搜索过程始终从作用域链前端开始,然后逐级地向后回溯。查询标识符就是从作用域的前端开始,向上逐级查询与给定名字匹配的标识符。如果局部环境中存在着同名标识符,就不会使用位于父环境中的标识符。访问局部变量要比全局变量快。

  内部环境可以通过作用域链访问所有的外部环境,但是外部环境不能访问内部环境中的任何变量和函数,这是单向访问的模式,环境之间的联系是线性的、由次序的。

  8.可以通过try-catch语句的catch块和with语句来延长作用域链。

  9.ES中没有块级作用域的概念。

    eg:for(var i = 0 ; i < 10 ; i ++){                                     可以看成   var i = 0;//全局变量

      doSomeThing(i);                         for(i<10;i ++){doSomeThing(i);}

      }                                  执行完for语句过后,i的最终值是10;

      alert(i);//10                            alert(i);//10

  if 和for语句都没有块级作用域,var 声明的变量会自动添加到最近的环境中,如果没有用var就会自动变成全局变量。但是建议在初始化变量之前一定要先声明。  

  10.垃圾收集   JS具有自动垃圾收集机制     1.标记清除 (主流的垃圾收集算法)  2.引用计数(容易导致循环引用)

    解除引用:一旦数据不再有用,最好通过设置其值为null来释放引用  这一做法适合大多数全局变量和全局对象的属性。局部变量会在他们离开执行环境时自动被解除引用。解除引用的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收。