筆記來自慕課網(wǎng)的js和《JavaScript DOM編程藝術(shù)》一書以及《JavaScript權(quán)威指南》一書的學(xué)習(xí)逃贝。
js基本概念
- 給網(wǎng)頁增加交互性的腳本語言
- 簡單易學(xué)易用
- 常用來給HTML網(wǎng)頁添加動態(tài)功能伶唯,比如響應(yīng)用戶的各種操作
- 可以彌補HTML語言的缺陷舌涨,實現(xiàn)web頁面客戶端的動態(tài)效果
- 動態(tài)的改變網(wǎng)頁內(nèi)容
- 動態(tài)改變網(wǎng)頁的外觀
- 驗證表單數(shù)據(jù)
- 響應(yīng)事件
幾乎所有瀏覽器都支持JavaScript
JavaScript的特點之一:腳本語言JavaScript只需要經(jīng)過編寫淹冰、運行這兩個步驟亦歉,不需要編譯脯燃、鏈接嵌牺。
js代碼的位置
- <script src="script.js">js代碼</script>放在<head></head>標(biāo)簽中帮辟;
- <script src="script.js">js代碼</script>放在body中速址;
- 將js代碼寫在一個單獨的js文件中,在<head>中引用:
tip:在JS文件中由驹,不需要<script>標(biāo)簽,直接編寫JavaScript代碼就可以了芍锚。
eg:
<head>
<script src="script.js"></script>
</head>
最好的做法是把<script>標(biāo)簽放到HTML文檔的最后昔园,</body>標(biāo)簽之前。
js注釋
- 單行注釋并炮,在注釋內(nèi)容前加符號 “//”默刚。
- 多行注釋以"/"開始,以"/"結(jié)束逃魄。
js變量
- 從編程角度講荤西,變量是用于存儲某種/某些數(shù)值的存儲器。
- 定義變量使用關(guān)鍵字var,語法如下:
var 變量名
變量名可以任意取名伍俘,但要遵循命名規(guī)則:
1.變量必須使用字母邪锌、下劃線()或者美元符($)開始。
2.然后可以使用任意多個英文字母癌瘾、數(shù)字寡痰、下劃線()或者美元符($)組成膝藕。
3.不能使用JavaScript關(guān)鍵詞與JavaScript保留字并巍。
tip:
變量最好先聲明再賦值(JavaScript是一種弱類型的語言锭魔,變量可以不用先聲明,但是最好先聲明咬荷,比較規(guī)范)嚣伐,如下:
var mychar;
mychar="javascript";
如果未在var聲明語句中給變量指定初始值,那么雖然聲明了這個變量萍丐,但在給它存入一個值之前轩端,它的初始值就是undefined。
- 變量的作用域
- 全局變量擁有全局作用域逝变,在js代碼中的任何地方都是有定義的基茵。
- 函數(shù)內(nèi)聲明的變量是局部變量,只在函數(shù)體內(nèi)有定義壳影。
- 函數(shù)參數(shù)也是局部變量拱层,它們只在函數(shù)體內(nèi)有定義。
- 在函數(shù)體內(nèi)宴咧,局部變量的優(yōu)先級高于同名的全局變量根灯。
eg:
var scope = "global";//聲明一個全局變量
function checkscope(){
var scope = "local";//聲明一個同名的局部變量
return scope; //返回局部變量的值,而不是全局變量的值
}
checkscope(); //結(jié)果為“l(fā)ocal”
eg:
scope = "global";//聲明一個全局變量掺栅,甚至不用var聲明
function checkscopes2() {
scope = "local"; //這種做法將修改全局變量的值
return scope;
}
checkscopes2();//結(jié)果為“l(fā)ocal”
eg:
var scope = "global scope";
function checkscope() {
var scope = "local scope";
function nested() {
var scope = "nested scope";
return scope;
}
return nested();
}
checkscope();//結(jié)果是什么呢烙肺? "nested scope"
- 函數(shù)作用域和聲明提前
塊級作用域:類似C語言的編程中,變量在聲明它的這段花括號內(nèi)是可見的氧卧,花括號外是不可見的桃笙。
函數(shù)作用域:js使用函數(shù)作用域,變量在聲明它們的函數(shù)體以及這個函數(shù)體嵌套的任意函數(shù)體內(nèi)都是有定義的沙绝。
eg:
function test(o) {
var i = 0;//i在整個函數(shù)體內(nèi)均是有定義的
if (typeof o == "object") {
var j = 0;//j在函數(shù)體內(nèi)是有定義的搏明,不僅僅是if這個代碼段內(nèi)
for (var k=0; k < 10; k++) {//k在函數(shù)體內(nèi)是有定義的鼠锈,不僅僅是在循環(huán)內(nèi)
console.log(k);//輸出數(shù)字0-9
}
console.log(k);//k已經(jīng)定義了,輸出10
}
console.log(j);//j已經(jīng)定義了星著,但可能沒有初始化
}
test("haha");//例如购笆,“haha”是一個字符串,不是對象虚循,所以IF判斷為假同欠,不進行if里面的代碼,但是雖然j是在if內(nèi)聲明的邮丰,但它在整一個test函數(shù)內(nèi)都是可見的行您,即j已經(jīng)聲明铭乾,僅僅未賦值剪廉,所以輸出undefined。
eg2:
var testObject = {
x:2,y:3
}
function test(o) {
var i = 0;
if (typeof o == "object") {
var j = 0;
for (var k=0; k < 10; k++) {
console.log(k);
}
console.log(k);
}
console.log(j);
}
test(testObject);//此處testObject是一個對象炕檩,滿足if的判斷條件斗蒋,執(zhí)行if花括號內(nèi)的語句,j則在if花括號內(nèi)賦值為0笛质,因此j輸出的值為0
js的函數(shù)作用域是指在函數(shù)內(nèi)聲明的所有變量在函數(shù)體內(nèi)始終可見的泉沾,這意味著變量在聲明之前甚至已經(jīng)可用。js的這個特性被非正式地稱為聲明提前妇押,即js函數(shù)里聲明的所有變量跷究,都被提前至函數(shù)體的頂部,是在js引擎的“預(yù)編譯”時進行的敲霍,是在代碼開始運行之前俊马。
eg:
var scope = "global";
function f() {
console.log(scope);//輸出“undefined”,而不是“global”
var scope = "local";//變量在這里賦初始值肩杈,但變量本身在函數(shù)體內(nèi)任何地方均是有定義的
console.log(scope);//輸出“l(fā)ocal”
}
f();
解析:
第一句聲明了一個全局變量柴我,然后調(diào)用函數(shù)f(),函數(shù)f()中的第一句console.log(scope)扩然,輸出的不是全局變量的scope(“global”)艘儒,因為f函數(shù)中的第二句聲明了局部變量的 scope,雖然這句聲明在第二行夫偶,但是聲明會提前到函數(shù)的開始界睁,所以f函數(shù)中第一句的scope是局部變量的scope,而不是f函數(shù)外的scope兵拢,所以輸出的是undefined晕窑,因為雖然聲明提前了,但是賦值還是在后面卵佛,所以第二個console.log(scope)輸出的是“l(fā)ocal”
即杨赤,以上的代碼可以等效為:
var scope = "global";
function f() {
var scope;
console.log(scope);
scope = "local";
console.log(scope);
}
f();
即<strong>函數(shù)體內(nèi)的變量聲明提前敞斋,而賦值不會提前,賦值在賦值語句所在位置才進行疾牲。</strong>
數(shù)據(jù)類型
字符串
- 如果字符串包含雙引號植捎,就把整個字符串放在單引號里;
- 如果字符串包含單引號阳柔,就把整個字符串放在雙引號里焰枢;
- 轉(zhuǎn)義字符:用反斜杠
eg:var mood ='don't ask';
數(shù)值
JavaScript允許使用帶小數(shù)點的數(shù)值,并且允許任意位小數(shù)舌剂。
eg: var age =20;
var temperature = -20.33333;
布爾值
布爾數(shù)據(jù)只有兩個可選值:true或false济锄。
eg:var sleeping =true;(注意true不用加雙引號)
數(shù)組
創(chuàng)建數(shù)組
聲明:
var team = Array(4); //聲明的同時說明數(shù)組的長度
var team = Array(); //只聲明數(shù)組;數(shù)組元素賦值:
team[0]="Jane";
team[1]="John";
team[2]="Linda";
team[3]="Alin";聲明同時賦值:
var team=Array("Jane","John","Linda","Alin");
或者
var team=["Jane","John","Linda","Alin"];數(shù)組中的元素可以是不同類型霍转,也可以包含其他數(shù)組:
eg:
var lennon=["Jane",1995,false];
var lennon=["Jane",1995,false];
var team=[];
team[0]=lennon;
對象
- js的基本數(shù)據(jù)類型之一
- 是一種復(fù)合值荐绝,將很多值聚合在一起,也可看做是屬性(名/值對)的無序集合避消。
- 創(chuàng)建對象:
- 名/值對中間用冒號分隔低滩;
- 名/值對之間用逗號分隔;
- 屬性名可以是js標(biāo)識符也可以是字符串直接量岩喷;
- 保留字作為屬性名要用引號括起來恕沫;
- 屬性的值可以是任意類型的表達式;
- 全部名/值對用一個花括號括起來纱意。
eg:
var empty = {};//沒有任何屬性的對象
var point = { x:0, y:0 };//兩個屬性婶溯,一個屬性名是x,屬性值是0偷霉;另一個屬性名是y迄委,屬性值是0.
var point2 = { x:point.x, y:point.y+1 };//更復(fù)雜的值
var book = {
"main title": "javascript",//屬性名里有空格,必須用字符串表示
'sub-title': "the definitive guide",//屬性名里有連字符腾它,必須用字符串表示
"for": "all audiences",//"for"是保留字跑筝,因此必須用引號
author: { //這個屬性的值時一個對象
firstname: "david",//注意:這里的屬性名都沒有引號
surname: "flanagan"
}
};
eg:通過new創(chuàng)建對象
var o = new Object();
var a = new Array();
var d = new Date();
var r = new RegExp("js");
- 原型對象
- 通過js代碼Object.prototype獲得對原型對象的引用
- 通過new關(guān)鍵字和構(gòu)造函數(shù)調(diào)用創(chuàng)建的對象的原型就是構(gòu)造函數(shù)的prototype屬性的值
eg:
//定義一個構(gòu)造函數(shù)以初始化一個新的Point對象
function Point(x,y) {//構(gòu)造函數(shù)均以大寫字母開始
this.x = x;
this.y = y;
}
var p = new Point(1,1);//使用new關(guān)鍵字和構(gòu)造函數(shù)來創(chuàng)建一個實例
var p2 = new Point(2,2);
Point.prototype.r = function() {//Point.prototype是Point對象的原型對象,每一個實例化的Point對象都繼承這個原型對象的方法瞒滴,因此才此處寫原型對象的某個方法后曲梗,每一個實例化的Point對象都繼承了這個方法并且可以調(diào)用
return Math.sqrt(this.x*this.x+this.y*this.y);
}
p.r();
p2.r();
- new Object()創(chuàng)建的對象繼承自O(shè)bject.prototype
- new Array() 創(chuàng)建的對象的原型是Array.prototype
- new Date()創(chuàng)建的對象的原型就是Date.prototype
- Object.create()創(chuàng)建一個新對象,第一個參數(shù)是這個對象的原型妓忍,第二個參數(shù)可選虏两,用以對對象的屬性進行進一步描述。這是一個靜態(tài)函數(shù)世剖,不是用來調(diào)用的定罢。使用方法:傳入所需的原型對象,則創(chuàng)建的 新對象繼承了傳進去的這個原型對象的屬性旁瘫。
eg:
var o1 = Object.create({x:1,y:2});//o1繼承了屬性x和y
var o2 = Object.create(Object.prototype);//創(chuàng)建了一個普通的空對象祖凫,和{}和new Object()一樣
任意對象都可以被繼承琼蚯,即可以將任意一個對象當(dāng)成原型,然后用這個原型創(chuàng)建一個新對象惠况,則這個新對象繼承了那個原型的屬性遭庶。
eg:
function inherit(p) {//這整一個inherit函數(shù)返回了一個新的對象,它的原型對象是傳入的參數(shù)p稠屠,繼承了p的屬性
if (p == null) throw TypeError();//p可以是一個對象但不可以是null
if (Object.create)//判斷是否存在Object.create()
return Object.create(p);//存在峦睡,直接使用Object.create();
var t = typeof p;//否則進一步檢測p的類型
if(t !== "object" && t !== "function") throw TypeError();//不是對象或者函數(shù)就不行
function f() {};//定義一個空的構(gòu)造函數(shù)权埠;
f.prototype = p;//設(shè)置其原型對象為p
return new f();//使用f()創(chuàng)建p的繼承對象
}
var o3 = inherit({x:1,y:2});//o3是一個實例化的對象榨了,它的原型對象是{x:1,y:2},繼承了它的屬性
- 獲得屬性值和設(shè)置屬性值
- 獲得屬性:用xxx.yyy或者xxx["yyy"];
- 屬性訪問錯誤:如果這個屬性不存在攘蔽,則返回“undefined”龙屉;
eg:
var book = {
"main title": "javascript",
'sub-title': "the definitive guide",
author: {
firstname: "david",
surname: "flanagan"
}
};
var title = book["main title"];//得到book的“main title”屬性
var subtitle = book.subtitle;//=>undefined,屬性不存在
var author = book.author;//得到book的”author“屬性,是一個對象
var name = book.author.surname;//得到book的”author“屬性的surname屬性秩彤,也可以var name = author.surname;叔扼,因為前面已經(jīng)把 book.author賦給author這個變量了
var len = book.subtitle.length;//book.subtitle是undefined,沒有l(wèi)ength事哭,所以拋出一個類型錯誤異常
//避免獲取屬性時出錯的方法:
//一種冗余的但很易懂的方法:
var len = undefined;
if (book) {
if (book.subtitle) len = book.subtitle.length;
}
//一種簡練的方法
var len = book && book.subtitle && book.subtitle.length;//由三個&&運算符連接起來的表達式漫雷,
//從左起,第一個若不是真值鳍咱,則不用繼續(xù)看后面降盹,表達式返回第一個操作數(shù)的值;如果第一個真谤辜,
//則繼續(xù)看第二個蓄坏,若第二個不是真值,就返回第二個操作數(shù)的值丑念;如果第二個也為真涡戳,
//則繼續(xù)看第三個,如果第三個為假脯倚,則返回第三個的值渔彰,如果第三個為真,則返回第三個的值推正;
//此處恍涂,第一個操作數(shù)book為真值,是一個對象植榕,所以繼續(xù)看第二個操作數(shù)再沧,
//第二個由于book不存在subtitle屬性,所以第二個操作數(shù)是undefined尊残,為假值炒瘸,
//所以不用繼續(xù)看第三個的值淤堵,表達式的值為第二個操作數(shù)的值,即undefined顷扩。
補充:即使上例存在subtitle屬性粘勒,上面那個表達式最后返回的值即len的值也是undefined,因為object對象不存在length屬性屎即。要獲得object對象中的length庙睡,可用如下方法:
eg:
var a = {a:1,b:2,c:3,d:4};
Object.prototype.length = function() {
var count = 0;
for(var i in this){
count ++;
}
return count;
};
alert(a.length()); //5,不是4,因為每個對象都有一個內(nèi)部屬性(__proto__指向原型)技俐。
tip:xxx.yyy,點運算符后面的yyy不能是保留字或關(guān)鍵字乘陪,比如不能是xxx.for或xxx.class,如果屬性名是保留字雕擂,必須用方括號的形式訪問啡邑,比如xxx["for"],xxx["class"]
- 設(shè)置屬性
eg:
book.edition = 6;//給book創(chuàng)建一個名為“edition”的屬性
book["main title"] = "ECMAScript";//給“main title”屬性重新賦值
- 繼承
假設(shè)要查詢對象o的屬性x,如果o中不存在x,那么將會繼續(xù)在o的原型對象中查詢屬性x.如果原型對象中也沒有x,但這個原型對象也有原型井赌,那么繼續(xù)在這個原型對象的原型上執(zhí)行查詢谤逼,直到找到x或者查找到一個原型是null的對象為止。
eg:
function inherit(p) {
if (p == null) throw TypeError();
if (Object.create)
return Object.create(p);
var t = typeof p;
if(t !== "object" && t !== "function") throw TypeError();
function f() {};
f.prototype = p;
return new f();
}
var o = {};//o從Object.prototype繼承對象的方法
o.x = 1;//給o定義一個屬性x并賦值為1
var p = inherit(o);//p繼承o和Object.prototype
p.y = 2;//給p定義一個屬性y并賦值為2
var q = inherit(p);//q繼承p仇穗、o和Object.prototype
q.z = 3;//給q定義一個屬性z并賦值為3
var s = q.toString();//toString()繼承自O(shè)bject.prototype
console.log(q.x + q.y);//=>3:x和y分別繼承自o和p
q.x = 3;//修改q的屬性x的值為3
console.log(q.x);//=>3,q的屬性x的值已被修改成3
console.log(o.x);//=>1,o的屬性值沒有被修改
console.log(p.x);//=>1,q的屬性值也沒有被修改
給q的屬性x賦值流部,只會改變q的屬性值,而它的原型對象的屬性值不會被修改纹坐,即“繼承”只關(guān)乎讀取屬性值而不關(guān)乎設(shè)置屬性值枝冀。
- 檢測屬性
- in運算符
eg;
var o = { x:1 };
console.log("x" in o);//true,x是o的屬性
console.log("y" in o);//false:y不是o的屬性
console.log("toString" in o);//true:o繼承toString屬性
- hasOwnProperty()方法:檢測給定的名字是否是對象的自有屬性,對于繼承屬性耘子,返回false
eg:
var o = { x:1 };
console.log(o.hasOwnProperty("x"));//true:o有一個自有屬性x
console.log(o.hasOwnProperty("y"));//false:o中不存在屬性y
console.log(o.hasOwnProperty("toString"));//false:toString是繼承屬性
- propertyIsEnumerable():檢測對象的可枚舉的自有屬性
eg:
function inherit(p) {
if (p == null) throw TypeError();
if (Object.create)
return Object.create(p);
var t = typeof p;
if(t !== "object" && t !== "function") throw TypeError();
function f() {};
f.prototype = p;
return new f();
}
var o = inherit({ y:2 });
o.x = 1;
console.log(o.propertyIsEnumerable("x"));//true果漾,o有一個可枚舉的自有屬性x
console.log(o.propertyIsEnumerable("y"));//false:y是繼承來的
console.log(Object.prototype.propertyIsEnumerable("toString"));//false,不可枚舉
- 用!==直接判斷是否是undefined
eg:
var o = { x:1 };
console.log(o.x !== undefined);//true,o中有屬性x
console.log(o.y !== undefined);//false,o中沒有屬性y
console.log(o.toString !== undefined);//true,o繼承了toString屬性
- tip:in可以區(qū)分不存在的屬性和存在但值為undefined的屬性
eg:
var o = { x:undefined };//屬性值被顯式賦值為undefined
console.log(o.x !== undefined);//false谷誓,屬性存在绒障,但值為undefined
console.log(o.y !== undefined);//false,屬性不存在
console.log("x" in o);//true捍歪,屬性存在
console.log("y" in o);//false户辱,屬性不存在
delete o.x;//刪除了屬性x
console.log("x" in o);//false,屬性不再存在
操作
算術(shù)操作符
- “+”號:
連接字符串:
eg:var message = "I am feeling"+"happy";
eg: alert("10"+20); //返回1020字符串费封,字符串和數(shù)值拼接是更長的字符串焕妙;
加法: alert(10+20); //返回數(shù)值30; - “++”自增:eg:year++; //等效:year=year+1;
函數(shù)
- 定義一個函數(shù):
function 函數(shù)名(參數(shù)) {
函數(shù)體弓摘;
}
eg:
function add(a,b){
var sum=a+b;
return sum;
}
var result=add(2,5); //result的值為7焚鹊;
認識DOM
文檔對象模型DOM定義訪問和處理HTML文檔的標(biāo)準(zhǔn)方法。DOM將文檔呈現(xiàn)為帶有元素、屬性和文本的樹結(jié)構(gòu)(節(jié)點樹)末患。
節(jié)點
- 元素節(jié)點 eg:< body>研叫、< p>、< ul>
- 文本節(jié)點 eg: < p>xxx< /p> ;包含文本節(jié)點“xxx"璧针;
- 屬性節(jié)點eg: < p title="i am a title">xxx< /p> 中 title="i am a title"是一個屬性節(jié)點嚷炉。
獲取元素
getElementById
eg:var a=document.getElementById("purchase"); //a為一個對象(object),對應(yīng)著ID值為purchase的元素探橱。getElementsByTagName:返回一個對象數(shù)組申屹,每個對象分別對應(yīng)著文檔里有著給定標(biāo)簽 的一個元素。
eg:
HTML代碼:
< ul>
< li>abc< /li>
< li>def< /li>
< li>ghi< /li>
< /ul>
js代碼:var a=document.getElementsByTagName("li");
//js代碼:返回一個數(shù)組隧膏,每個對象分別對應(yīng)著document對象中的一個列表項元素哗讥,即a是一個數(shù)組,數(shù)組中的每個對象是一個li元素胞枕;
//alert(a.length);可以獲得列表項元素的個數(shù)“3”杆煞;
//可以通過for循環(huán)遍歷數(shù)組中的每個對象:
for(var i=0;i<a.length;i++){
alert(typeof a[i]);//typeof可以告訴我們獲得的類型(object);
}getElementsByClassName(html5 DOM中新增的方法):返回一個對象數(shù)組腐泻,每個對象分別對應(yīng)著文檔里有著給定類 的一個元素决乎。
eg:var b=document.getElementsByClassName("red select");//b對應(yīng)文檔中同時擁有“red”和“select”類的元素。(如果多個元素都同時擁有這兩個類派桩,則b為一個數(shù)組仍然可以通過b.length獲得數(shù)組長度和通過for循環(huán)遍歷數(shù)組中的對象)summary:
一份文檔就是一棵節(jié)點樹构诚;
節(jié)點分為不同的類型:元素節(jié)點、屬性節(jié)點窄坦、文本節(jié)點唤反;
getElementById將返回一個對象凳寺,該對象對應(yīng)著文檔里的一個特定的元素節(jié)點鸭津;
getElementsByTagName和getElementsByClassName將返回一個對象數(shù)組,它們分別對應(yīng)著文檔里的一組特定的元素節(jié)點肠缨;
每個節(jié)點都是一個對象逆趋。
獲取和設(shè)置屬性
getAttribute:xxx.getAttribute(屬性名);
eg:
var c = document.getElementsByTagName("p");
for (var i=0;i<c.length;i++){
alert(c[i].getAttribute("title"));//彈出文檔中每一個標(biāo)簽為p的元素的title屬性的值,如果沒有這個屬性晒奕,則會返回null
}setAttribute:xxx.setAttribute(屬性名闻书,我們要設(shè)置的屬性值);
eg:var d=document.getElementById("choose");
d.setAttribute("title","choose something");//為ID值為choose的元素設(shè)置title屬性的屬性值為“choose something”
(tip:如果為已經(jīng)擁有指定屬性的屬性設(shè)置屬性值則會改變原有的屬性值。例如原來的title屬性值為“哈哈”脑慧,后來設(shè)置為“choose something”魄眉,則title的屬性值為“choose something”。)
tip:通過setAttribute對文檔做出修改后闷袒,在通過瀏覽器查看源代碼時看到的仍然是修改前的屬性坑律,也就是說setAttribute做出的修改不會反映在文檔本身的源代碼里。這種“表里不一”的現(xiàn)象源自DOM的工作模式:先加載文檔的靜態(tài)內(nèi)容囊骤,再動態(tài)刷新晃择,動態(tài)刷新不影響文檔的靜態(tài)內(nèi)容冀值。這正是DOM的真正威力:對頁面內(nèi)容進行刷新卻不需要在瀏覽器里刷新頁面。
事件處理函數(shù)
- <a href="xxx" onclick="show();return false;">click me</a>
原本點擊這個鏈接是會跳轉(zhuǎn)到相關(guān)鏈接去的宫屠,但是在onclick設(shè)置了return false列疗,則鏈接的默認行為不會被觸發(fā),僅執(zhí)行onclcik中的函數(shù)浪蹂。(通過return false禁用默認行為)抵栈。
childNodes屬性
xxx.childNodes; //獲得xxx的全體子元素(數(shù)組)
tip:返回的數(shù)組包含所有類型的節(jié)點,不僅僅是元素節(jié)點坤次,甚至連空格和換行都會被解釋為節(jié)點竭讳。
nodeType屬性
- 元素節(jié)點的nodeType屬性值為1;
- 屬性節(jié)點的nodeType屬性值為2浙踢;
- 文本節(jié)點的nodeType屬性值為3.
nodeValue屬性:改變文本節(jié)點的值
eg:< p id="description">xxx< /p>
var description=document.getElementById("description");
如果直接:alert(description.nodeValue);將返回null绢慢,因為description是< p>,而< p>中的文本是< p>的第一個子節(jié)點,所以要獲得< p>中的文本洛波,則應(yīng)為:alert(decription.childNodes[0].nodeValue);
firstChild和lastChild屬性
xxx.firstChild等價于xxx.childNodes[0],第一個子節(jié)點胰舆;
xxx.lastChild等價于xxx.childNodes[xxx.childNodes.length-1],最后一個子節(jié)點蹬挤。
分離JavaScript
例如為一個鏈接添加點擊事件:
法一:<a onclick="popUp(this.getAttribute('href'));return false;">example</a>
當(dāng)點擊此鏈接文本時缚窿,將調(diào)用popUp函數(shù),并且由于return false焰扳,a標(biāo)簽的默認行為(打開一個鏈接)將被禁用倦零。
如果要將js代碼與HTML文檔分離:
法二:<a class="popup">example</a>
步驟:
- 把文檔里的鏈接全放入一個數(shù)組里;
- 遍歷數(shù)組吨悍;
- 如果某個鏈接的class屬性等于popUp扫茅,就表示這個鏈接在被點擊時應(yīng)該調(diào)用popUp()函數(shù)。
window.onload=prepareLinks;
function prepareLinks(){
var links=document.getElementsByTagName("a");
for(var i=0;i<links.length;i++){
if(links[i].getAttribute("class")=="popup"){
links[i].onclick=function(){
popUp(this.getAttribute("href"));
return false;
}
}
}
}
向后兼容
對于不支持DOM的一些瀏覽器應(yīng)有相應(yīng)的處理育瓜,比如一些不支持DOM的瀏覽器就沒有g(shù)etElementById這些方法葫隙,因此先進行對象檢測。
對象檢測
eg:
function myFunction(){
if(document.getElementById){//檢測瀏覽器是否支持這個方法
xxxx;//如果支持該方法躏仇,則執(zhí)行這段語句恋脚,如果不支持,則永遠不會執(zhí)行
}
}
改進:
window.onload=function(){
if(!document.getElementsByTagName||document.getElementById)return false;//使用邏輯非和邏輯或焰手,可以檢測多種方法糟描;如果不支持,則跳出整個函數(shù)书妻,如果支持船响,繼續(xù)往下執(zhí)行。
xxxx;
}
性能考慮
- 盡量減少訪問DOM和盡量減少標(biāo)記
eg:
if(document.getElementById("haha").length>0){
for(var i=0;i<document.getElementById("haha").length;i++){
xxx;
}
}
這樣子的代碼重復(fù)訪問了DOM樹,降低了性能灿意。
改進:
var links=document.getElementById("haha");
if(links.length>0){
for(var i=0;i<links.length;i++){
xxx;
}
}
這樣僅一次搜索DOM樹即可實現(xiàn)相同的功能估灿。
- 合并和放置腳本
eg:
<script src="script/functionA.js></script>
<script src="script/functionB.js></script>
<script src="script/functionC.js></script>
<script src="script/functionD.js></script>
應(yīng)合并成一個js文件,這樣可以減少加載頁面發(fā)送的請求數(shù)量缤剧,提高性能馅袁。
而且建議把<script>標(biāo)簽放在文檔的末尾,</body>的前面荒辕,可以讓頁面變得更快汗销。
- 壓縮腳本:把腳本文件中不必要的字節(jié),如空格和注釋都刪除抵窒。
精簡后的代碼失去了可讀性弛针,解決方法:把壓縮前的腳本文件保存為副本,把壓縮后的腳本文件命名為xxx.min.js文件放在站點上李皇。
動態(tài)創(chuàng)建標(biāo)記
document.write
eg:document.write("< p>This is inserted.< /p>");//插入一段文本
tip:使用document.write 不能很好地將行為與表現(xiàn)分開削茁,因此應(yīng)避免使用這個方法。
innerHTML
讀:eg:
< div id="testdiv">
< p>this id < em>my< /em>content.< /p>
< /div>
js:alert(document.getElementById("testdiv").innerHTML);
結(jié)果:< p>this id < em>my< /em>content.< /p>寫:eg:
< div id="testdiv">< /div>
js:var testdiv=document.getElementById("testdiv");
testdiv.innerHTML="< p>this id < em>my< /em>content.< /p>";
DOM方法
- createElement方法和appendChild方法
document.createElement方法創(chuàng)建一個新的元素節(jié)點掉房,但是創(chuàng)建后的節(jié)點仍然是游離的茧跋,要把它添加到DOM節(jié)點樹種。
eg:
< div id="testdiv">< /div>
var para=document.createElement("p");<!--創(chuàng)建了一個<p>元素節(jié)點-->
var testdiv=document.getElementById("testdiv");
testdiv.appendChild(para);<!--把創(chuàng)建的節(jié)點添加為div的子節(jié)點-->
- createTextNode方法
eg:
< div id="testdiv">< /div>
var para=document.createElement("p");<!--創(chuàng)建了一個<p>元素節(jié)點-->
var testdiv=document.getElementById("testdiv");
var txt =document.createTextNode("hello");<!--創(chuàng)建文本節(jié)點-->
testdiv.appendChild(para);<!--把創(chuàng)建的節(jié)點添加為div的子節(jié)點-->
para.appendChid(txt);<!--將文本節(jié)點添加為p元素的子節(jié)點-->
- insertBefore()方法
parentElement.insertBefore(newElement,targetElement);
新元素(newElement):你想插入的新元素
目標(biāo)元素(targetElement):你想把新元素插入到哪個元素之前卓囚;
父元素(parentElement):目標(biāo)元素的父元素瘾杭。
eg:(要把一張圖片插入到ul前面)
<body>
<ul id="gallery">
<li>xxx</li>
<li>xxx</li>
</ul>
</body>
js:
var gallery=document.getElementById("gallery");
gallery.parentNode.insertBefore(placeolder,gallery);//假設(shè)placeolder是新生成的一個圖片的元素節(jié)點,則這句代碼實現(xiàn)將placeolder插入到gallery之前
- insertAfter方法哪亿?
沒有粥烁。
但是可以編寫一個:
function insertAfter(newElement,targetElement){
var parent=targetElement.parentNode;//目標(biāo)元素的父元素
if(parent.lastChild==targetElement){如果目標(biāo)元素是最后一個元素,要把新元素插入蝇棉,只要為父元素append一個子節(jié)點讨阻,自然就是在目標(biāo)元素的后面了;
parent.appendChild(newElement);
}else{//如果目標(biāo)元素不是最后一個元素银萍,那么就把新元素插在目標(biāo)元素和目標(biāo)元素后面一個元素的之間变勇,所以就是用insertBefore,插在targetElement.nextSibling之前贴唇;
parent.insertBefore(newElement,targetElement.nextSibling);
}
}
className屬性
可讀可寫;
xxx.className=aClass; //aClass是一個類名飞袋。
tip: 這樣寫是替換某個元素的class屬性戳气,原來有的class屬性將被覆蓋,如果原來沒有class屬性巧鸭,則為添加class屬性瓶您。
如果只是想要增加一個class而不替換原來的class,就要:
xxx.className+=" info"; //注意:info是一個要新增加的類,前面要有一個空格呀袱,表示將原來的類名和新的類名用空格連接起來贸毕,所以就不會把原來的類替換掉。
可以先判斷原來是否已經(jīng)有類夜赵,即檢查className屬性的值是否為null明棍;
如果是,即原來沒有類寇僧,就把新的class設(shè)置值直接賦值給className屬性摊腋;
如果不是,即原來已經(jīng)存在類嘁傀,就把一個空格和新的class設(shè)置值追加到className屬性上去兴蒸。
封裝成一個函數(shù):
function addClass(element,value){//element是需要添加類的元素,value是要添加的類名
if(!element.className){//如果element的className值為null细办,即原來沒有類
element.className=value;//直接把新的類名賦值給className橙凳;
}
else{如果element的className值不為null,即原來有類
newClassName=element.className+" value";//將新舊類連接笑撞;
element.className=newClassName;
}
}
用js實現(xiàn)動畫效果
原理:讓元素的某個屬性值隨時間的變化而變化痕惋。
setTimeout
xxx=setTimeout("function",interval);//function是要執(zhí)行的函數(shù),interval是以毫秒為單位設(shè)定了需要經(jīng)過多長時間后才開始執(zhí)行函數(shù)
eg:movement=setTimeout(“moveMessage()”娃殖,5000)值戳;//5秒之后執(zhí)行moveMessage函數(shù)
- clearTimeout(xxx)//取消要執(zhí)行的函數(shù),xxx為setTimeout函數(shù)調(diào)用返回值的變量eg:clearTimeout(movement)炉爆;
parseInt函數(shù)
可以把字符串里的數(shù)值信息提取出來堕虹。
parseInt("39 steps"); //返回數(shù)值39
由elem.style.left得到的值比如為50px,是字符串芬首,就可以通過parseInt函數(shù)來獲得數(shù)值進行計算赴捞。
待續(xù)。郁稍。赦政。