js 比 ECMAScript 多

完整的js:

  • ECMAScript 核心语言功能
  • DOM 文档对象模型 访问&操作 网页内容的方法和接口
  • BOM 浏览器对象模型 提供 与浏览器交互的方法和接口

dom 文档对象模型

document object model 用于HTML 应用程序的 编程接口 api. application programming interface

DOM 把整个页面映射为一个多层节点结构.

有了这个文档树. 开发人员就有了 控制页面内容和结构的 主动权. 借助 DOM 提供的 api. 我们可以 自如的 增删改任何节点.

BOM 浏览器对象模型

弹出新浏览器窗口 移动 缩放 关闭浏览器窗口 支持 cookie …

HTML 中使用 JavaScript

<script> 元素

  • async 可选: 应该立即下载脚本.
  • src: 可选: 要执行代码的 外部文件.
  • type: 可选: 编写代码使用的脚本语言的内容类型. text/JavaScript(默认值,可忽略) text/ECMAScript .

两种使用方法:

  • 直接嵌入js 代码
  • 包含外部js 文件. 要用外部文件 src 属性就必须要了. <script src="main.js"></script>

js 出现顺序 依次解析. 第一个js 解析完后 才会解析后面的…

js 标签最佳位置: body 页面底部

按照惯例 所有 script 元素都应该放在 head 中. 但是 这样的话 就影响网页内容的显示. 网页是 在 body 标签后才开始显示内容的. 一旦有很多 js 那么必须等head中的所有js下载完成 才能开始解析body元素 . 浏览器页面才会有东西显示出来. 也会出现明显的延迟…

现代的浏览器 一般都会 把js 脚本 放在 </body> 元素前面.

这样 会先 显示网页内容, 再下载脚本..

XHTML 可扩展超文本标记语言 Extensible hypertext markup language.

外部js文件

直接在HTML中嵌入代码虽然没有问题.但是最好是在外部文件来包含js代码.

  • 可维护性: 所有js 都放在 一个文件夹中.
  • 可缓存: 多个页面使用同一个js文件的话. 可以缓存. 加快加载速度.

文档类型: doctype:

<!–HTML 4.01 严格型–> <!–XHTML 1.0 严格型–> <!–HTML 5–>

<noscript> 元素

浏览器不支持js 时 如何处理

noscript 元素中的内容只有在下列情况才会显示出来:

  • 浏览器不支持脚本.
  • 浏览器支持脚本,但是脚本被禁用.

基本概念

任何语言都涉及: 语法.操作符.数据类型,内置功能,等基本概念

区分大小写 test 和 Test 是两个不同的变量. 函数名 不能用 typeof 这是一个关键字.

标识符 变量 函数 属性的名字:

不能把 关键字 保留字 true false null 用作标识符.

js 严格模式

strict mode 严格模式下.一个不安全的js操作 会抛出错误. 只要在顶部添加 *use strict*

function doSomething() { *use strict*; // 函数... }

严格模式下. js 的结果会有很大不同..

变量 var

ECMAScript 变量 是松散类型的. 松散类型:可以保存任何类型的数据.

换句话说. 每个变量 仅仅是一个 用于保存值的 占位符而已.

var message 定义了一个名为message的变量. 这个变量可以用来保存任何值. (像这样未经过初始化的变量.会有一个特殊值: undefined )

也可以直接 初始化变量: var message = “hi”; 变量 message 保存了一个 字符串 hi . 但是这样的初始化 不会把 message标记为字符串类型.可以在修改变量值的同时 修改值的类型:

var message = “hi”; message = 100; //有效 但不推荐.

局部变量

用var 定义的变量 是局部变量. 如果在一个函数中 var 定义一个变量. 那么这个变量 在函数退出后会被销毁:

function test() { var message = 100; }

test();

alert (message); // ❌

全局变量

可以在函数外 任何地方 访问.

function test() { message = 100; }

test(); alert (message); // ✔️

数据类型

复杂数据类型: object 基本数据类型: undefined null boilean number string

  • undefined 未定义. 只定义了变量名. 没有给赋值.
  • boolean 布尔值:
  • string 字符串
  • number 数值
  • object 值是对象 或者 null
  • function 值是函数

所有的值 最终都是 上面6种数据类型之一 由于 ECMAScript 数据类型的动态性 因此没必要定义数据类型.

Null 类型

只有一个值的 数据类型. null 值 标识一个 空对象指针.

用 typeof 操作符检测 null值时会 返回 object.

var car = null; alert(typeof car); //*object*

如果 定义的变量 准备在将来用于保存对象. 那么最好把该变量初始化为null 而不是其他值. 只要 直接检查 null值 就可以指定 那个变量是否已经保存了一个对象的引用.

只要 将来要保存对象的变量 还没有真正的保存对象. 那么应该明确的让这个变量 保存null值. 有助于 区分 null 和 undefined.

Boolean : true / false

js 用的最多的一种类型. 只有两个值: true false. 两个值 和 数字值 不是一回事. true 不一定等于 1 false 不一定等于 0

所有类型的值 都有与 boolean值等价的值. 可以用 boolean() 把一个值 转换成对应的 boolean值.

var message = “hello world”; var messageAsBoolean = Boolean(message);

message 被转换成了一个 boolean值. 这个值被保存在 messageasboolean 中.

任何数据类型调用 boolean() 函数 都会返回一个 boolean值. true 还是 false .取决于转换值的数据类型 以及其实际值.

数据类型 true false string 非空字符串 空字符串 number 非零数值 0 和 NaN object 任何对象 null undefined n/a undefined

n/a: not applicable 不适用的意思

Number

前导 + 字面值

十进制 219 八进制 0 + 0-7 如果后面的值超出7 那么前面的0 会被忽略 070 → 八进制的56 079 → 79 08 → 8

十六进制: 0x + 0-9 A-F a-f 不区分大小写. 0xA → 16进制的 10 0x1f → 16进制的 31

算术计算时: 所有 8进制 16进制 最终都会被转成10 进制.

浮点数值:

数值中 包含一个小数点.

e 10的指数次. 3.125e7 = 31250000

浮点数值 需要的内存空间是 整数值的两倍.

数值范围

内存的限制. js 不能保存世界上 所有的值. Number.MIN value: 5e-324 Number.MAX value: 1.79e+308 如果某次计算超出范围: 子自动转为特殊的 infinity 值. 正数 → infinity 正无穷 负数 → -infinity 负无穷 如果 某次计算值 返回 无穷.. 那么这个值就无法参与下一次计算.

判断一个数字 是不是 有穷的: isFinite() 函数. 在最大最小值之间的话 会返回 true.

NaN not a number 非数值. 一个特殊的 数值. 表示 一个本来要返回数值的操作数未返回数值的情况. 这样就不会抛出错误了.

别的语言: 任何数值 除以0 都会导致代码错误. 从而停止代码执行. 在js中.任何数除以0 会返回 NaN,不影响其他代码执行.

数值转换

非数值转为数值

  • Number() 任何数据类型.
  • parseInt() 字符串→数值
  • parseFloat() 字符串→ 数值

boolean :
true → 1 false → 0 null → 0 undefined → NaN 字符串: 转成 十进制. 空字符串 → 0 忽略 前导 0

var num1 = Number (“hello world”); //NaN var num2 = Number (“”); //0 var num3 = Number (“000011”) //11 var num4 = Number (true) //1

number 转换字符串 比较复杂.且不太合理. 一般用 parseInt parseFloat

parseInt(“1234blue”); → 1234 parseInt(“”); → NaN parseInt(“0xA”); → 10 十六进制 parseInt(“22.5”); → 22 parseInt(“070”); → 56 八进制 parseInt(“70”); → 70 十进制 parseInt(“0xf”); → 15 十六进制

进制转换 有歧义 最好指定要怎么转: parseInt(“10”,2); → 2 按2进制解析 parseInt(“10”,8); → 8 按8进制解析 parseInt(“10”,10); → 10 按10进制解析 parseInt(“10”,16); → 16 按16进制解析

一般都是10 进制 解析的.

字符串 String

在双引号 或者 单引号之中.

js中 字符串 是 不可变的. 一旦创建 值就不能改变. 要改的话 只能西安销毁 在赋值.

转为字符串: toString()

var age = 11 ; var ageAdDtring = age.toString(); → 字符串”11”

var found = true; var foundAsString = found.toString(); → 字符串 “true”

object 类型

对象: 其实就是 一组数据和功能的集合. 用 new 创建.

var o = new Object()

操作符

一元操作: 只能操作一个值.

alert(!false) //true alert(!”blue”) //false alert(!0) // true alert(!NaN) // true alert(!””) //true alert(!12345); //false

乘性操作符

乘法 除法 求模(求余) %

=== 全等 !== 不等于

if

if (条件 condition) statement1语句1 else statement2语句2

条件 可以是任意表达式. 表达式的求值结构不一定是布尔值. 会自动调用 boolean 函数 帮你把值 转为一个 布尔值. 值是 true 执行 语句1 值是false 执行语句2

这两个语句 可以是 一行代码 .也可以是 代码块 (用花括号) 推荐用 代码块.

if (condition) statement1 else if statement2 else statement3

推荐: if (i > 25) { alert(“greater than 25.”); } else if (i < 0) { alert(“less than 0 “); } else { alert(“between 0 and 25.”); }

do-while

后测试循环语句. 循环体中代码 先执行 然后测试出口条件. 也就是说 代码至少会执行一次.

while

前测试循环语句. 先判断条件. 再看是否执行. 循环体内代码 有可能永远不会被执行.

for

前测试循环语句.

for-in

精准迭代语句. 可用来 枚举对象的属性.

for (var propName in window) { document.write(propName); } 循环显示 BOM 中的window 对象的 所有属性.

label 语句

在代码中 添加标签. 以便将来使用.

break continue 语句

在循环中 精确的控制代码的执行.

break 语句会立即退出循环.强制继续执行循环语句后面的语句. continue 也是立即退出循环.但是退出后会从循环的顶部 继续执行.

var num = 0; for (var i=1; i<10; i++ ) { if (i % 5 == 0 ) { break; } num++; } alert(num) //4 也就是 循环了4次

var num = 0; for (var i=1; i<10; i++ ) { if (i % 5 == 0 ) { continue; } num++; } alert(num) //8 也就是循环了8次. i=5的时候 跳出循环.以6重新开始 5的这次 不算循环.

with 语句

将代码 作用域 设置到一个特定的对象中.

主要目的: 简化多次编写同一个对象的工作.

var qs = location.search.substring(1); var hostName = localtion.hostname var url = location.href

上面 三行都包含 location 对象.

with(location){ var qs = search.substring(1); var hostName = hostname; var url = href; }

with 语句内部. 每个变量 首先被认为是一个局部变量. 如果在局部环境中 找不到变量的定义 就会查询 location 对象中是否有同名的属性. 如果发现同名属性: 则以 location对象属性的值 作为变量的值.

switch

和 if 密切相关. 普遍使用的一种流控制语句.

switch (expression) { case value: statement break; case value: statement break; case value: statement break; default: statement

}

每种case的含义:
如果表达式 等于这个值. 就执行后面的语句. 如果没有break. 就会执行下一个case. default: 不匹配任何上面的case 就这些这个代码.

case 可以是 变量 甚至是表达式.

函数 function.

对任何语言 都是核心概念.

通过函数可以封装 任意多条语句. 而且可以在 任何地方 任何时候 调用执行.

参数

js 函数 不介意传递进来多少个参数. 也不在乎 参数是什么数据类型. 也就是说: 即便你定义的函数只要接收两个参数. 在调用这个函数的时候 未必一定要传递两个参数. 可以 一个 三个 甚至不传递参数..

.原因是 js中的参数 在内部是用一个数组来表示的. 函数接收到的始终都是这个数组. 而不关心数组中是否有参数.

变量 作用域 内存问题

基本类型: 简单的数据段. 引用类型: 可能有多个值 构成的对象.

引用类型的值是保存在内存中的对象. js 不允许直接访问内存中的位置. 也就是不能直接操对象的内存空间.

检测类型 typeof

检测一个变量 是不是 基本数据类型: typeof.

var s = “nick” var b = true var i = 21 var u; var n = null var o = new Object();

alert (typeof s); // string alert (typeof b); // boolean alert (typeof i); // number alert (typeof u); // undefined alert (typeof n); //Object alert (typeof o); //Object

执行环境 作用域

执行环境: ececution context 也叫环境. 最重要的一个概念.

环境 定义了 变量/函数 有权访问的其他数据. 觉得了他们各种的行为. 每个环境 都有一个 与之关联的 变量对象. 环境中定义的 所有变量和函数都保存在这个对象中.

全局环境: 最外围的一个执行环境. web浏览器中. 全局环境被认为是 window 对象.

垃圾收集

js 具有自动垃圾收集机制. 不用关心内存使用问题.

垃圾收集原理: 找出那些不再使用的变量.释放其占用的内存.

管理内存

浏览器的内存 比桌面应用相对少很多. 内存限制问题.不仅会影响 给变量分配内存. 还会影响 一个线程中能够同时执行的 语句数量.

确保占用最少的内存可以让一个页面获得更好的性能 优化内存占用最佳方式: 为执行中的代码 只保存必要的数据. 一旦数据不再有用.将其值设置为 null 来释放引用. 这个做法叫: 解除引用. 这个做法使用与 大多数全局变量.和全局对象的属性. 局部变量会在离开执行环境时 自动解除引用.

引用类型

Object 类型

用的最多的一个类型.

创建 Object 实例: 方法一: var person = new Object(); person.name = “nick” person.age = 29;

方法二: var person = { name: “nick”, age: 29 }

array 数组类型

和 别的语言的数组 有很大的区别. js 中的数组key保存任意数据类型. 一个数组还能混用各种数据类型. js 数组大小 是可以动态调节的. 随着数据的增加自动增长.

创建数组: 方法一: var colors = new Array(); var colors = new Array(20); // 预先设定数组长度:20 var colors = new Array(“red”, “blue”, “green”);

也可以省略new: var colors = Array(); var colors = Array(20); // 预先设定数组长度:20 var colors = Array(“red”, “blue”, “green”);

方法二: 数组字面量表示法: var colors = ["red", "blue", "green"] var colors = ["red", "blue", "green",] 不要这样! 在最后添加, var names = [] 空数组

检测数组:

转换方法: 所有对象 都有: tolocalString() toString() valueof()

栈方法 push() + pop()

栈 一种可以限制插入和删除的数据结构. 是一种 LIFO last in first out 后进先出的数据结构. 也就是 最新添加项 最早被移除. 就像子弹夹. 栈中 项的插入叫 推入. push() 移除叫 弹出. pop() 只发生在一个位置. 栈的顶部.

push() 可以接收任意数量的参数. pop() 从数组末尾移除一项.减少数组的length.

var colors = new Array(); //创建一个数组 var count = colors.push(“red”, “green”); //推入2项. alert(count); //2 count = colors.push(“black”); //推入另一项 alert(count); //3 var item = colors.pop(); //取得最后一项 alert(item); // “black” alert(colors.length); //2

队列方法 push() + shift()

栈数据结构: LIFO 后进先出. 队列数据结构: FIFO 先进先出.

var colors = new Array(); //创建一个数组 var count = colors.push(“red”, “green”); //推入2项. alert(count); //2 count = colors.push(“black”); //推入另一项 alert(count); //3

var item = colors.shift(); //取得第一项 alert(item); // “red” alert(colors.length); //2

重排序方法 reverse() sort()

reverse() 反转数组的顺序.

var values = [1,2,3,4,5] values.reverse(); alert(values); // 5,4,3,2,1

sort() 按照升序方法排列. 从小到大排列. 这个比较的是 字符串. 会调用每个数组项的 tostring()来转换 再排列.

var values = [0,1,5,10,15] values.sort(); alert(values); // 0,1,10,15,5 虽然 5<10 但是字符串比较时候 “10”位于”5”前面..

所以这也不是 最佳方案.

比较函数 接收两个参数. 如果第一个参数 应该 位于第二个参数之前 则返回一个负数. 如果两个参数相等 返回0 如果第一个参数应该在第二个参数之后 返回一个正数.

function compare (value1, value2) { if (value1 < value2) { return -1 ;} else if (value1 > value2) { return 1;} else {return 0;} }

这个比较函数 适用于大多数数据类型. 只要将其 作为参数传递给 sort()方法即可.

var values = [0,1,5,10,15] values.sort(compare); alert(values); // 0,1,5,10,15

降序排列: function compare (value1, value2) { if (value1 < value2) { return 1 ;} else if (value1 > value2) { return -1;} else {return 0;} }

var values = [0,1,5,10,15] values.sort(compare); alert(values); // 15,10,5,1,0

对数值类 可以有简单的函数: function compare(value1,value2) { return value2-value1; }

操作方法

concat()  可以基于放弃数组中的 所有 项 创建一个新的数组.类似副本. 然后把 接收到的参数 添加到副本.

var colors = ["red", "green", "blue"]; var colors2 = colors.concat("yellow",["black","brown"]) // 传入一个字符串 和 一个数组.

alert(colors) // red,green,blue alert(colors2)// red,green,blue,yellow,black,brown

slice() 基于当前数组中的 一个或者多个项创建新数组. slice() 可以接受一个或两个参数: 返回项的 起始和结束位置.

var colors = ["red", "green","blue","yellow","purple"] var colors2 = colors.slice(1); var colors3 = colors.slice(1,4); alert(color2) // green,blue,yellow,purple alert(color3) // green,blue,yellow

splice 最强大的数组方法. 插入 删除 替换 项目.

  • 删除: 可删除任意数量的项. 两个参数: 要删除第一项的位置+删除的项数. splice(0,2) 会删除数组中的前两项.

  • 插入:可在指定位置插入任意数量的项. 三个参数: 起始位置,要删除的项,要插入的项… splice(2,0,”red”,”green”) 从当前数组的位置2开始 插入字符串 red green

  • 替换: 插入的同时删除. splice(2,1,”red”,”green”) 先删除第二项 再添加red 和 green

    splice 始终返回一个数组. 该数组 包含从原始数组中删除的项, 如果没删除任何东西 就返回空数组.

var colors = ["red", "green", "blue"]; var removed = colors.splice(0,1); //删除第一项 alert(colors) // green,blue alert(removed) // red

removed = colors.splice(1,0,”yellow”,”orange”) //从1插入两项 alert(colors) // green yellow orange blue alert(removed) // 空数组 因为没有东西被删除.

removed = colors.splice(1,1,”red”,”pirple”) // 插2 删1 alert(colors) // green red purplr orange blue alert(removed) //yellow

位置方法 indexOf(正向查找) LastIndexOf(反向查找)

都接收两个参数. 要查找的项,和查找起点位置的索引(可选)

都会返回 要查找的项在数组中的位置. 没有找到 返回 -1

var numbers = [1,2,3,4,5,4,3,2,1]; alert(numbers.indexOf(4)); // 3 alert(numbers.lastIndexOf(4)) //5

alert(numbers.indexOf(4,4)) //5 alert(numbers.lastIndexOf(4,4)) //3

var person = { name: “nick” }; var people = [{name: "nick"}]; var morePeople = [person] alert (people.indexOf(person)); // -1 alert (morePeople.indexOf(person)) // 0

迭代方法

数组 5个 迭代方法:

每个方法: 接收两个参数: 要在每一项上运行的函数 运行该函数的作用域对象 - 影响this的值.

传入这些方法的函数会接收三个参数: 数组项的值 该项在数组中的位置. 数组对象本身.

every 每一项都返回true 则返回true

filter 返回 该函数 会返回 true 的项 组成的数组

foreach 没有返回值 map 返回 每次函数调用的结果组成的 数组 some 如果该函数 任一项 返回true 则返回 true.

以上方法都不会修改数组中包含的值.

every some 类似. 查询数组中的项是否满足某个条件. every 必须每一项都返回true 这个方法才返回 true

var numbers = [1,2,3,4,5,4,3,2,1]

every: var everyResult = numbers.every( function(item,index,Array) { return (item > 2) } );

alert(everyResult) // false

some: var everyResult = numbers.some( function(item,index,Array) { return (item >2 ) } ); alert(everyResult) // true

fliter: var filterResult = numbers.filter(function(item,index,Array) { return (item > 2); });

alert(filterReault) // 3 4 5 4 3

map: var mapResult = Numbers.map(function(item,index,Array){ return item * 2 }); alert(mapResult); // 2 4 6 8 10 8 6 4 2

缩小方法 reduce (正序:向后遍历) reduceRight(倒序:向前遍历)

迭代数组的所有项. 构建一个最终返回值.

如: 数组中所有值之和 var values = [1,2,3,4,5]

var sum = value.reduce(function(prev,cur,index,Array){ return prev + cur; });

alert(sum); // 15

第一次 prev 是1 cur是2 第二次 prev 是3 (1+2=3) cur是3 ….

date 类型

var now = new Date(); 默认 赋值 当前日期和时间. 默认是只接受 毫秒的. 为了方便 有有了下面两个函数. 帮你自动把时间编程 毫秒.

Date.parse() Date.UTC()

月/日/年 6/13/2004 英文月名 / 日/ 年 january/13/2004

var someDate = new Date(Date.parse(“may 25 2004”));

var start = Date.now() 取得开始时间

doSomething() 调用函数

var stop = Date.now() 取得停止时间

result = stop - start;

日期格式化方法

toDaateString() 星期几 月 日 年 toTimeString() 时 分 秒 时区 toLocalDateString() 特定时区的 星期几 月 日 年 toLocalTimeString() 特定时区的 时 分 秒 toUTCString() 完整的 utc 日期.

getTime 日期的毫秒数 getFullYear 取得四位数的 年份. 2007 getMonth 返回月份 0→ 一月 11→12月.

RegExp 类型

正则式表达.

var expression = / pattern / flags

模式 pattern 可以是任何 正则式表达. 每个正则式 都可以带一个 或 多个 flags. 用以表明正则式的行为.

g 全局模式: global i 不区分大小写 case-inseneitive m 多行模式 multiline

var pattern1 = /at/g; 匹配所有 at

var pattern2 = /[bc]at/i 匹配 第一个 bat或cat 不区分大小写

var pattern3 = /.at/gi 匹配所有 at结尾的 3个字符的组合 不区分大小写.

RegExp 主要 配合 exec() 使用 exec() 专门为 捕获组而设计的. exec() 接受一个参数. 然后返回包含第一个匹配项信息的数组. 没有匹配 返回null.

返回的数组 有两个额外属性: index 和 input. index: 匹配项在字符串中的位置. input: 正则式的字符串?

js 下 正则式的局限性: 虽然功能比较完善 但是 还是不能和 perl 比. 少了很多高级的功能.

Function 类型

函数 实际上 是对象. 每个函数 都是 function 类型的 实例. 由于函数是对象. 所以 函数名实际上就是一个指向函数对象的指针. 不会与某个函数绑定.

这两行 函数 差不多. function sum (num1, num2) {return num1 + num2; } var sum = function(num1, num2) {return num1 + num2;} → 不推荐

一个函数 可能有多个名字:

function sum (num1, num2) {return num1 + num2;} alert(sum(10,10)); //20

var anotherSum = sum; alert(anotherSum(10,10)) //20 不带圆括号的函数名是 访问函数指针. 而不是调用函数.

sum = null; alert(anotherSum(10,10)) // 20

  1. 定义了一个 名为 sum() 的函数 用于求和.
  2. 声明变量 anothersum 设置和sum 相等 这时候 anothersum 和 sum 都指向同一个函数. 因此 anothersum() 也可以被调用 并求和.

  3. 即使 把 sum 设置为 null 让它与函数 断绝关系. 仍然可以使用 anothersum()

函数声明 & 函数表达式

解析器 向执行环境中 加载数据的时候.
对函数 声明 和 函数表达式 并非 一视同仁.

解析器 优先读取函数声明 并使其在执行任何代码之前可用(可以访问)

函数表达式: 等解析器执行到它所在的代码行 才会真的被解释执行.

函数 可以作为 另一个函数的值来用. 函数本身就是变量.

函数内部属性

函数内部 有两个特殊对象: arguments & this

函数属性 和 方法

函数是对象. 因此也有属性 和方法.

每个函数包含两个属性: length & prototype length : 函数希望接收参数的个数.

prototype 是 保存所有实例方法的真正所在.

换句话说: tostring 和 valueof 等方法 实际都保存在 prototype名下. 只是可以通过格子对象的实例访问罢了.. prototype 属性是不可枚举的. 所以 for-in 无法发现.

每个函数都包含两个非继承而来的方法: apply() call()

string 类型

每个 string 实例 都有一个 length 属性:字符串中包含多少字符.

var name = “xu jian” alert(name.length) // 7

字符方法:

  • charAt() 字符
  • charCodeAt() 字符编码 访问 字符串 中 特定字符的方法. charAt . 以单字符的形式返回给定位置的那个字符. 0 开始

var name = “xe jian”; alert(name.charAt(1)); // “e” alert(name.charCodeAt(1)); // 输出 “101”

字符串操作 concat 拼接字符串.

var xx = “xujian” var result = xx.concat(“a bad boy”) alert(result) // xujian a bad boy alert(xx) // xujian

其实 最方便的 是用 + 号, 特别是拼接 多个字符串的时候.

  • slice()
  • substr()
  • substring() 参数1: 字符串的开始位置. 参数2: 字符串的结束位置.

var xx = “hello world” alert(xx.slice(3)); lo world alert(xx.substring(3)); lo world alert(xx.substr(3)); lo world alert(xx.slice(3,7)); lo w alert(xx.substring(3,7)); lo w alert(xx.substr(3,7)); lo worl

alert(xx.slice(-3)); rld alert(xx.substring(-3)); hello world alert(xx.substr(-3)); rld alert(xx.slice(3,-4)); lo w alert(xx.substring(3,-4)); hel alert(xx.substr(3,-4)); 空字符串

字符串 大小写转换. toLowerCase() toLocalLowerCase() toUpperCase() toLocalUpperCase()

var xx = “hello world” alert(xx.toUpperCase()); // HELLO WOELD alert(xx.toLowerCase()); // hello world

字符串模式匹配: match 返回的是一个数组. search 返回字符串中第一个匹配项的 索引. 没有则返回 -1

var text = “cat, bat, sat, fat”; var patern = /.at/;

var matches = text.match(pattern); alert(matches.index) //0 alert(matches[0]) // cat alert(pattern.lastindex); //0

var pos = text.search(/at/) alert(pos) //1 at在字符串中第一次出现.

替换字符串 replace() 接受两个参数: 正则式/字符串 & 字符串/函数

如果第一个参数 是字符串 那么只会替换第一个子字符串. 要替换所有.就要提供 正则表达式. 指定全局.

var result = text.replace(“at”, “ond”) alert(result) // cond bat sat fat

result = text.replace(/at/g,”ond”); alert(result) // cond bond sond fond

localCompare() 比较两个字符串. 字母表排序. 区分大小写. 大写字母在前. 小写字母在后. 靠前 → 1
靠后→ -1 一样 →0

var xx = “yellow” alert(xx.localCompare(“black”)); //1 alert(xx.localCompare(“yellow”)); //0
alert(xx.localCompare(“zoo”)); // -1

eval() 一个完整的 js 解析器.

eval(“alert(‘hi’)”); 等于 alert(‘hi’)

Math 对象

math.PI

min max  min() 数组中的 最小值 max() 数组中的 最大值

var max = Math.max(3,54,32,16); alert(max); //54

var min = Math.min(3,54,32,16); alert(min); //3

数组中的 最大值/最小值:

var values = [1,2,3,4,5,6,7,8]; var max = Math.max.apply(Math.values)

关键是把math 最为 apply 函数的 第一个参数. 从而正确的设置 this值. 然后可以将任何数组 作为第二个参数..

舍入方法

标准舍入 Math.round 四舍五入
向上舍入 Math.ceil 上最近的整数 向下舍入 Math.floor 下最近的整数

alert(Math.ceil(25.1)); //26 alert(Math.floor(25.9)); //25 alert(Math.round(25.5)); //26 alert(Math.round(25.4)); //25

random() 随机函数

返回 0-1 中的 一个随机数. 不包括 01

随机生成一个 1-10的数:

var num = Math.floor(Math.random()*10 + 1)

0.99 x 10 + 1 = 10.9 → 10 0.44 x 10 + 1 = 5.4 → 5 0.01 x 10 + 1 = 1.1 → 1

随机生成 2-10 中的一个数: var num = Math.floor(Math.random() * 9 + 2 )

面向对象程序设计

Object-oriented OO 面向对象语言有个标志: 都有类的概念.

通过类可以创建任意多个具有相同属性和方法的对象.

创建对象: 创建Object实例. 然后再添加 属性 和 方法.

var person = new Object(); preson.name = “xu.jian” person.age = 29 person.job = “software engineer”

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

这个例子 创建了一个 名为 person 的对象. 添加了 三个属性: name age job 和一个方法: sayName() 用于显示 this.name (将被解析成 person.name)

var person = { name: “xu.jian”, age: 29, job: software engineer,

sayName: function(){ alert(this.name); } }

属性类型

attribute.

数据属性: 包含数据值的位置. 这个位置可以读取和写入值.

  • configurable(true) 能否通过delete删除属性从而重新定义属性.
  • enumerable(true) .能否通过 for-in 循环返回属性.
  • writable(true) 能否修改属性值.
  • value (undefined)这个属性的数据值.读写的修改都在这个位置.

工厂模式

避免大量的重复代码.

function createPerson(name, age, job) { var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function() { alert(this.name); }; return o; }

var person1 = createPerson(“jing”,29,”seiler”); var person2 = createPerson(“xxx”,29,”back-end”)

原型模式

创建的每个 函数都有一个 prototype 属性. 这个属性 是一个指针. 指向一个对象.

函数表达式

定义函数方法:

  • 函数声明
  • 函数表达式

函数声明: function functionName(arg0,arg1,arg2) { // 函数体 }

function 是关键字. functionName 是函数名字.

函数声明特点: 函数声明提升 指向代码之前 先读取函数声明. 意味着: 可以把函数声明 放在调用它的 语句后面.

sayHi(); function sayHi(){ alert(“hi!”); }

这个例子 不会报错. 因第一行代码执行之前 会先读取函数的声明.也就是后面的内容.

函数表达式 类似变量赋值.

var functionName = function(arg0, arg1, arg2) { // 函数体. }

这个 就不能下面这样了. 函数表达式是没有 函数声明提升的!!! sayHi(); function sayHi(){ alert(“hi!”); }

要先定义 再使用.

递归函数:

在一个函数 通过名字调用 自身.

function factorial(num) { if (num <=1) { return 1; } else {return num * factorian(num-1); }; }

闭包

匿名函数 & 闭包

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

创建闭包:在一个函数内部 创建另一个函数.

BOM

window 对象: BOM 的 核心对象是 window. 表示一个浏览器实例.

浏览器中: window 即是通过js访问浏览器窗口的一个接口. 优势 js 规定的 global 对象.

var age = 29; function sayAge(){ alert(this.age); }

alert(window.age) //29 sayAge(); //29 window.sayAge() //29

创建的 age 和 sayAge 会自动归到 window对象名下.

窗口关系 及 框架

窗口位置

ie safari chrome : screenLeft screenTop firefox: screenx screeny

下面代码可跨浏览器 取得 窗口左边和上边的位置.

var leftpos = (typeof window.screenLeft == “number”)? window.screenLeft ; window.screenX;

var toppos = (typeof window.screenTop == “number”)? window.screenTop ; window.screenY;

首先用 二元操作符 确定 screenleft 和 screentop 属性是否存在 如果存在(ie chrome) 则取得这两个属性的值. 如不存在(firefox) 则取 screenX screenY的值.

窗口大小 innerwidth innerheight outerwidth outerheight

导航 和 打开窗口 window.open() 可以导航到某url 也可以打开新窗口.

window.open(“http://www.google.com”,”google”, “height=400,width=400,top=10,left=10,resizable=yes” )

google.resizeTo(500,500); 调整大小

google.moveTo(100,100); 移动位置

google.close() 关闭窗口.

弹出窗口屏蔽程序

有内置的 也有插件的.. 可以将绝大多数不想看到的窗口屏蔽掉.

于是 在弹出窗口被屏蔽时候 应该考虑两种可能性.

如果是浏览器内置屏蔽程序阻止弹出窗口: window.open() 很可能返回null值. 只要检测 这个返回值 就可以确定是否被屏蔽了.

如果是 扩展程序 阻止弹出: window.open() 通常会抛出错误.

间歇调用 超时调用

js 是一个 单线程的解释器. 一定时间内 只能执行一段代码.

为了控制 要执行的代码. 就有一个 js 任务队列. 这些任务会按照顺序执行.

系统对话框 alert()
confirm() prompt() 都可以调用系统对话框向用户显示消息.

系统对话框 与网页没有关系 和css 也没关系. 它的外观是由 操作系统 或者 浏览器设置决定的. 显示对话框的时候 代码会停止执行. 关掉对话框后 代码恢复执行.

alert 只有一个 ok 按钮. 适合 错误信息的提示.

comfirm ok + cancel 按钮. ok → true cancel/关闭窗口 → false

location 对象

最有用的 bom 对象之一. 即是 window 对象的属性 也是 document 对象的属性.

window.location == document.location 引用的是 同一个对象.

location.host www.google.com:80 返回服务器名称+端口号 location.hostname www.google.com 返回服务器名称 location.href http://www.google.com 完整的页面 url location.port 8080 端口号 location.protocal http/https 协议 location.search 查询url?

识别浏览器的标志.

插件检测 plugins

name 插件名字 description 插件描述 filename 插件文件名

function hasPlugin(name) { name = name.toLowerCase(); for (var i=0; i< navigator.plugins.length; i++ ) { if (navigator.plugins [i].name.toLowerCase().indexOf(name)>-1) {return true;} } return false; }

// 检测 flash alert(hasPlugin(“flash”))

//检测 quicktime alert(hasPlugin(“qiucktime”));

要检测插件名 . 先把传入的名字 转成小写. 便于比较.

然后 迭代 plugins 数组. 通过 indeof 检测 每个name属性.

history 对象

浏览器上网历史积累.

history 是 window 对象属性. 每个浏览器窗口.每个标签 每个框架 都有自己的 history.

安全考虑. 开发者 无法得知用户的历史记录.

可以通过 历史记录列表. 在不知道实际url的情况下 实现 后退和前进.

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

history.go(1) 前进一页 history.forword()

history.go(2) 前进2页

history.go(google.com) 跳到历史记录有google的位置.

客户端检测

每种浏览器都有自己的优点.也有缺点. 就算同一个浏览器 不同的版本 也不太一样.

不到万不得已 不要使用 客户端检测

能力检测 (特性检测)

用户代理检测

每次http请求 用户代理字符串 是作为 响应首部发送的. 这个字符串 可以通过 js 的 navigator.userAgent 属性访问.

用户代理字符串 http 明确规定: 浏览器应该发送简短的 用户代理字符串. 指明 浏览器名称和版本号.

浏览器版本号 平台 加密类型 操作系统 cpu 语言 …

识别平台

不同的平台 会有不同的问题… windows mac linux.

完整的用户代理字符串检测脚本: 呈现引擎 平台 移动设备 游戏系统..

var client = function() { // 呈现引擎 var engine = { ie: 0, gecko: 0, webkit: 0, khtml: 0; opera: 0;

//完整版本号 ver: null };

// 浏览器 var browser = { // 主要浏览器 ie: 0, firefox: 0, safari: 0, konq: 0, opera: 0, chrome: 0,

//具体版本号 ver: null };

// 平台 设备 操作系统 var system = { win: false, mac: false, x11: false,

//移动设备: iphone: false, ipod: false, ipad: false, ios: false, andriod: false, nokian: false winMobile: false

//游戏系统 wii: false ps: false };

//检测 呈现引擎 和 浏览器 var ua = navigator.userAgent; if (window.opera) { engine.ver = browser.ver = window.opera.version(); engine.opera = browser.opera = parseFloat(engine.ver); } else if (/AppleWebKit\/(\S+)/.test(ua)) { engine.ver = RegExp["$1"] engine.webkit = parseFloat(browser.ver); } else { // 近似的确定版本号: var safariVersion = 1; if (engine.webkit < 100) {safariVersion = 1;} else if (engine.webkit < 312) { safariVersion = 1.2 } else if (engine.webkit < 412) {safariVersion =1.3 } else {safariversion = 2;} } brower.safari = borwer.ver= safariVersion; }

} else if ….

DOM

针对 HTML 和xml 文档 的 一个 api.

node 类型

DOM 最常用的 : 取得特定的某个/组 元素 然后执行一些操作.

getelementbyid getelementsbytagname

文档写入: write() writein() open() close()

canvas 绘图

canvas 最受欢迎的 HTML5 元素. 负责在页面中设定一个区域. 然后用js 动态的在这个区域绘图.

canvas 由几组 api 组成. 并非所有浏览器都支持这些api.

canvas 必须设置 width height . 指定绘图区域的大小. 使用 canvas之前 . 必须先检测 getContext() 方法是否存在.

2D 绘图

矩形 弧线 路径 … 起始左边 左上角 (0,0)

var drawing = drawing.getElementById(“drawing”);

//检测浏览器 是否支持 canvas 元素 if (drawing.getContext) { var context = drawing.getContext(“2d”);

context.fileStyle = “ff0000”; context.fileRect(10,10,50,50); //绘制 红色矩形 10,10 开始 宽高:50.

context.fileStyle = rgba(0,0,255,0,5); context.fileRect(30,30,50,50); //绘制 蓝色 半透明 矩形 }

clearRect() 清楚画布上的矩形区域. …

绘制路径:

路径绘制 可以创造出 复杂的形状和线条. 必须调用: beginPath() 方法.

arc(x,y,radius,startangle,endangle,conterclockwise) xy为原型. 画一条弧线. 弧线半径: radius 起始角度:startangle 结束角度:endangle 最后一个: 逆时针/顺时针

arcTo

bazierCurveTo

LineTo

moveTo

rect(x,y,width,height) xy 左边开始画. 高宽: width height

绘制文本: filetext() stroketext() 参数:文本字符串,x坐标,y坐标, 最大像素宽度. font: 文本样式,大小,字体. textaligh: 对齐方式: start end textbaseline 文本基线. top hanging middle alphabetic ideographic bottom.

context.font = “bold 14px arial” context.textAlign = “center” context.textBaseline = “middle” context.fillText(“12”,100,20)

脚本编程:

跨文档消息传递. cross document messaging. XDM 来自不同域的页面间传递消息.

原生拖放

默认 图像 文本 链接是可以 拖动的. dragable .属性 . 默认是 true.

媒体元素

audio video 实现不依赖任何插件 就能放音视频.

src 执行媒体文件. width height 指定播放器大小.

检测 编解码的支持情况

不是所有浏览器 都支持 audio video的. 这意味着 你必须提供多个媒体来源. 就好比 chrome 不能播放 aac…

错误处理 & 调试

js 一直没有固定的 开发工具. 脚本出错时 经常会给出 Object ecpected 缺少对象这样的消息. 没有上下文消息. js 3 版本 引入了 try-catch 和 throw 以及一些错误类型. 现在 浏览器中也出现了调试工具. 最有名的就是 chrome 开发者工具.

chrome . 默认隐藏 js 错误. 因为普通人也看不懂.. 所有错误都被记录在 web inspector 控制台中.

错误处理: try-catch js 处理异常的 标准方式.

try { // 可能会出错的代码 } catch (error) { // 错误发生时 怎么处理.} 

错误类型

error: evalerror eval 函数发生异常是被抛出. rangeerror 数值 超出范围. referenceerror 找不到对象, 访问不存在的变量会报这个错误 syntaxerror 字符串有语法错误. typeerror 变量中保存意外的类型. urlerror

常见错误:

  • 类型转换错误
  • 数据类型错误
  • 通信错误.

类型转换错误:

alert(5 == “5”); true alert(5 === “5”); false alert(1 == true); true alert(1 === true); false

数据类型错误: js 是松散类型. 在使用变量和函数之前. 不会进行数据类型比较. 为了不发生这种错误 只能 开发人员 编写适当的 数据类型检测代码.

不安全的函数. 任何非字符串值 都会导致错误: function getQueryString(url) { var pos = url.indexOf(“?”); if (pos > -1 ) {return url.substring(pos +1);} return “”; }

这个函数 用意是 返回给定url中的查询字符串. 先用 indexof 寻找 字符串中的 问好. 如果找到了 用substring 方法 返回问好后面的所有字符串. 这个例子中的两个函数 只能 操作字符串. 只要传入 其他类型的数值 就会出错.

添加 一条简单的 类型检测语句 就可以确保函数不那么容易出错.

function getQueryString(url) {   if (typeof url == "string") { var pos = url.indexOf(“?”); if (pos > -1 ) {return url.substring(pos +1);}   } return “”; }

通信错误 Ajax . js 和 服务器的任何一次通信 都可能产生错误.

致命错误 非致命错误

不影响用户的主要任务 只影响页面的一部分 可以恢复 重复相同的操作 可以消除错误.

如 公共wifi 的短信验证. 由于某种原因发送不了短信.也不算致命错误.

把错误记录到服务器.

集中保存错误日志 以便查找重要错误的原因.

调试技术

最常见的 是 插入 alert() 函数. 这个比较麻烦. 调试好后还要手动清理.. 万一alert()没清理干净 还会产生后续问题..

浏览器的 js控制台 可以查看js错误.

chrome → 开发者工具→ debugger →

可以通过 console 对象 向js控制台写入消息.

error(message) 把错误消息记录到控制台 info(message) 把消息信息记录到控制台 log(message) 把一般消息记录到控制台 warn(message) 把警告消息 记录到控制台.

错误消息: 红色 警告消息: 黄色

无效字符

js文件必须只包含特定的字符. 存在无效字符时 ie会抛出 无效字符 invalid character 错误.

如 很像减号的 一横 但不是减号. 这个不能当成减号用的.

语法错误

少了一个 分号. 前后花括号 不对应.

系统无法找到指定资源

the system can not locate the resource specified.

JavaScript & XML

json

xml曾经是 传输结构化数据的 事实标准. 但是 xml 过于繁琐 就有了 json. json 是js的一个严格子集 是js中 读写数据化结构的更好的方式. 可以直接把 json 传给 eval() 而不必创建 dom对象. json 是一种数据格式. 而不是一种编程语言 并不只属于js 很多编程语言都对json支持.

json 语法: 简单值: 字符串,数值,布尔值,null, (除了 undefined)

对象: 复杂数据类型. 表示的是 一组有序的 键值对. 每个键值对中的值 可以是 简单值/复杂数据类型的值

数组:也是一种复杂数据类型. 表示一组有序的值的列表. 可以通过数值索引来访问其中的值.

js 不支持 变量 函数 对象实例. 就是一种表示结构化数据的格式.

json 字符串: 必须用双引号. “hello world!”

json 对象:

  • js对象: var person = { name: “xu.jian”, age: 18 };

    • json 对象:

    { “name”: “xu.jian”, “age”: 18 }

    区别:

    • json 没有变量声明.(json 没有变量的概念)
    • 没有末尾的分号. (for this is not a js 语句. 所以不需要 分号.)
    • 对象的属性 必须加双引号.

    { “name”: “xu.jian”, “age”: 29, “school”: { “name”: “ningbo university” “location”: “zhejiang ningbo,cn” } }

    在顶级对象中 嵌入了 学校的 信息. 虽然name有两个 但是分别属于不同的对象. 所以可以. 同一个对象 绝对不能出现两个同名属性.

json 数组

js数组: var values = [25,"hi",true];

json 数组: [25, "hi", true]

as the same . no var. and no ;

 json 数组&对象 { “title” : “professional js”, "authors": ["nick c. zakas"],  edition: 3, year: 2011 },

{ “title” : “professional js”, "authors": ["nick c. zakas"],  edition: 2, year: 2009 },

{ “title” : “professional Ajax”, "authors": [ "nick c. zakas", "jaremy", joe, ],  edition: 2, year: 2008 },

{ “title” : “professional Ajax”, "authors": [ "nick c. zakas", "jaremy", joe, ],  edition: 1, year: 2007 },

{ “title” : “professional js”, "authors": ["nick c. zakas"],  edition: 1, year: 2006 } ]

这个数组包含一些 图书对象. 每个对象都有几个属性. 其中一个属性是 authors 这个值是一个数组.

解析&序列化

json数据结构 可以解析为 有用的 js 对象. 优势极其明显.

就上一组 图书结构为例. 在解析为 js 对象后. 只需要加上下面一行就可以取得三本书名. book[2].title 这是把 json 解析后得到的对象 保存到了 变量books中.

要用DOM 的话就得长长一段代码: doc.getelementdbytagname("book")[2].getAttribute("title")

对比下 json的优势就出来了. 现在 json 就成了 web开发中 交换数据的 标准

json 对象方法: stringify() parse() 把 用于js对象序列化化为 json 字符串. 把 json 字符串解析为原生js值.

var book = { title: “professional js”, authors: ["nick"], edition: 3, year: 2011 };

var jsonText = JSON.stringify(book);

用 json.stringify() 把js对象序列化为一个json字符串. 然后把它保存在 jsontext中.

默认 json.stringify() 输出的json字符串 不包含任何空格字符或缩进. 因此 保证在 jsontext 中的 字符串如下:

{"title":"professional js","authors":["nick"],"edition":3,"year":2011}

把json 字符串直接传递给 json.parse() 就可以得到响应的 js 函数. var bookCopy = JSON.parse(jsonText);

虽然 book 和 bookcopy 具有相同的属性. 但是他们是两个独立的.没有任何关系的对象.

序列化选项: 参数2:过滤器: 数组/函数 参数3: 是否在json 字符串中保留缩进.

var jsonText = JSON.stringify(book,["title","edition"]); title 和 edition 和 js 中的参数是对应的. 因此 返回结果字符串中 只会包含这两个属性: {"title":"professional js","edition":3}

字符串缩进 json.stringify() 方法的第三个参数 用于控制结果中的缩进和空白符. 这个值 如果是一个数值. 那么就表示 每个级别缩进的空格数. 比如每个级别 缩进4个空格:

var jsonText = JSON.stringify(book,null,4); 保存在 json中的字符串如下:

{ “title” : “professional js”, “authors”: “nick c. zakas” ], “edition””: 3, “year”: 2011 },

ajax Comet

asynchronous JavaScript + xml

核心是: XMLHttpRequest 对象 XHR

XHR 用法:

xhr.open(“get”, “example.php”, false); 会针对 example.php 发起一个get 请求. 这个只会 启动一个请求 以备发送. 不会真正发送.

要发送 必须用 send

xhr.open(“get”, “example.php”, false); xhr.send(null)

这个请求是同步的. js会等到服务器响应后 继续执行后面的代码.

state 属性:

接收到响应 第一步: 检测 status 属性. 以确定响应已经成功返回.

一般来说 200 是成功标志. 这时候 responsetext 属性的内容已经就绪. .responsexml 也能够访问了.

304: 请求的资源没有修改.可以直接使用缓存在本地的版本.

http 头部信息: 每个 http 请求和响应 都带有响应的 数字能力.

xhr 蜂螯伤你亲请求时候: 还会阿下垂.

accept 浏览器能处理的 内容类型.

jttp-charset: 浏览器能显示的 字符集. accept-encoding : 浏览器能处理的 压缩编码. accept-language 浏览器当前设置的语言. cookie: 当前页面的 任何 cookie

user-agent 浏览器的用户代理字符串.

get 请求. 最常见的请求类型. 向服务器查询某些 信息.

post 请求: 向服务器发送要保存的数据. xhr.open(“post”,”example.php”, true);

example:

function submitdata() { var xhr = createxhr(); xhr.onreadystatechange = function() { if (xhr.readystate == 4) { if ( (xhr.status >= 200 && xhr.status < 300) || xhr.status == 304 ) { alert (xhr.responsetext); } else { alert(“request was unsuccessful: “ + xhr.status); } } };

xhr.open (“post”, “postexample.php”, true); xhr.setrequestheader(“content-type”, “application/x-www-form-urlencoded”); var form = document.getElementById(“user-info”); xhr.send(serialize(form)); }

这个函数 可以将 id 为 user-info 的表单中的数据 序列化之后发给服务器.

而下面的php文件 就可以通过 $—post 取得提交的数据了.

<?php header (“content-type:text/plain”); echo <<<EOF Name: {$_post['user-name']} Email: {$_post['user-email']} EOF; ?>

如果不设置 content type 头部信息. 那么 发送给服务器的数据 就不会出现在 $post 这个超级全局变量中. 这时候就必须借助别的方法了.

超时设置 timeout 请求在等待 多少毫秒之后就停止.

进度事件 progress events. 定义了 客户端 和 服务器之间的 通信事件.

  • loadstart 接收到响应数据的第一个字节时触发.
  • progress: 接收响应期间 持续不断地被触发.
  • error: 请求发生错误时触发.
  • abort 接收到完整的响应数据时触发.
  • loadend 通信完成 或或者 触发error abort load 事件后触发.

每个请求 都从 触发 loadstart 事件开始. 接下来是 一个或者多个progress 事件. 然后触发 error abort load 事件中的一个. 最后触发 loadend 事件结束.

comet

更高级的 Ajax技术. 有人叫 服务器推送.

Ajax 是一种 从页面向服务器请求数据的技术. comet 是一种 服务器向页面推送数据的技术. 能让 信息几乎实时的被推送到页面上. 非常适合处理 体育比赛的分数 和 股票报价.

两种comet 方式: 长轮询和流. 短轮询和流(短轮询).

长轮询: 浏览器定时向服务器发送请求. 看数据有没有更新. 短轮询: 页面发起一个到服务器的请求,然后 服务器一直保持连接打开.直达有数据可发送. 发送完数据后 浏览器关闭链接.随即又发起一个到服务器的新请求. .. 重复….

http 流:  在页面的 整个生命周期内 只使用一个 http 链接.

<?php >

$i = 0; while(true) { //输出一些数据 然后立即刷新输出缓存 echo “number is $i”; flush();

// wait seconds sleep(10); $i++; }

所有服务器端语言 都执行 打印到输出缓存 然后刷新的功能: 把输出缓存中的内容一次性全部发送到客户的功能. 这是实现http流的关键.

chrome 可以通过 侦听 readystatechange 事件. 及 检测 readystate值是否为3.就可以利用xhr对象实现http流. 这些浏览器 随着不断从服务器接收数据. readystate 的值会周期性的变为3. 当变为3时: responsetext 属性中就会保存接受到的所有数据. 这时候 需要比较之前接收到的数据. 决定从什么位置开始取得最新的数据.

服务器发送事件

SSE server-sent Events . 围绕只读comet 交互推出的api.

sse api 用于创建到服务器的单向连接. 服务器可以通过这个连接发送任意数量的数据. 服务器响应的 mime 类型必须是 text/event-stream 而且是浏览器中的jsapi 呢个解析格式输出.

sse 支持: 短轮询 长轮询 和 http流. 而且能在断开连接时 自动确定何时重新连接. 有了这么简单啊api 再实现comet就容易多了.

sse api: 需要预定新的事件流. 首先要创建一个 新的 eventsource对象.并传进一个入口点: var source = new eventsource(“myevents.php”)

事件流: 服务器事件会通过一个持久的http响应发送. 这个响应的类型 为 text/event-stream 响应格式是 纯文本. 最简单啊情况是 每项数据都带有 data:

data: foo data: bar

对以上响应事件:
第一个message 事件 返回的 event.data 值是 foo. 第二个message 事件 返回的 event.data 值是 bar.

web sockets

在一个单独的持久连接上提供全双工,双向通信.

在js中 创建 web socket 之后. 会有一个http请求从浏览器发起链接. 取得服务器服务器响应后. 建立的连接会从 http 协议 转换为 socket 协议.. 也就是说 标准的 http服务器无法实现 web sockets. 只有支持这种协议的专门服务器才能正常工作.

web sockets 使用了 自定义的协议. 未加密的: http:// → ws:// 加密连接: https:// → wss://

使用自定义协议 而非 http 协议的好处: 能在 客户端和服务器之间 发送非常少量的数据. 而不必单向 http那样字节级的开销. 由于传递的数据包很小.所以非常适合移动应用.

缺点: 制定协议的时间很长 . 因为不断有人发现这个新协议存在一致性和安全性问题.

离线应用 客户端存储

支持离线 web 应用是HTML5的另一个重点. 在设备不能上网的适合 仍然可以运行的应用.有电就能使用.

开发离线应用步骤: 了解设备是否能上网. 有本地空间可以读写保存数据.

离线检测: 判断设备 在线还是离线. navigator.online true/false 在线/离线

eventutil.addHandler(window,”online”,function(){alert(“online”);}); eventUtil.addHandler(window,”offline”,function(){alert(“offline”);});

应用缓存:

application cache. appcache. 是从浏览器缓存中 分出来的一块缓存区. 想要在这个缓存中保存数据.可以使用一个描述文件. manifest file 列出要下载和缓存的资源.

简单描述文件示例: cache manifest # comment file.js file.css

描述文件中列出的都是需要下载的.可以离线使用. 把描述文件 和 页面关联: <HTML mainfest=”/offline.mainfest”> //告诉页面 offline.mainfest 中包含着描述文件 描述文件 扩展名: 以前用manifest 现在用appcache.

离线状态: applicationcache 对象. 的 status 属性. 0 无缓存. 1 闲置: 缓存没有得到更新. 2 检查中: 正在下载描述文件 并检查更新 3 下载中: 缓存正在下载描述文件中指定的资源. 4 更新完成: 下载完毕.可以用 swapcache()来使用了. 5 废弃: 缓存描述文件不存在.

checking 浏览器为应用缓存查找更新时触发. error: 检查更新/下载资源期间发生错误时触发 noupdate: 检查描述文件时发现文件无需更新时触发. downloading: 在开始下载应用缓存资源时触发. progress: 下载缓存过程中 不断的触发 updateready 缓存下载完毕且可以通过 swapcache 使用时触发. cached 应用缓存完整时触发.

一般来说 这些事件会随着页面加载 按顺序触发. 也可以调用update方法手工干预.

数据存储

直接在客户端上储存用户信息能力的要求. 属于某个特定用户的信息 就应该储存在该用户的机器上. 方案一: cookie.

最初是 客户端用于储存会话信息的. 要求 服务器对任意http请求发送 set-cookie http 头作为响应的一部分.其中包含会话信息. 服务器响应头: http/1.1 200 ok content-type: text/HTML set-cookie: name=value other-header: other-header-value

这个http响应 设置以name为名称. 以value为值的一个cookie. 名称和值在传送时候 都必须是 url 编码的.

浏览器会储存这样的会话信息.并在这之后,通过为每个请求添加cookie http 头将信息发送回服务器. get /index.HTML http/1.1 cookie: name=value other-header: other-header-value

发送回服务器的额外信息可以用于唯一验证客户来自于发送的哪个请求.

限制:

cookie 的性质是绑定在特定的域名下的. 设定了一个cookie 后. 再给创建它域名发送请求时 都会包含这个cookie. 这个限制 确保了 存储在cookie中的信息.只能让批准的接受者访问. 而无法被其他域访问. . 每个域的cookie 总数是有限的.50 左右.

cookie 构成:

  • 名称: 一个唯一确定的 cookie 名称. 名称不区分大小写. myCookie = Mycookie cookie名称必须是通过 url编码的.

  • 值: 存储在cookie中的 字符串. 值必须被url编码.
  • 域: 对哪个域有效.所有发向该域的请求中都会包含这个cookie信息. 可以包含单个子域. 也可以所有子域都有效
  • 路径:对于指定域中的哪个路径 应该向服务器发送cookie 如果指定 cookie 只有从 0214.help/books/ 中才能访问. 那么客户端访问0214.help/ 就不会发送cookie 哪怕是在一个域中.

失效时间: cookie 何时被删除的时间戳.(何时应该停止向服务器发送这个cookie) 默认浏览器会话结束.就会删除所有cookie. 也可以自己设置: 按照 GMT格式就行 wdy,dd-mon-yyyy HH:MM:SS 用于删除cookie 的精确时间. 这样 cookie在浏览器关闭后依然保存在用户的机器上.

安全标志: 指定后 cookie 只有在使用ssl 连接时才会发送到服务器.例如: cookie 信息只能发送给 https:// 不发给http://

http/1.1 200 ok content-type: text/HTML set-cookie: name=value;expires=Mon, 22-Jan-07 07:10:24 GMT; domain=.0214help.com other-header: other-header-value

这个cookie 会在 2007 年 1 月22 失效. 对0214.help的 任何子域都有效.

js中的cookie.

web 储存机制: 克服 由cookie 带来的一些限制. 当数据需要被严格的控制在客户端上时 无需持续地把数据发回到服务器.

主要 目标: 提供一种在cookie 之外的 存储会话数据的 途径. 提供一种存储大量可跨会话存在的数据机制.

storage: clear 删除所有值. getitem(name) 根据指定的name 获取响应的值. key(index) 获得 index 位置处 值的名字. removeitem(name) 删除由name指定的 名值对儿. setitem(name,value) 为指定的name 设置一个对应值.

sessionstorafe: 对象 储存特定于某个会话的数据. 该数据只保持到浏览器关闭.

indexedDB 数据库 最大的特色是 使用对象保存数据.而不是用表来保存数据. 一个 indexedDB 数据库 就是一组位于相同命名空间下的对象的集合.

索引

可能需要为一个对象指定多个键. 如要通过用户id 和 用户名 两种方式来保存用户资料. 就需要通过这两个键来存取记录. 可以考虑用id 作为主键.然后为用户名创建索引.

代码 可维护性. 很重要. 可理解性. 直观性 可扩展性 可调试性

可读性: 代码缩进.

给每个函数都编写文档.注释.

变量和函数名: 起名对代码的可理解性 和 可维护性 非常重要.

一般以动词开始: getName 返回布尔类型的函数 一般 is 开头 isEnable()

名字应该合乎逻辑. 不要担心长度. 长度问题可以通过后处理/压缩 来缓解.

性能: js 代码的执行效率 越来越受到关注. 因为 js 最初是一个解释型语言. 执行速度要比 编译型语言慢的多.

chrome 是第一款内置优化引擎.把js 编译成本地代码的浏览器. 但是即使到了 编译执行js的新阶段.还是存在低效率的代码.

注意作用域: 访问全局变量总是要比访问局部变量慢.

避免全局查找

优化循环 循环很常见.同样很重要.

使用后测试循环. for while 都是前测试循环. do-while 是后测试循环. 可以避免最初终止条件的计算. 运行更快.

比如: for (var i=0; i< values.length; i++) { process(values[i]); } 可以改成: for (var i=values.length -1; i>=0 ; i-- ) {process(values[i]);} 这样就从 o(n)级别的调用 变成了o(1) 级别的.

还可以改成:

var i=values.length -1; if (i>-1) { do {process(values[i]); } while(–i >=0); }

最小化语句数 单行语句执行多个操作 肯定比多行执行多个操作块.

比如: 多个变量的声明:

var count = 5; var color = "blue"; var values = [1,2,3] var now = new Date()

var count = 5, color = "blue", values = [1,2,3], now = new Date();

优化 DOM 交互  js各方面中 DOM 无疑是最慢的一部分.

压缩

代码长度: 浏览器需要解析的字节数. 配重: 实际从服务器传送到浏览器的字节数.

早期这两个数字几乎是一样的; 现在很少相等.

  1. 文件压缩. js 并非编译成字节码. 而是按照源代码传送的. 代码文件通常包含浏览器执行不需要的额外信息:注释 额外的空白.长长的变量名.
  • 删除额外的空白 包括行.
  • 删除所有注释
  • 缩短变量名.

http 压缩