《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")