代码改变世界

《javascript高级程序设计》第二版 读书笔记

2013-03-01 19:26  臭小子1983  阅读(418)  评论(0编辑  收藏  举报

第一章   JavaScript简介

一、javascript组成部分

1、核心(ECMAScript)      2、文档对象模型(DOM)        3、浏览器对象模型(BOM)

 

第二章    HTML中使用JavaScript

一、<script>元素

<script>的5个属性:

1、charset:表示通过src属性指定的代码字符集。

2、defer:表示脚本可以延迟到文档完全被解析和显示之后在执行。只有IE支持

3、src:文件路径

4、type:表示使用脚本语言的类型,<script>默认的是text/javascript,所以可以不用写.

 

使用<script>的两种方式:

1、内嵌

  可以写直接写到html文档中,<script> ... </script>

2、引用外部

  通过src来引用外部的js文件,好处是通过src加载一次可以缓存到机器中,从而减少了服务器的压力

  <script src="...."></script>

 

二、标签的位置

  引用在<head>中:引用在head标签中页面的css也会在这里引用,页面上来会载入css和javascript的文件,javascript在下载到浏览器后会进行解析和执行,在这个过程中会导致延迟,这样页面会一片空白等javascript解析完后在往下执行代码,

  所以避免这个问题一般会把javascript放到</body>之前,这样在解析javascipt之前先将页面的内容呈现出来,令用户感觉页面打开的速度也快了.

 

三、延迟脚本

  这个属性用途表明脚本在执行时不会影响页面的构造,与将javascript文件放到</body>之前一个意思,但这个属性有兼容性问题

      <script src=”” defer = “defer”></script>

 

四、不推荐使用的语法

  <script><!--

      ...... 

    --></script>

  加入<!--  -->注释,这个是当初了为解决一些不支持javascript的浏览器,但现在所有浏览器都支持,所以就没必要加入

 

五、嵌入代码与外部文件

  在HTML中内嵌代码虽然没有问题,但还是建议使用外部文件,这样的目的

  1、代码可维护    2、文件可缓存    3、可适应未来

 

 

六、文档模式

  IE5.5引入了文档模式的概念,最初的文档模式有:混杂模式标准模式

  混杂模式会让ie的行为与ie5相同,而标准模式让ie的行为更接近标准行为。

        

     标准模式:

         <!—HTML 4.01 严格模式 -->

         <!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” “html://www.w3.org/tr/xhtml1/DTD/xhtml1-strict.dtd”>

 

         <!—HTML XHTML 1.0 严格型 -->

         <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN” “html://www.w3.org/tr/xhtml1/DTD/xhtml1-strict.dtd”>

 

    <!—HTML XHTML 1.0 过渡型 -->

         <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “html://www.w3.org/tr/xhtml1/DTD/xhtml1-strict.dtd”>

 

     <!—HTML XHTML 1.0 框架型 -->

         <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Framest//EN” “html://www.w3.org/tr/xhtml1/DTD/xhtml1-strict.dtd”>

 

         IE8引入了一个叫做“超级标准模式”,标准模式使用IE7呈现的引擎,而超级标准模式则是IE8的默认文档模式,可以在IE8使用<meta>值可以关闭其默认文档模式。

         <meta http-equiv=”X-UA-Compatible” content=”IE=7” />

 

五、<noscript>元素

  如果浏览器不支持javascript或者支持被禁用时,就会执行<noscript>元素,但现代浏览器基本支持.

  <noscript>

     <p>浏览器不支持javascript</p>

  </noscript>

 

 

第三章   基本概念

一、语法

  1、区分大小写:var test和 var Test是两个变量

  2、标识符:指的是变量的名和函数、属性或参数的名符

        第一个字符必须是字母、_、或$符号,可以使用驼峰格式,如:firstServer

  3、注释: // 单行注释    /*  多行注释 */

  4、语句:var min = a + b; 如果没有最后的分号也是正确的,但不推荐这么写 var min = a + b

        if(a==0){ ....  }

        if(a == 0)    // 没有花括号也是可以的,但不推荐这样写,容易出错

         alert("正确")

二、变量:

  1、ECMAScript变量是松散类型,所谓松散类型就是可以存储任何值,可以是变量、字符串、函数、对象。

      定义变量时使用var,如果不使用var来创建变默认成全局变量

      function test(){

        message = "hi";

      }    alert(message);    // 这时候还是会弹出hi

   2、局部变量:在函数中使用的变量是局部变量,外界不可调用局部变量,这个变量在函数执行完退出后会自动销毁,释放内存。

      funciton test(){

        var message = "hi";    // 局部变量

      }

      test();

   3、定义多个变量可以使用逗号分开:var messgae="hi", found = false,  max = 20; 这样可以提高可读性

二、数据类型

  1、ECMAScript有五种数据类型:整型、字符型、布尔型、undefined、null,function

  2、typeof操作符,检测变量的数据类型,String、number、boolean、null,undefined、function、object

      1) undefined:在使用一个变量未初始化时,这个变量的值就是undefined,调用未定义的变量时会报错显示 is not undefined,注意:值是undefined和报undefined的错误是不同的.

          var message;

          if(message === undefined){

            alert("成功")

          }

      2) null:null表示一个空对象的指针

          var obj = null;  alert(typeof obj);    // 返回object一个对象

          注意:if(undefined == null) // 返回的是true  if(undefined === null)  // 返回的是false      

      3) boolean:布尔,两个值true和false

      4)number:来表示整数和浮点数,

          NaN:非数值,isNaN()如果不是非数值返回true

            alert(isNaN(NaN));    // 返回true;

            alert(isNaN(10));      // 返回false;

          alert(isNaN("10"));    // 返回false可以初转成数值10

          alert(isNaN("aaa"));    // 返回true;

          alert(isNaN(true));     // 返回False 可以将true将成1

        5)三个函数可以把非数值转成数值:Number()、paresInt()、paresFloat();

      6)String:字符串可以用"和'号

          转成字符串:1、var age = 111;  age.toString();  

                2、 var num = 10; num.toString();   // 返回"10"

                  var num = 10; num.toString(2);  // 返回二进制

                  var num = 10; num.toString(8);  // 返回八进制    还可以返回十进制、十六进制

      7)Object:

 

隐式类型转换

  alert(200 == "200");    // 输出true;

  alert(200 === "200");   // 输出false;

 

三、操作符

  1、一元操作符:递增和递减,i++, i--

  2、布尔操作符: 1、!逻辑非,如果表达式为真则返回假,否则返回true

 

四、布尔操作符

  1、!逻辑非,如果为真结果为假             2、&& 逻辑与  表达式两端都为真返回为真               3、|| 逻辑或 表达式两端有一个为真返回为真

 

五、基础操作符

  1、运算操作符:+ 加、 - 减、 *  乘、 / 除、 % 求余

  2、关系操作符:小于(<)、大于(>)、小于等于(<=)、大于等于(>=)、等于(==)、全等于(===)、不全等于(!==)

  3、逗号操作符:var a=0, b=1, c=2; 一个语句中可以执行多个操作.

 

六、语句:

  1、if... else... :

  2、do... while...:是一种后测试语句,先执行循环体的内容在去看是否满足条件。

  3、while:循环语句,前测试语句,先判断是否满足条件在执行语句。

  4、for:也是前测试语句,for( ; ;)一个死循环

  5、for... in ..:迭代语句,可以用来枚举对象的属性,

  6、break:结束循环

  7、continue:结束此次循环继续下一次循环

  8、switch() ... case:流控制语句

 

七、函数:

  函数可以封装任意条语句,可以在任何地方调用它使用function来声明

  1、arguments对象,将函数参数做为一个数组返回

  function add(a, b, c){   arguments.length; }  // 返回2  也可以arguments[1]来访问参数b

 

  2、函数重载

    重载,就是同时存在两个名称相同的函数,但它们的接收参数不同或返回值不同;在JAVA中经常会遇到.但在JS中,如果同时存在两个相同的名字的函数,它不会引发错误,但它会真正使用最后一个

    例: function add(a) { return a + 100 }  

         function add(a) { return a + 200 }

       add(100);    // 返回300

 

  3、return语句:函数返回值

 1 function a(){
 2     var b = 10;
 3     var c = 'abc';
 4     return 5 + 6;
 5     alert('abc');
 6 }
 7 
 8 a();    // 不会输出abc
 9 
10 return : 函数返回值。
11     1, 给函数赋一个值。    
12     2, 当函数中碰到return,就会直接跳出函数,不再执行return后面的任何代码。

 

 

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

一、基本类型和引用类型

  变量有两种不同类型的值:基本类型和引用类型

  基本类型:指保存在栈内的简单数据断,这种值完全保存在内存的一个位置.

  引用类型:指保存在堆内存中的对象,意思是变量保存实际上是一个指针,这个指针指向内存的另一个位置. 

 

二、动态属性也是对象属性

1 var person = new Object();
2 person.name = "nice";
3 alert(person.name);         // 返回nice

  将一个对象保存在变量中,增加一个name属性并赋值为”nice”,如果对象不被销毁这个值也不会被删除,这个属性将一直存在。

  删除对象属性delete person.name;

 

三、复制变量值

  如果一个变量向另一个变量赋基本类型值,会在栈中创建一个新值,然后把该值复制到新的变量分配的位置

1 var obj1 = {"name": 11, "age": 22};
2 var obj2 = obj1;
3 obj2.name = "haha";
4 
5 console.log(obj1);        // obj1和obj2都为{"name": "haha", "age": 22};

 

四、参数的传递

         参数的传递其实就是变量之间的传递

 

五、检测类型

         1、typeof 检测数据类型(基本数据类型)

         var  str = “sss”;

         alert(typeof  str);            // 返回String

         如果typeof检测引用数据类型就不管用了,也就是对象,使用instanceof

 

         2、instanceof 检测变量是否是引用类型,也就是对象的属性和方法,如果是返回true;

 1 function Parane(){
 2 
 3 };
 4 
 5 var obj = new Parane();
 6 obj.name = "aa";
 7 obj.say = function(){
 8     alert("bb");
 9 }; 
10 alert(obj instanceof Parane);            // 返回true

 

六、变量作用域

1、变量声明:如果变量在未经声明的情况下创建会认为是全局变量

 1 function add(n1, n2){
 2       var sum = n1 + n2;            // 如果用var 声明变量,变量存在于函数的局部
 3       return sum;
 4 }
 5 
 6 var res = add(10, 20);
 7 alert(sum);     // 返回错误没有这个变量
 8 
 9 function add(n1, n2){
10       sum = n1 + n2;          // 如果不用var来声明变量,执行完add()后会将sum增加到全局中.
11       return sum;
12 }
13 
14 var res = add(10, 20);
15 alert(sum);    // 返回30

 

 1 例1:
 2 var a = 1;
 3 function fn1(){
 4     var a = 5;
 5     alert(a)        // 输出5
 6 }
 7 fn1();
 8 
 9 
10 例2:
11 var a = 1;
12 function fn1(){
13     var b = 4;
14     fn2();
15     a = b;
16     function fn2(){
17         alert(b);        // 4
18         alert(a);        // 1
19     }
20 }
21 fn1();

 

2、搜索标识符

也就是查找变量,当用到一个变量时会查找这个变量的实际代表什么,搜索过程从作用域开始查找,逐级向上查找,

1 var color = “blur”;
2 function getColor(){
3      var color = “rad”;
4      return  color
5 }
6 
7 getColor();        // 返回rad  *查找局部变量要比全局变量要快*  

 

七、拉圾回收机制

      Javascript的所需内存的分配和无用内存的回收实现了自动管理

  局部变量的生命周期:

        函数中的局部变量只在函数执行中存在,会在栈或堆内存中分配一块空间,到函数执行结束时,些时局部变量就会自动销毁.

 

八、内存管理

  分配给web浏览器的内存要比桌面内存要少,处于安全问题,防止运行javascript的网页耗尽内存使系统崩溃

  为了确保性能,优化的最佳方式,就是执行中的代码保存有用的数据,一旦没有用就将其设置为null来释放引用,这个方法叫解除引用。这个做法适用于全局变量和对象属性,局部变量它们在函数执行完后自动被解除引用.

 

九、加载和执行,从编辑到可执行的代码

  1、变量引用的执行顺序

  alert(i);    // undefined

  var i = 10; 

 

  2、函数的执行顺序

  test();    // a

  function test(){ alert("a") }    // 会将test函数进行预编辑

 

  3、函数重载 

1 test()      // 输出b 因为函数预存,并且函数重载 
2 function test(){ alert("a") }
3 var test = function(){ alert("s"); }
4 function test(){ alert("b") }
5 
6 test()      // 输出s
7 test();       // 输出s 

 

 

第五章 引用类型

引用类型是一种数据结构,引用类型也被称为对象定义,

var peron = new Object();       创建Object的引用类型的一个新实例,把它保存在peron变量中,它只为新对象定义了属性和方法。

 

一、引用

  引用实际就是指向对象实际位置的指针.

  几个变量指向同一个对象时,其中一个改变了对象的变量,这种改变是全局的,另一个也会受到影响.

 1 <script>
 2     var obj = {
 3         arg: 0,
 4         show: 1
 5     }
 6 
 7     var n1 = obj;
 8     var n2 = obj;
 9 
10     n1.age = 10;
11     alert(n2.age);        // 10 
12     alert(n2.show);        // 1
13 </script>

 

1 <script>
2     var items = new Array( "one", "two", "three" );
3     var itemsRef = items;
4     //给原始数组添加一项
5     items.push( "four" );
6     alert( items.length == itemsRef.length );      // 相等
7 </script>

 

一、Object类型

大多数引用类型都是object类型的实例.

创建object实例的两种方法:

1、  new

1 var peron = new Object();
2 peron.name = "aaaa";
3 peron.age = "bbbb";

 

2、  对象直接量 {}

1 var peron = {  // 与var peron = new Object()相同
2 
3   name : "aaaa",
4   age : "bbbb" 
5 }

 

----还有一种写方法

1 var peron = {};    // 与var peron = new Object()相同
2 peron.name = "aaaa";
3 peron.age = "bbbb";

 

----直接量也是向函数传大量可选参数的首选

 1 例如:
 2 
 3 function displayInfo(args){
 4     var output = "";
 5     if(typeof args.name){
 6          output = "属性是字符串"
 7   }
 8   return output;
 9 };
10 
11 displayInfo({
12     name : "aaa",
13     age : "29"
14  });

 

二、Array类型

  创建数组:

  1、 arr = new Array()  2、arr = new Array('red', 'blur', 'green');    3、arr = ['red', 'blue', 'grren'];

 

三、Function类型

函数实际上是一个对象,每个函数都是一个Function类型的实例

为什么可以写匿名函数,说白了就是函数也是对象,与引用类型一样具有属性和方法,由于函数是对象,所以函数名实际上也是函数的指针

定义方法:

1 funciton sum(n1, n2){    // 方法一
2   return n1 + n2;     
3 }
4 
5 var sum = function(n1, n2){  // 方法二
6     return  n1 + n2;
7 }

 

--- 另一种函数定义函数的方式是使用Function 构造函数,Function构造函数可以接受任意参数,但最后一个参数为函数主体,不过此方法不推荐

var newFun = Function("n1", "n2", "return n1 + n2");    // 这种方法会导致解析两次
alert(newFun(10, 20));

 

四、函数的内部属性

  arguments:一个数组,奖参数传入这个数组中。

 

五、call和apply

  调用指定的函数,也可以方法能劫持另外一个对象的方法,继承另外一个对象的属性.

  两者的区别是call需要将函数的参数列出来,apply第二个参数是一个数组

 1 function fun1(num1, num2){
 2     return num1 + num2;
 3 }
 4 
 5 function fun2(num1, num2){
 6     return fun1.call(this, num1, num2);
 7 }
 8 
 9 function fun3(num1, num2){
10     return fun1.apply(this, arguments);
11 }
12 
13 
14 var num = fun2(20, 50);
15 var num1 = fun3(100, 200);
16 console.log(num);        // 70
17 console.log(num1);        // 300

 

 

第六章  面向对象的程序设计

一、创建对象

1 var Person = new Object();
2 Person.name = “haha”;    // 对象属性
3 Person.age = 29;      
4 Person.sayName = function(){ // 对象方法
5          alert(this.name);
6 }

创建一个对象,添加了两个属性和一个公用函数

 

1、、销毁对象

  var Person = new Object();

  Person.name = “haha”;    // 对象属性

  Person.age = 29;

  Person = null;    // 将对象消毁

 

2、删除对象的属性

  var Person = new Object();

  Person.name = “haha”;    // 对象属性

  Person.age = 29;

  delete Person.name;  //删除name属性

 

 

二、设计模式

1、工厂模式:用函数来封装,以特定的接口创建对象的

 1 function createPerson(name, age, job){
 2         var o = new Object();
 3         o.name = name;
 4         o.age = age;
 5         o.job = job;
 6         o.syaName = function(){
 7             alert(this.name);
 8         };
 9         return o;
10 };
11 
12 var Person1 = createPerson("nn", 29, "sofeware Exgineer");
13 Person1.syaName();

 

2、构造函数模式:

象Object和Date之类的内置对象,构造函数也是函数,但需要new来创建

 1 function Person(name, age, job){
 2     this.name = name;
 3     this.age = age;
 4     this.job = job;
 5     this.sayName = function(){
 6         alert(this.name);
 7     }
 8 }
 9 var person1 = new Person("哈哈", 20, 0);
10 Person("啊啊", 21, 0);  // 这种调用就需要window.syaName();
11 person1.sayName();
12 
13 // 在另一个对象中调用
14 var o = new Object();
15 Person.call(o, "可呆", 100, 100);
16 o.syaName();

 

3、  原型模式:

每一个函数都有一个prototype原型属性,这个属性是一个对象,用途是包含可以由特定类型的所有实例共享的属性和方法

1 function Person(){}
2 
3 Person.prototype.name = "sss";
4 Person.prototype.syaName = function(){
5     alert(this.name);
6 }

 

三、继承

许多oo语言都支持两种方式:接口继承 和 实现继承

1、只继承方法:

 1 function ClassA(name){
 2     this.name = name;       // 通过参数赋给属性的不可以继承
 3     // this.name = 20;        // 这种可以继承 
 4 }
 5 
 6 ClassA.prototype.sayName = function(){
 7     console.log(this.name);
 8 }
 9 
10 function ClassB(age){
11     this.age = age;
12 }
13 
14 ClassB.prototype = new ClassA();
15 
16 ClassB.prototype.sayAge = function(){
17     console.log(this.age);
18 }
19 
20 var newClassA = new ClassA("lulu");
21 var newClassB = new ClassB(20);
22 newClassA.sayName();        // undefinded
23 newClassB.sayAge ();          // 20        

 

可以通过call来继承属性

 1 function ClassA(name){
 2     this.name = name;
 3 }
 4 
 5 ClassA.prototype.sayName = function(){
 6     console.log(this.name);
 7 }
 8 
 9 function ClassB(name, age){
10     ClassA.call(this, name);    // 继承属性
11     this.age = age;
12 }
13 
14 ClassB.prototype = new ClassA();  // 继承方法
15 
16 ClassB.prototype.sayAge = function(){
17     console.log(this.age);
18 }
19 
20 var newClass = new ClassB("lulu", 20);
21 newClass.sayAge();
22 newClass.sayName();

 

ECMAScript只支持实现继承.

1、  原型链

实现原型链的一种基本模式:

 1 function VideoFirst(){  // 创建对象1
 2     this.name = "aa";
 3 };
 4 
 5 VideoFirst.prototype.syaName = function(){
 6     alert(this.name);
 7 };
 8 
 9 function VideoSecnd(){  // 创建对象2
10     this.say = "bb";
11 };
12 
13 //  VideoSecnd继承了VideoFirst;
14 VideoSecnd.prototype = new VideoFirst();
15 
16 var newVideo = new VideoFirst();
17 newVideo.syaName();         // 返回 aa
18 
19 var newVideo1 = new VideoSecnd()
20 newVideo1.syaName();        // 返回 aa
21 
22 // 超生类
23 // 重新syaName函数,叫超生类
24 VideoSecnd.prototype.syaName = function(){
25     alert("bb");
26 };
27 
28 var newVideo2 = new VideoSecnd();
29 newVideo2.syaName();    // 返回 bb

 

 

第七章  匿名函数

      匿名函数就是没有名字的函数,也称为拉姆达函数

一、函数声明

1、声明函数:

1 function functionName(age0, age1, age2){    // 声明函数调用可以在任意位置
2     alert(“aa”);
3 };

 

2、  将一个函数表达式结果返回给一个变量:

1 var functionName = function(){        // 调用函数表达式必须在之后
2   alert(“aaa”);
3 }

 

3、  创建一个匿名函数并执行

1 (function(n){
2     Alert(n)
3 })(“20”);

 

4、  还可以这么写:但这种函数是没法调用的

1 function(age1, age2, age3){
2       alert(“bbb”);
3 }

 

二、递归

  递归函数是在一个函数内在调用这个函数本身

 1 <script>
 2     var num = 100;
 3     function factorial(){
 4         num -= 1;
 5         if(num <= 0){
 6             alert("已经为0");
 7         }
 8         else{
 9             console.log(num);
10             factorial();
11         }
12     }
13 
14     factorial();
15 </script>

 

 

三、闭包

  闭包:是有权访问另一个函数作用域中变量的函数

  一般局部变量会在函数结束时而自动销毁,而闭包里的变量不会销毁,所以易导致内存泄漏.

1 function comp(){
2     var name = "aa";
3     return  function(){
4         alert(name);    // 可以访问name,外部函数是无法访问函数内部变量的
5     }
6  }    

 

  1、什么是闭包:函数嵌套函数,内部函数可以引用外部函数的变量,参数和变量不会被拉圾回收机制所收回

一个简单的闭包:

 1 function aa(a){
 2     var b = 5;
 3     function bb(){
 4         alert(a);
 5         alert(b);
 6     }
 7    return bb;
 8 }
 9 
10 var c = aa(5);
11 c();

   

2、闭包的好处:1)希望一个变量长期在内在中     2)避免全局变量的污染  3)私有成员的存在

 1 如果想a来存储累加,但又不想超成全局的污染,这时候可以使用闭包,
 2 如果不需要a累加存储数据,直接放到函数内部做局部变量就好了
 3 <script>
 4     var a = 1;
 5     function aa(){
 6         a++;
 7         alert(a);
 8     }
 9 
10     aa();    // 2
11     aa();    // 2
12     alert(a);
13 </script>
14 
15 
16 将上面改成闭包的形势
17 <script>
18     function aa(){
19         var a = 1;
20         return function(){
21             a++;
22             alert(a);
23         }
24     }
25 
26     var cc = aa();
27     cc();    // 2
28     cc();    // 3
29 </script>

 

3、闭包的用法: 1)模块化代码 

 1 <script>
 2     var aa = (function(){
 3         var a = 1;      // 私有变量
 4         
 5         function bb(){  // 私有函数
 6             alert(a);
 7         }
 8         
 9         return function(){  // 公有函数
10             a++;
11             alert(a);
12         }
13     })();
14 
15     aa();
16     aa();
17 </script>

 

4、闭包需要注意的: 1)在IE下会引发内存泄露

 1 <script>
 2     // 内存泄露会导致cpu的运算增加,内存不断的累加页面会死掉,或者缓慢
 3     // 产生内存泄露:一个对象调用事件后,内部函数又调用了这个对象的属性或方法,这样互相调用会导致内存泄露
 4     var box = document.getElementById("box");
 5     box.onclick =  function(){
 6         alert(box.id);      // 这种会产生内存泄露
 7     }
 8 
 9     // 解决方法一:使用后将对象清除
10     var box = document.getElementById("box");
11     box.onclick = function(){
12         alert(box.id);
13     }
14     window.onunload = function(){
15         box.onclick = null;     // 清除对象引用
16     }
17 
18     // 解决方法二:避免内部引用
19     var box = document.getElementById("box")
20     var oId = box.id;
21     box.onclick = function(){
22         alert(oId);     // 将要引用的属性存放在外部变量中
23     }
24 </script>

拉圾回收机制,当函数执行完后变量就会被拉圾回收机制所收回,这样来节省内存

function create(){ var a = "1111"; }

create()

 

三、内存泄漏

闭包在IE中会导致一些问题,闭包作用域中保存着HTML元素,那么就意味着该元素的该元素将无法被销毁。

 1 function assignHandler(){
 2     var element = document.getElementById("some")
 3     element.onclick = function(){
 4         alert(Element.id);
 5     }
 6 }
 7 
 8 // 获取一个元素,在闭包内调用了元素的属性,IE就会存在内存泄漏
 9 
10 解决方法:
11 
12 function assignHandler(){
13     var element = document.getElementById("some")
14     var getId = element.id;             // 获取放到下面
15     element.onclick = function(){    // 这个闭包创建了死循环引用
16         alert(getId);
17     }
18     element = null;                   // 将获取的对象为空
19 }

 

四、解除对匿名函数的引用(释放内存)

var compareName= createCompareName();

compareName = null;  // 解除引用

 

五、this对象

  在全局函数中,this指象的是window

 

六、私有变量

Javascript没有私有成员的概念,所有对象的属性都是公有,不过有私有变量的概念。

任何函数内的变量都是私有,因为外部不可以调用。

1 function add(num1, num2){
2   var sum = num1 + num2;
3   return sum;               // num1, num2, sum都是私有变量
4 };

 

1、  特权方法:我们把有权访问私有变量和私有函数的公有方法称为特权方法。 

 1 function MyObject(){
 2         var ss = "aaa";   // 私用变量
 3 
 4         function privateFun(){
 5             return false;
 6         }; 
 7 
 8         this.publicMyObject = function(){  // 特权方法
 9             alert(ss);
10         };
11 } 
12 var createMy = new MyObject();
13 createMy.publicMyObject();   // 通过构造函数的公用方法来调用私有变量

   

五、静态私有变量

  通过在私有作用域中定义了私有变量或函数,

 

六、模块模式

模块模式是为单例创建私有变量和特权方法,

所谓单例,指的就是一个实例的对象。

创建一个模块模式:

 1 var singleton = {
 3     name : value,
 5     method : function(){
 7          alert(“aa”)
 9   }
10 };

 

另一种单例,有私有属性和方法

 1 var singleton = function(){
 2     // 私有变量和私有函数
 3     var privateVar = 10;
 4 
 5     // 私有函数
 6     function privateFun(){
 7         return false;
 8     }
 9 
10     // 返回对象,可以通过特权方法来访问私有属性和私有方法
11     return {
12         publicVar : 10,
13         publicMethod : function(){
14             privateVar++;
15         }
16     }
17 }()
18 
19 singleton.publicMethod();

 

 

 

第八章  BOM 浏览器对象模型

一、Window对象

         BOM的核心是window对象,它表示浏览器的一个实例。

         网页的任何一个对象、变量和函数,都以window作为其Global对象,

 

         全局作用域:

         全局作用域中声明的变量、函数都会变成window对象的属性和方法。

1 var age = 29;
2 
3 function syaAge(){
4   aert(this.age);
5 };
6 
7 alert(this.age);         // 29
8 syaAge();          // 29
9 window.syaAge();    // 29

 

二、窗口位置

         1、浏览器窗口距屏幕左、上的位置:window.

    screenLeft、screenTop:兼容IE、Safari、Opena、Chome,注:ie是以客户区域而不是浏览器窗口为准

    screenX、ScreenY:FF下兼容

        

         2、移动窗口window

    moveTo(x,y):将窗口移动距屏幕x,y轴的位置

    moveBy(x,y):以当前窗口位置,将窗口移动多少像素

 

     3、窗口大小window

         Window.innerWIdth、window.innerHeight、window.outerWidth、window.outerHeight:兼容FF、Safari、Opena、Chome

         注:innerWIdth、innerHeight、outerWidth、outerHeight中FF、Safari返回浏览器本身窗口

 

         4、获取客户端区域大小:document

         clientWidth、clientHeight:

         document.documentElement.clientWidth;

         document.body.clientWidth;

        

         5、调整浏览器窗口宽、高window

         resizeTo(w, h):

         resizeBy(w, h):

 

 

三、window其它方法

         1、window.open(),window.close():打开和关闭窗口

         2、window.setInterval(fn, timer):按规定的时间不断的执行函数

     window.setTimeout(fn, timer):按规定的时间只执行一次

     window.clearIntervall()、window.clearTimeout();

           

四、location对象

  提供了窗口中加载文档的相关信息

  location它既是window对象的属性也是document对象的属性,window.location和document.location引的同一个对象

  属性和方法:

  1、hash:返回url中的“#”号之后的字符串,如果url中没有#返回空字符串

  2、host:返回端口号, wan.renren.com:8080  返回8080

  3、hostname:返回主机名称,wan.renren.com

  4、pathname:返回目录或文件名称,wan.renren.com/pay/login/   返回/pay/login

  5、port:返回url中指定的端口号

  6、protocol:返回页面使用的协议,如http:或https:

  7、search:返回url查询的字符串,“?a=javascript”

 

五、history对象

  history保存着用户上网的历史记录,从窗口被打开算起。

 

  1、  go():通过go方法可以在用户历史记录中任意跳转

  history.go(-1):后退一页

  history.go(1):前进一页

  history.go(2):前进两页

 

  2、back():后退一页

           

 

第九章  客户端检测 

一、能力检测:测试浏览器是否支持

    例:ie5.0不支持document.getElementById()

 1 var getid;
 2 
 3 if(document.getElementById){
 4   getid = document.getElementById("obj");
 5 }
 6 else if(document.all){        // ie5.0以下
 7   getid = document.all["obj"];
 8 }
 9 else{
10   alert("浏览器不支持获取id元素")
11 }

 

二、怪癖检测:

         与能力检测类似,目的是识别浏览器的特殊行为,与能力检测的区别是,怪癖检测要知道浏览器的缺陷在哪

 

三、用户代理检测

 

 

第十章  DOM

一、动态脚本

         动态脚本指的是在页面加载进不存在,但某一时段通过修改DOM动态添加的脚本。

         创建动态脚本有两种方式:插入外部文件和直接插入javascript代码

 1 function loadScript(url){
 2         var script = document.createElement("script");
 3         script.type = "text/javascript";
 4         script.src = url;
 5         document.getElementsByTagName("body")[0].appendChild(script);
 6 
 7 };
 8 
 9 var scrStr = "http://img.wan.renren.com/vcms/js/new-wan-2/base.js";
10 loadScript(scrStr);

 

二、动态样式   

 function loadCSS(url){

        var css = document.createElement("link");

        css.type = "text/css";

        css.rel = "stylesheet";

        css.href = url;

        document.getElementsByTagName("head")[0].appendChild()

}

 

         动态加载外部文件的过程是异步的,也就是加载的内容与固定页面的内容加载没有次序

 

三、表格

      1、rows:表格的所有行

      2、cells:保存着<tr>元素中的单元格

 

 

第十一章   事件

一、事件流

         事件流描述页面中接收事件的顺序,IE的事件流就是事件冒泡流,Netscape的事件流是事件捕获流.

 

1、 事件冒泡:

  IE的事件流叫事件冒泡,事件开始由具体的元素接收,然后逐级向上传播

      <html>

<head>

<title>无标题文档</title>

</head>

<body>

         <div id="box">demo</div>

</body>

</html>

  如果点击box时会按照如下顺序:

  <div>-<body>-<html>-document  会沿着DOM树一直传播到document对象

 

2、事件捕获:

         Netscanp提出了另一种事件流叫事件捕获。

 

         拿上面的例子来说:

         如果点击box时会按照如下顺序:

         document-<html>-<body>-<div>  与事件冒泡正好相反

 

3、事件流:

         事件流包括三个阶段:事件捕获、处于目标和事件冒泡

         Opear、chrom、ff、Safari都支持DOM事件流,IE不支持DOM事件流

 

 

二、事件处理程序(或事件侦听)

  1、HTML事件处理程序:<div onclick="alert('aaa')"></div>

  2、DOM事件处理:先取得操作对象的引用

var btn = document.getElementById("myBtn");
btn.onclick = function(){
    alert(this.id);
}

btn.onclick = null;         // 删除事件处理程序

 

 

  事件就是用户在浏览器作出的行为,如click、load和mouserove等,都是事件的名称,而响应某个事件的函数叫事件处理程序

function addEvent(obj, type, fn){
    if(obj.addEventListener){
        obj.addEventListener(type, fn, false);     // 标准DOM下事件侦听
    }
    else{
        obj.attachEvent("on" + type, fn);             // IE下事件侦听
    }
};

注:如果fn为闭包,则不能移出侦听,也就是

Obj.addEventListener(“onclic”, function(){ ….. }, false);           // 这种是无法用removeEventListener移除

 

 

三、事件对象

  在DOM触发某个事件时,会产生一个事件对象Event,这个对象包含所有事件的信息

 

 

四、事件类型

事件类型有五种:

1、  UI(用户界面)事件,在用户与页面上的元素进行交互.

2、  鼠标事件:用户通过鼠标在页面上执行的操作

3、  键盘事件:用户通过键盘在页面上执行的操作

4、  HTML事件:当浏览器窗口在发生变化或发生特定的客户端、服务器端交互时触发

5、  变动事件:当底层的DOM结构发生改变时触发.

 

UI主要与元素的焦点有关,有三个UI事件

1、  DOMActive:操作元素已被用户操作(通过鼠标或键盘)所激活。

2、  DOMFocusIn:元素已经获得了焦点,HTML中focus

3、  DOMFocusOut:元素已经失去了焦点,HTML中focus

 

鼠标事件:

1、  onclick:点击

2、  ondbclick:双击左键

3、  onmouseup:鼠标抬起

4、  onmousedown:鼠标按下

5、  onmouseover:移到指定元素中

6、  onmouseout:移出指定的元素

7、  onmousemove:在指定的元素中移动所触发

8、  clientX、clientY:客户区域的x、y轴

9、  screenX、screenY:屏幕坐标的x、y轴

 

  鼠标和按键的组合键:

shiftKey、ctrlKey、altKey、metaKey:如果相应的按下时会返回true       

box.onclick = function(event){
        var evt = RGEvn.getEvent(event);

        if(evt.shiftKey){
            alert("已按下shift和鼠标左键");
        }
if(evt.altKey){ alert("已按下alt和鼠标左键"); } if(evt.ctrlKey){ alert("已按下ctrl和鼠标左键"); } if(evt.metaKey){ alert("已按下Cmd和鼠标左键"); } }

 

 

  鼠标按钮:

  button属性:

      DOM下的button属性返回值:1左键  2中键(滚轮)  3右键

      IE下的button属性返回值:0没有按下按键     1按下左键      2按下右键   3同时按下左右键  4

 

键盘事件:

1、  keydown:按下按键

2、  keypress:按下按键

3、  keyup:释放按键

4、  testInput:用户在可编辑区输入

 

键盘码:keyCode

在keyup、keydown时,event对象的keyCode属性中会包含一个代码,

 document.onkeyup = function(event){
     evt = event || window.event;
     box1.innerHTML = evt.keyCode;
};

 

HTML事件:

1、  load:当页面加载(包括图片、javascript文件、css等资源)后会触发window上面的load事件

2、  unload:当页面卸载后在window上触发

3、  abor:当用户停止下载过程时

4、  error:当发生javascript错误时在window触发

5、  resize:窗口或框架的大小改变时触发

6、  scroll:滚动条滚动时触发

7、  select:下拉菜单

8、  change:

9、  submit:用户提交表单时触发

10、reset:表单重置

11、focus:当页面或元素获得焦点时触发

12、blur:当页面或元素离开焦点时触发

 

变动事件:变动事件能在DOM中的某一部分发生变化时给出提示,变动事件是为XML和DOM设计的,

1、  DOMSubtreeModified:在DOM结构中发生任何变化时触发,这个事件在任何事件触发后都会触发

2、  DOMNodeInserted:在一个节点作为子节点被插入到另一个节点中时触发

3、  DOMNodeRemoved:在节点从其父节点宫被移除时触发

4、  DOMNodeInsertedIntoDocument:在一个节点被直接插入文档或通过子树间接插入文档之后触发.

5、  DOMNodeRemovedFromDocument:

6、  DOMAttrModified:在特性被修改之后触发

7、  DOMCharacterDataModified:在文本节点的值发生变化时触发

 

专有事件:

1、 DOMContentLoaded:在形成完整的DOM树之后就会触发,不会等图像、javascript文件、css文件或其它资源是否已经下载完毕

RGEvt.addEvent(document, “DOMContentloaded”, function(){ ….. })

2、 contextmeun:上下文菜单事件

3、 readystatechage:就绪状态变化事件,其实就是ajax中调用的onreadystatechange来查看数据是否加载完成,这个事件是提供与文档或元素的加载信息,readystatechage事件的每个对象都有一个readyState属性,它包括5个值。

1、 uninitialized(未初始化):对象正在加载数据

2、 loading(正在加载):对象下正在加载数据

3、 loaded(加载完毕):对象加载数据完成

4、 interactive(交互):可以操作对象了,但还没有完全加载

5、 complete(完成):对象已经加载完毕

 

五、事件委托

         对“事件处理程序过多”问题的解决方案就是事件委托,事件委托就是利用事件冒泡,只

 

 

 

 

一些遇到的问题

一、定时器的重复开启

function Drag(){
    var timer = null
    var speed = 1;
    clearInterval(timer);        // 如果这块不清除那么点一次就开启一个定时器
    timer = setInterval(function(){
        $("#box").css("left", $(this).offset().left + speed);
    }, 30);
}

$("#box").click(function(){ Drag(); })

 

二、定时器的分配与管理

<div id="div1">
<ul>
	<li></li>
    <li></li>
    <li></li>
</ul>
</div>

<script>
function getID(id){
    return document.getElementById(id);	
}

var obj = getID("div1");
var oLi = obj.getElementsByTagName("li");
var speed = 0;

for(var i=0; i<oLi.length; i++){
    oLi[i].timer = null;        // 为每个元素定义一个定时器的引用
    oLi[i].onmouseover = function(){
        startMove(this, 500)
    }
    
    oLi[i].onmouseout = function(){
        startMove(this, 100);
    }
}

function startMove(element, target){
    clearInterval(element.timer);
    element.timer = setInterval(function(){    // 如果在这只开一个定时器,若第一个还没有执行完,在执行第二个就会将定时器停止重新开启第二个定时器
        speed = (target - element.offsetWidth) / 8;
        speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
        console.log(element.offsetWidth +" "+ target + " " + speed);
        if(element.offsetWidth == target){
            clearInterval(element.timer);
        }
        else{
            element.style.width = element.offsetWidth + speed + "px";
        }
    }, 30)
}
</script>

 

三、定义元素name属性值值不能为xxx-xx

如果在jquery通过name来获取时是取不到这种属性值的,nav-first可以写成navFirst

<input type="text" value="" name="usAgears" class="inp-t-w122">
<input type="text" value="" name="usAgears" class="inp-t-w122">
<input type="text" value="" name="usAgears" class="inp-t-w122">

$("input[name='" + n1 + "']").each(function(){
        alert("a")    // 弹出三次
})


如果带值带"-"
<input type="text" value="" name="us-Agears" class="inp-t-w122">
<input type="text" value="" name="us-Agears" class="inp-t-w122">
<input type="text" value="" name="us-Agears" class="inp-t-w122">

$("input[name='" + n1 + "']").each(function(){
        alert("a")     // 只弹出一次
})

  

第十七章   Ajax与JSON

 1 /*
 2  * 1、readyState存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。
 3  * 0: 请求未初始化
 4  * 1: 服务器连接已建立
 5  * 2: 请求已接收
 6  * 3: 请求处理中
 7  * 4: 请求已完成,且响应已就绪
 8  *
 9  * 2、status
10  * 200: "OK"
11  * 404: 未找到页面
12  * */
13 
14  // 创建XMLHttpRequest对象
15 function createAjax(){
16     var xhr = null;
17     if(window.XMLHttpRequest){
18         xhr = new XMLHttpRequest();
19     }
20     else{
21         xhr = new ActiveXObject("Microsoft.XMLHTTP");
22     }
23     return xhr;
24 }
25 
26 // GET请求
27 function get(url, async, callback){
28     var newAjax = createAjax();
29     newAjax.open("GET", url, async);
30 
31     // 当请求被发送到服务器时
32     newAjax.onreadystatechange = function(){
33         if(newAjax.readyState === 4 && newAjax.status === 200){
34             if(callback){
35                 console.log(newAjax.responseText);      // 返回非xml文件,也可以请求XML文件,使用responseXML
36                 callback();
37             }
38             else{
39                 console.log(newAjax.responseText);
40             }
41         }
42     }
43 }
44 
45 // POST请求
46 function post(url, dataJson, async, callback){
47     var newAjax = createAjax();
48     newAjax.open("POST", url, async);
49     newAjax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
50     newAjax.setRequestHeader("If-Modified-Since","0");
51 
52     // 当请求被发送到服务器时
53     newAjax.onreadystatechange = function(){
54         if(newAjax.readyState === 4 && newAjax.status === 200){
55             if(callback){
56                 console.log(newAjax.responseText);
57                 callback();
58             }
59             else{
60                 console.log(newAjax.responseText);
61             }
62         }
63     }
64     newAjax.send(dataJson);         // 如果请求不需要数据参数可以为空
65 }

 

第十九章   客户端存储

一、cookie限制

  cookie是绑定在特定的域下,

  IE6下每个域限制最后存储20个cookie,IE7下最多50个cookie

 

二、cookie的组成

  1、名称  2、值  3、域  4、失效时间

  document.cookie = "name=siguang";

 

  内容使用:decodeURIComponent()、encodeURIComponent()来进行编码和解码

 1 // 存储Cookie
 2 // 如果存储时不加日期,cookie的类型为Session,否则就是结束日期
 3 function addCookie(key, val, expires){
 4     var nDate = new Date();
 5     nDate.setTime(nDate.getTime() + 1000*60*60*24*expires); // 以天为单位
 6     var sContent = key + "=" + val;
 7     var sExpires = "expires=" + nDate.toGMTString();
 8     document.cookie = sContent + ";" + sExpires;
 9 }
10 
11 // 获取Cookie
12 function getCookie(key){
13     var sCookies = document.cookie;     // 获取域下所有cookie
14     if(sCookies.length <= 0){ return false; }
15     var setVal = "";
16     var arr = sCookies.split(";");
17 
18     for(var i=0; i<arr.length; i++){
19         var arrJosn = arr[i].split("=");
20         if($.trim(arrJosn[0]) === key){
21             setVal = arrJosn[1];
22             break;
23         }
24     }
25     return setVal;
26 }
27 
28 // 删除Cookie
29 function deleteCookie(key){
30     addCookie(key, "", -1);
31 }
32 
33 // addCookie("name", "lulu", 5);
34 // addCookie("haha", "siguang", 5);
35 deleteCookie("name")
36 deleteCookie("haha")