Head first javascript

基础

<script type="text/javascript"> 
    function validateNumber(value) { 
        // Validate the number 
        if (!isNumber(value))    alert("Please enter a number."); 
    } 
</script>

javascript 最好与html分离
浏览器里具有一种特殊软件-javascript解释器

onload 事件

onclick

javascript 是通过事件被调用的.

事件后可以接多个函数名, 例如:

<body onload="alert('Hello, loading now');">

<body onload="function1(); function2();">

// 消息
prompt 提示
alert
confirm

设置元素属性

document.getElementById("rockImg").src = "rock_happy.png"


3种基本数据类型
number, boolean, text

const pi = 3.14;       // 定义常量 
var aa = 3.14;        // 定义变量

变量定义时, 最好直接进行初始化.

NaN 设计的目的是 数字数据类型有误时

parseInt(), parseFloat() 把字符串转换成数字

document.getElementById("aaa").value

toFixed(2)  // 四舍五入到小数点后两位

isNaN(document.getElementById("pick").value)

活用 parseInt, 例如用户输入 3 dozen , dozen 是 "打" 的意思, 1打是12个, 所以可以用以下方法解决:

function parseDonuts(donutString) {

  numDonuts = parseInt(donutString);

  if (donutString.indexOf("dozen") != -1 )

    numDonuts *= 12;

  return numDonuts;

}

浏览器可以做什么 ?

提供度量单位, 历史记录, 定时器, cookie,

cookie 就像变量, 浏览器把他存储在用户的硬盘里, 存活期超过单一 web session.
换句话说, 你可以放着某个网页稍后再回来, 数据依然等着你

timer 以毫秒即 千分之一秒表示, 1000 即为1秒

refresh(); // 刷新网页, setTimeout(refresh, 120000);
setTimeout("alert('wake up');", 60000 );  // 单次计时器, 可以用 for 循环+setTimeout 来模拟 setInterval, 而且这种方法比较好.
setInterval("alert('wake up');", 60000);  // 间隔计时器
clearInterval(timerID);

document.body.clientWidth    // 窗体宽度 
document.body.clientHeight  // 窗体高度

document.getElementById("rockImg").style.height = "100px";

onresize 浏览器尺寸被变动

javascript 于 浏览器关闭或网页重新载入时摧毁"所有"变量

适合客户端, 便利的持久性数据存储方案 = cookie

cookie 以独一无二的名称存储一段数据, 这点很像变量, 但是cookie 可以设定有效日期, 时限一到, 则销毁 cookie, 这点跟变量不一样. 实际上 cookie 并非永恒不变, 它们只是比变量的寿命更长, 你也可以创建未设定有效日期的cookie, 但是它将与一般javascript的变量没有两样-于浏览器关闭时清除. cookie 以长文本字符串的形式存储于用户的计算机中, 分号分隔各cookie, 例如:

userName=Paul; expires= 9/3/2009

以上格式, 用分号分隔,

readCookie()    // 读取cookie  
writeCookie()    // 写入cookie   
eraseCookie()    // 清除cookie

function writeCookie(name, value, days) {    // days 为cookie 可以存活的天数

  var expires = "";

  if (days) {

    var date = new Date();

    date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));    // 计算有效日期, 把天数换算成毫秒

    expries = "; expires=" + date.toGMTString();

  }

  document.cookie = name + "=" + value + expires + "; path=/";    // 这个是 cookies 的存储形式

}

function readCookie(name) {

  var cookies = document.cookie.split(';');   
  for (var i=0; i<cookies.length; i++) {    
    var c = cookies[i];    
    while (c.charAt(0) == '' )    
        c = c.substring(1, c.length);    
    if (c.indexOf(serachName) == 0)    
        return c.substring(searchName.length, c.length);    
  }

  return null;

}

function eraseCookie(name) {

  writeCookie(name, "", -1);

}
 
<script type="text/javascript" src="cookie.js"></script>



function greetUser() {    // 保存用户内容, 如果找到用户名在cookie中, 就显示出来, welcome back.
    userName = readCookie("irock_username"); 
    if (userName) 
        alert("Hello" + userName + ", I missed you."); 
    else 
        alert('Hello, I am your pet rock.'); 
}

writeCookie("irock_username", userName, 5 * 365);  // 要先把内容保存在cookie中

判断是否支持cookie
if ( navigator.cookieEnabled )        // 判断是否支持 cookie

数组可以存储不同类型的东西, 但是最好还是存储同类型的

二维数组  // 最好每行元素个数相同, 即内部数组是同样长度

var seats = new Array(new Array(9), new Array(9), new Array(9)); 
var seats = [ [false, true], 
            [false, true], 
            [false, true] ];

函数

函数的作用:1 分解问题, 2 去掉重复代码

分解问题, 软件设计的经典思想

去掉重复代码, 可重构极大影响, 如果有很多重复代码, 当你需要修改程序时, 你就要修改所有重复的代码.

MVC 模型
内容 html 即 model ( 结构 )
功能 javascript 即 control ( 动作 ) 
外观 css 即 view ( 式样 )

函数可以理解为 只是变量, 函数名称是变量名称, 函数体是变量值. 

var showSeatStatus = function(seatNum) { 
    alert("This seat is" + getSeatStatus(seatNum) + "."); 
}; 


当函数主体单独出现而没有名称时, 又被成为 函数字面量, 上面例子就是函数字面量:

函数其实只是“值” 引用到函数主体的变量

函数字面量的意义, 函数字面量只是没有名称的函数主体, 有点像实际数据, 例如一个数字
函数字面量重要性在于它们很适合需要快速偶发回调函数的情况,换句话说,函数只被调用 1 次,
而不是被你的程序代码调用, 除非不只需要函数引用( 例如需要传送自变量给函数), 函数字面量才真的必要
( 这里的传递的自变量是一个函数, 它类似局部变量, 函数调用结束后, 就销毁了 )

有了函数字面量, 函数就能像变量一样被操控, 例如:

var myShowSeatStatus = showSeatStatus;  // showSeatStatus 是刚刚上面定义的变量

以上内容可以被称为”函数引用”, 即函数主题又多了一个变量名为myShowSetaStatus, 这个名字引用了这个函数主体

函数调用”, showSeatStatus(); 这个是函数调用, 它需要执行函数主体的代码, 注意后边有个(), 这是最主要区别

目前在 html 代码中, 嵌入了javascript函数的内容, 例如 <body onload=“initSeat();”> 这样, javascript程序员就需要深入到html中, 确认html中放置javascript的位置, 但是我们也可以不这么做, 使用函数引用联结事件, 例如:

window.onload = initSeats;  // 注意这是函数引用

这样的好处, 就是将 javascript 与 html 完全分离.

当我们需要传递参数时, 函数引用就不合适了, 这时函数字面量就提供了帮助, 例如: 点击座位号的事件, 需要知道点击的是哪个座位,

document.getElementById(“seat26”).onclick = function(evt) {

  showSeatStatus(26);  // 26 这个参数传递进来

};
何时运行的问题: ( 比如你在 javascript 中写了如下代码, 但是这段代码放在什么地方呢?  
document.getElementById(“seat26”).onclick = function(evt) {
}
首先, 在<head> 标签下的 <script> 脚本, 会被加载进内存, 作为准备, window.onload = initSeats; 这个语句在这个位置时,
当页面被加载时, 由于触发了 onload() 事件, 又因为 onload 对应的function 已经被加载到内存中, 所以这是页面可以执行
initSeats()函数, 例如:
<html>
    <head>
        <script type="text/javascript">
            function initSeats() {
                alert("hello");
            }
            window.onload=initSeats;    
        </script>
    </head>
    <body>
        <p>haha</p>
    </body>
</html>

以上程序, 会在打开网页时, 自动执行.

所以这段代码放在什么位置的问题, 就是应该放在以下内容里, 因为会在页面加载时, 就会执行.

window.onload = function() {

  // write here, onload 事件联结

  document.getElementById(“seat26”).onclick = function(evt) {

  }  // 最后, 初始化 onload, 即调用 initSeats(); 函数  initSeats();};


所谓”回调函数”, 就是这些 onload 等事件, 另外还有ajax 请求数据时也有回调函数.


所以, onload 实际上变成了事件初始化函数, 用于设置网页中其他事件.

问? 为什么把 onload 事件处理器创建为函数字面量 ?

答: 因为完全没有创建有名称的函数的理由, 这个函数只会创建一次, 创建的目的就是响应onload时间.


函数字面量有时被称作匿名函数

// ----------- 这部分内容再确认, 貌似不是这本书上的 ------------------

一、什么是匿名函数?
在Javascript定义一个函数一般有如下三种方式:

函数关键字(function)语句: 普通
function fnMethodName(x){alert(x);}
函数字面量(Function Literals):字面量
var fnMethodName = function(x){alert(x);}
Function()构造函数: 很少用
var fnMethodName = new Function('x','alert(x);')
上面三种方法定义了同一个方法函数fnMethodName,第1种就是最常用的方法,后两种都是把一个函数复制给变量fnMethodName,而这个函数是没有名字的,即匿名函数。实际上,相当多的语言都有匿名函数。

二、函数字面量和Function()构造函数的区别
虽然函数字面量是一个匿名函数,但语法允许为其指定任意一个函数名,当写递归函数时可以调用它自己,使用Function()构造函数则不行。
var f = function fact(x) { if (x < = 1) return 1; else return x*fact(x-1); };
Function()构造函数允许运行时Javascript代码动态的创建和编译。在这个方式上它类似全局函数eval_r()。
Function()构造函数每次执行时都解析函数主体,并创建一个新的函数对象。所以当在一个循环或者频繁执行的函数中调用Function()构造函数的效率是非常低的。相反,函数字面量却不是每次遇到都重新编译的。
用Function()构造函数创建一个函数时并不遵循典型的作用域,它一直把它当作是顶级函数来执行。
var y = "global"; function constructFunction() { var y = "local"; return new Function("return y"); // 无法获取局部变量 } alert(constructFunction()()); // 输出 "global" 
和函数关键字定义相比Function()构造器有自己的特点且要难以使用的多,所以这项技术通常很少使用。而函数字面量表达式和函数关键字定义非常接近。考虑前面的区别,虽然有消息说字面量的匿名函数在OS X 10.4.3下的某些webkit的引擎下有bug,但我们平常所说的匿名函数均指采用函数字面量形式的匿名函数。更多详细内容可以阅读《JavaScript: The Definitive Guide, 5th Edition》的Functions那章。

// ----------- 这部分内容再确认, 貌似不是这本书上的 -------------------

表单

javascript 可以协助处理表单数据的可靠性, 例如: 输入的日期格式是否正确.

访问表单数据的两种方法:
<input id="zipcode" name="zipcode" type="text" size="5" /> 其中, id 是用来唯一标识这个html 元素的, name是用来在表单内唯一标识
为了访问输入表单的数据,首先需要区分表单中的每个域,这点可利用HTML代码 id 或 name 属性( 或两者并用 ) 处理
表单具有两种识别方式
1. getElemById()
2. <input id="zipcode" name="zipcode" type="text" size="5" onclick="showIt(this.form)"/>
form对象也是个数组, 负责存储表单中所有域, 但是这个数组是利用 name 属性标识的, 例如:
function showIt(theForm) {
    alert(theForm["zipcode"].value);
}
实参:this.form 是一个数组
形参: theForm 这个数组是利用 name 属性来读取 value的 theForm["zipcode"]

输入表单时产生的事件( 有顺序的 )
1. onfocus
2. 输入数据
3. 离开该域 onblur/onchange ( onchange必须修改内容才能出发, 且不能为空域, onblur 只要到过该域, 离开时就会触发 )
   onblur 是 onfocus 相反事件
4. 选择下个区域 onfocus

当然在输入的过程中, 还有许多事件, 例如 onkeypress, onkeyup, onkeydown 等等.

检验表单输入( 不使用烦人的alert

<input id=”phone” name=”phone” type=”text” size=”12”

  oblur=”validNonEmpty(this, document.getElementById(‘phone_help’)); ” /> 
<span id=”phone_help" class=”help”></span>

后边这个help 是用于用户输入错误时, 再表单后边给予提示的内容, 目前为空, 但是如果一旦输入错误, 你可以写上提示内容,

并且, 可以设置颜色等, 注意: 这两个地方的 id 一定要相同, 至于函数就类似下边的代码.

<span id="message_help" class="help"></span> 
function validateNonEmpty(inputField, helpText) { 
    if (inputField.value.length == 0) { 
        if (helpText != null) { 
            helpText.innerHTML = "Please enter a value."; 
        } 
        return false; 
    } else { 
        if (helpText != null) { 
            helpText.innerHTML = ""; 
        } 
        return ture; 
    } 
    
}

<input id=”phone” name=”phone” type=”text” size=”12” onblur=”validateNonEmpty(this)” />

这里的this, 就是指表单域本身, 也就是说可以在形参那边写 theForm 来接收this, 然后使用 theForm[phone] 来判断

不合理的数据, 不应该到达服务器, 类似以下函数 :

function placeOrder(form) {  // 形参, 接收表单域实参

  if (validateLength(1, 32, form[“message”], form[“message_help”]) &&

    validateZIPCode(form[“zipcode”], form[“zip_code_help”])) {

      form.submit();  // 提交表单, 将数据送服务器

    } else {

      alert(“i’m sorry but there is something wrong with the order information.”);

    }

}

正则表达式

正则表达式 专门用于匹配文本模式, 可用于创建模式, 而后应用文本字符串, 搜索匹配的部分.
正则表达式只能用于匹配字符串, 不能用于其他类型.

例如, 你定义了一个模式, 有5位数字组成, 那么就可以利用正则表达式, 查看是否匹配, 来判断时候把消息发到服务器

正则表达式: / Expression /
模式 = /^d{5}$/  模式要在 // 双斜线中间
# 匹配数字 例如 /####-##/

. 匹配任何字符(不包括换行符)
s 匹配空格 (包括空白字符(space), tab, 换行符)
d 匹配数字
^ 匹配模式的字符串前部能有其他文字, = linux (开始字符)
w 匹配任何字母(字母或数字)
$ 字符串需以模式结束 = linux (结束字符)
* 0 或多次
{n} 需出现 n 次, {2, 5} 出现2-5 次
+ 必须出现1次或多次
? 0 或 1次
() 集合字符或 /和元字符, 成为子模式, 即将括号里的内容作为一个单元来处理,

例如 /(hot)?  ?Donuts/ 这个就匹配 “Donuts” 和 “hot Donuts” 一定要有两个问号, 第2个问号是用来判断空格是否需要出现一次, 或一次都不出现.
|相当于 or 例如 /(red|blue) pill/  注意: 模式串里的空格不能乱加
字符类 [] 擅长把非常着重于可选字符的规则建立到子模式中, 你可以把字符类想成一组匹配单一字符的规则.

[characterClass] 在字符类内部, 每个列出的字符都是合格的字符匹配目标, 不过字符类的匹配都是对单一字符的匹配, 除非字符类后面加上限定符, /$d[d.]*/ 后边的限定符* 就是对前边字符类进行限定. 这个可以匹配 “$3.50”, “$5”, “$19.95”

/d[iu]g/  匹配 dig, dug, = linux ( 可选 )

邮件地址匹配: /^[w._]+@[w-]+(.w)+$/ 注意, 这的+是1个或者多个的意思
例如:格式要求 “#####-####”, 则 /^d{5}-d{4}/
/(hot)? ?Donuts/ 可匹配出 “Donuts” " Donuts" "hot Donuts"
匹配任何字母 /w*/
匹配非空字符 /.+/
/(red|blue) pill/  "red pill" "blue pill"

正则表达式不是字符串, 你可以把正则表达式当成对字符串的描述, 至少当成对部分字符串的描述
正则表达式与字符串紧密相关。

利用正则表达式,校验数据

var regex = /^d{5}$/; 
if (!regex.test(inputField.value))

function validateRegEX(regex, inputStr, helpText, helpMessage) { 
    if (!regex.test(inputStr)) { 
        if (helpText != null) 
            helpText.innerHTML = helpMessage; 
        return false; 
    } else { 
        if (helpText != null) { 
            helpText.innerHTML = ""; 
        } 
        return true; 
    } 
    
}
也可以将 正则表达式作为实参, 传递进函数, 如下:
return validateRegEx(/^d{2}/d{4}$/, inputField.value, helpText);
 

利用 DOM

DOM : document object model

document.getElementByID("aaa")          // 抓取html 元素 by id, 其中 “aaa”就是元素id值
document.getELementsByTagName("div");     // 抓取一类 html 元素, 例如抓取所有的 div 元素
document.getElementsByTagName("img")[3] // 抓取第 4 个 img 元素,javascript下标是从0开始

<p id=”story”>

  you are standing

  <strong>alone</strong> in the woods

</p>
document.getElementByID(“story”).innerHTML // 这里抓取的内容, 包括里边的 html 元素一起

innerHTML 取得元素的所有内容, 包括里边的 HTML 标签.

可以利用 innerHTML 来设置网页, 而不仅仅是从网页get内容, 例如:

document.getElementById(“story”).innerHTML = ”You are <strong>not</strong> alone!”;

注意, 以上的innerHTML没有附加的概念, 如果想要在此基础上附加, 可以使用

elem.innerHTML += “This sentence gets appended.”

通过 dom, 网页看起来就像 形成树状的层层元素, 各个元素就是书上的每片叶子节点.

image

注意: 图中, 因为脚本中元素标签的前后有空格, 所以, 例如在元素 <p> 的前后有个text类型的空格. 所以我们可以在写脚本时, 不写空格, 就不会再”树”中出现空的空格脚本.

节点有不同类型:

document : 根节点

element : 元素节点

text : 元素的文本内容, 一定存储在元素下的子节点里.

attribute: 元素的属性, 可透过元素节点访问, 但不会直接出现在 dom 树里.

综上, 可以看到dom树, 是“骨架”, javascript 支持提取骨架中的某个内容, 修改, 同时也可以修改该元素的属性, 例如css属性, 但是属性不会列在”骨架”中.

dom 把网页视为结点构成的层次树, 从 document-> html -> ...

nodeValue (不含元素, 文本节点使用,text类型)
nodeType  ( 结点类型 )
childNodes ( 所以子结点数组 )
firstChild ( 下一个子结点 )
lastChild( 最后子结点 )

alert(document.getElementById("scenetext").nodeValue);
document.getElementsByTagName("body")[0].childNodes[1].lastChild

image

注意: 这的”” 是因为书写脚本时, 元素后边自己写的空格, 如果不写, 这个空格就不会出现在文档树中.

image

改变结点文本的 3 个步骤
1. 移除所有子结点 removeChild()
2. 根据新内容创建新的文本结点 createTextNode()
3. 把所创建的文本子结点附加在结点上 appendChild()

var node = document.getElementById("story"); 
while (node.firstChild) { 
    node.removeChild(node.firstChild); 
} 
node.appendChild(document.createTextNode("Ok, maybe you are alone."));

通过 dom 修改 css 式样

调整一类式样 
<span id="decision1" class="decision" onclick="changeScenne(1)">Start Game</span>
<span id="decision2" class="decision" onclick="changeScenne(2)">End Game</span>
alert(document.getElementById("decision1").className);  // 读取到了该 class 的名字
想要改变式样, 只要改变式样名称就可以了 ( 换一组式样 )
document.getElementById("decision1").className = "decisionverse";
因为 css 是通过 html 元素来进行设置的, 而 javascript 可以通过dom 修改html元素的值, 这样就对应到了另外的css式样


调整单项式样
document.getElementById("decision2").style.visbility = "visbile";
找到对应元素, 增加 style,该style就是对应该元素的 css 式样, 就可以直接更改了 ( 换一个式样 )

createElement() 创建HTML元素
createTextNode() 创建文本, 肯定是叶子节点了
var decisionElem = document.createElement("p");        // 创建了一个html元素<p>赋值给 decisionelem, p元素漂浮在"空中"
decisionElem.appendChild(document.createTextNode"fork in the road");     // 仍然漂浮在"空中"
document.getElementByID("History").appendChild(decisionElem);            // 插入结点

dom 补充

image

1. window 对象作为全局对象. 在页面上创建的所有全局对象都会变成window对象的属性.

2. 方法在对象下面以函数形式存在.

最重要的dom节点为: document, element, text.

3. 每个浏览器引擎对dom的支持有一些轻微的不同.

image

image

对象

数据 + 行为 = 对象
成员变量 用来存储 数据

成员方法 用来实现 行为

var invitation = new Invitation("Somebody", "Something", "Sometime", "Somewhere");

innerHTML 的好处是, 当你利用javascript 生成元素时, 可以一次性将 父子 元素同时生成, 看下例:
因为在 innerHTML 中已经包含了元素的信息
blogText += "<strong>" + blog[i].date + "</strong><br/>" + blog[i].body + "</p>" ;
document.getElementById("blog").innerHTML = blogText;

var now = new Date();    // date 对象   var blogDate = new Date("08/14/2009");

getMonth() // 返回日期中的月份, 例如 9

getDate()  // 返回日期中的哪天 1~31, 例如 24

getFullYear()  // 返回日期中的四位年份, 例如 2008

对象字面量
var blogEntry = new Blog("Nothing going on but the weather", new Date("10/31/2008"));

toString() 方法 转换成文本, 一般用于将日期对象转换成文本.

把数组也看成是对象, 数组对象的 sort 方法
自定义排序方式
function compare(x, y) {
    return x - y;
}
<0 x 排序 y 前, 0 不排序, >0 y 排序 x 前
nums.sort(compare);

搜索字符串内部
var str = "Got the aaa cube i ordered."
var location = str.indexOf("aaa");   // 返回 8, 下标从 0 开始
charAt 搜索单个字符, indexOf 搜索子串

Math 对象
alert(Math.random());        // 生成随机数

Math.round()  // 四舍五入

Math.floor()   // 把浮点数无条件舍去为整数

Math.ceil()  // 把浮点数无条件进位为整数

Math.random() // 产生 介于 0~1之间的随机数

Math.PI  // 常量 3.14

因为 Math 对象中只有静态方法, 没有实例变量和方法, 所以不用创建对象

创建自己的对象

错误的创建过程, 每个实例都有如下方法, 效率低下:

function Blog(body, date) { 
    this.body = body; 
    this.date = date; 
    this.toString = function() { 
    } 
    this.toHTML = function() { 
    } 
    this.containsText = function() { 
    } 
}

// prototype 方法属于类层, 非实例层 
Blog.prototype.toHTML = function() { 
// something   
}

构造函数时创建 JavaScript类时非常重要的一部分, 因为它们负责创建对象实例.

即, 如果在构造函数中创建方法, 那么会在每个实例中都创建一个, 一模一样的方法. 这显然不是我们想要的.
你可以把构造函数和原型分别想成javascript类拼图的两块重要拼图, 构造函数负责设定实例的一切事项,
原型则处理类层的一切事项. (方法存储在类里, 而非实例中, 这样所有的实例都可以共享一份方法.)

使用 prototype 可以创建 类拥有的方法 ( 而非属于某个对实例的方法 ), 注意 类拥有的方法不是下边的类方法

例如上边的, Blog.prototype.toHTML = function() {}  // 这个Blog是类名.

image

类的创建是通过构造函数进行的.

并且构造函数中, 只需要出现实例变量, “类拥有方法” 要定义在构造函数外边.

对象名 采用首字母大写, 构造函数跟对象名同名, 所以也是首字母大写
类对象, Blog.prototype.signature = "Puzzler Ruby";  // 类特性

类特性的访问:

1. 通过实例访问, this.雷特性

2. 通过类方法访问, ( 类方法不是类拥有的方法, 不同 )

类拥有的方法, 意思是它属于类, 但能访问实例的成员变量.

Blog.prototype.setName = function() {}  // 这个是类拥有的方法
类方法,只能访问类特性(当然不能访问实例变量, 因为实例变量可能还没有被创建呢.)

Blog.showSignature = function() {}  // 这个是类方法, 注意没有 prototype 啊.

类方法与实例没有联系, 调用时只需要使用类名.方法就可以了, 类似 Math.random 一样.

( 个人, 类方法类似于静态方法, 类拥有的方法, 只是javascript特有继承中的一个环节 )

除错

Firefox 是普遍认为最好的调试浏览器 Firebug

自定义控制台

function DebugConsole() {

  var consoleElem = document.createElement(“div”);

  consoleElem.id = “debug”;

  consoleElem.style.fontFamily = “monospace”;

  consoleElem.style.color = “#333333”;

  document.body.appendChild(consoleElem);  // 将调试台加到网页的最后端

  consoleElem.appendChild(documehnt.createElement(“hr”));  // 调试台的第一个子元素是”水平线”

  this.shaded = false;  // 背景颜色开始设为false, 形成预设的白色背景

}

DebugConsole.prototype.displayMsg = function(msg) {

  var msgElement = document.createElement(“div”);

  msgElement.appendChild(document.createTextNode(msg));

  msgElement.style.backgroundColor = this.shaded ? “#EEEEEE”: “#FFFFFF”;

  var consoleElem = document.getElementById(“debug”);

  consoleElem.appendChild(msgElement);

  this.shaded = !this.shaded;  // 每则信息的背景颜色会更替, 增加可读性.

}


使用你的控制台来进行调试

调试脚本, 不能放在<head>标签中, 即网页开始的地方, 因为那个时候, 脚本载入内存, 但是这个时候html树还没有被解析, 所以这时候无法访问到html树中节点的内容.

把函数代码放在网页标头, 与放在HTML中的javascript代码是两回事, 放在标头的代码, 在加载网页前就会被加载到内存, 而在HTML中的代码, 知道被调用才会加载到内存.

控制台放置的位置:

浏览器发出的 onload 事件能让我们知道网页完全载入的时期, 不过存储这个对象的console变量仍应该在网页标头里声明, 让这个对象为全局变量.

<body onload=”console = new DebugConsole(); ”>

利用 注释 代替删除 暂时不用的代码.

Ajax ( 再确认吧 )

从网页的结构中, 将内容分离出来.

动态数据: 在网页被浏览器处理时, 动态供给网页的数据.  需要以什么样的格式存储 ?

动态网页: 以动态数据建造的网页称为 数据驱动网页, 这类网页值定义了等着数据填入的网页架构而已.

数据的实体另外存储成一份文件, 可在不触碰网页的状态下编辑这份文件.

网页包含网页结构所用的html代码, 还有整合动态网页和数据之间的javascript代码.

Ajax 让网页能动态接收网络服务器的数据

image

Ajax 能够动态的快速下载并存储数据以及实时相应用户, 却不用重新载入网页或利用浏览器的某些小手段

XML
xml 与 html 类似, 也是标签, 为任何类型的数据设计格式标记

XML 让你用自己的标签标示数据 
例如电影
<moveie>
    <title>Cleaming the Cube</title>
    <releaseDate>01/13/1989</releaseDate>
    <direction>Graeme Clifford</direction>
    <summary>A skateboarder investigates the death of his adopted brother.</summary>
</moveie>
xml 有点类似数据库, 可以存储东西, 元素名有点类似"column name", 大的元素名类似"table name" 中间的值类似数据库中的值
xml 只是文本, 扩展名.xml ( 纯文本文件 )
xhtml 是遵守xml的叫严格语法的 html
xml 与 Ajax 的联系, "Asynchronous JavaScript And XML" Javascript 并未限制大家在实行Ajax请求与相应时只能使用XML作为数据格式,
但这样做确实容易应付一切但也是最琐碎的数据.

Ajax 流程
Ajax 的请求与响应 为中心概念.
1. 浏览器 发出Ajax 请求服务器, 请求的事物是存储博客数据的XML文件

2. 服务器收到情况, 开始工作, 创建响应 
3. 创建浏览器响应, 把文件打包, blog.xml
4. 浏览器解开响应中打包的XML数据, 并小心吧数据整合到网页中
JavaScript 内置一个称为 XMLHttpRequest的对象, 用于发起 Ajax请求并处理 Ajax响应

image

Ajax 使用两类请求, Get 与 Post, 与送出 HTML 表单相同.
Get 请求 不会改变服务器上任何事物的数据获取方式, 如果需要, 还能透过URL 传入小量数据给服务器, GET 非常适合从服务器获取数据.
request.open("GET", "blog.xml", true)
request.send(null);  // 因为get 方式不需要传送数据到服务器
Post 请求 传送数据给服务器, 可能改变服务器的状态(例如修改数据库中的数据)
request.open("POST", "aasdf.php", true);    // 这个true 是标识支持异步处理
request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
request.send("09/26/2008&Thess dream &cubeapart.png");
自定义 Ajax 对象
var ajaxReg = new AjaxRequest();
send(type, url, handler, postDataType, postData)
type: GET 或 POST
url : 服务器的 url
postDataType: 被传送的数据类型
handler: 用于处理响应的回调函数
postData: 被传送的数据 (只用于 POST, GET 不需要)
异步 Ajax 请求被处理时, 网页不需冻结行动以等待服务器处理请求

客户端脚本使用自定义的回调函数处理Ajax请求的响应.

DOM 可以把 XML当成节点树而处理.

- sample code

   1:  function validateNonEmpty(inputField, helpText) {
   2:      if (inputField.value.length == 0) {
   3:          if (helpText != null) {
   4:              helpText.innerHTML = "Please enter a value.";
   5:          }
   6:          return false;
   7:      } else {
   8:          if (helpText != null) {
   9:              helpText.innerHTML = "";
  10:          }
  11:          return true;
  12:      }
  13:      
  14:  }
  15:   
  16:  function validateRegEX(regex, inputStr, helpText, helpMessage) {
  17:      if (!regex.test(inputStr)) {
  18:          if (helpText != null) 
  19:              helpText.innerHTML = helpMessage;
  20:          return false;
  21:      } else {
  22:          if (helpText != null) {
  23:              helpText.innerHTML = "";
  24:          }
  25:          return true;
  26:      }
  27:      
  28:  }
原文地址:https://www.cnblogs.com/moveofgod/p/3374333.html