javascript
【前端】JavaScript
一、JavaScript概述
1.JavaScript的歷史
-
1992年Nombas開發出C-minus-minus(C--)的嵌入式腳本語言(最初綁定在CEnvi軟件中).后將其改名ScriptEase.(客戶端執行的語言)
-
Netscape(網景)接收Nombas的理念,(Brendan Eich)在其Netscape Navigator 2.0產品中開發出一套livescript的腳本語言.Sun和Netscape共同完成.后改名叫Javascript
-
微軟隨后模仿在其IE3.0的產品中搭載了一個JavaScript的克隆版叫Jscript.
-
為了統一三家,ECMA(歐洲計算機制造協會)定義了ECMA-262規范.國際標準化組織及國際電工委員會(ISO/IEC)也采納 ECMAScript 作為標準(ISO/IEC-16262)。從此,Web 瀏覽器就開始努力(雖然有著不同的程度的成功和失敗)將 ECMAScript 作為 JavaScript 實現的基礎。EcmaScript是規范.
2.ECMAScript
盡管 ECMAScript 是一個重要的標準,但它并不是 JavaScript 唯一的部分,當然,也不是唯一被標準化的部分。實際上,一個完整的 JavaScript 實現是由以下 3 個不同部分組成的:
- 核心(ECMAScript)?
- 文檔對象模型(DOM) Document object model (整合js,css,html)
- 瀏覽器對象模型(BOM) Broswer object model(整合js和瀏覽器)
- Javascript 在開發中絕大多數情況是基于對象的.也是面向對象的.?
? ? ? ? ?
簡單地說,ECMAScript 描述了以下內容:
- 語法?
- 類型?
- 語句?
- 關鍵字?
- 保留字?
- 運算符?
- 對象 (封裝 繼承 多態) 基于對象的語言.使用對象.
二、JavaScript的基礎
1.JS的引入方式
1 直接編寫<script>alert('hello yuan')</script> 2 導入文件<script src="hello.js"></script>2.JS的變量、常量和標識符
2.1:JS的變量
(1)聲明變量時不用聲明變量類型,全都使用var關鍵字;
var a;<br>a=3;(2)一行可以聲明多個變量,并且可以是不同類型
var name="yuan", age=20, job="lecturer";(3)聲明變量時,可以不用var,如果不用var,那么它是全局變量
(4)變量命名,首字符只能是字母,下劃線,$美元符 三選一,余下的字符可以是下劃線、美元符號或任何字母或數字字符且區分大小寫,x與X是兩個變量
Camel 標記法 首字母是小寫的,接下來的字母都以大寫字符開頭。例如: var myTestValue = 0, mySecondValue = "hi"; Pascal 標記法 首字母是大寫的,接下來的字母都以大寫字符開頭。例如: Var MyTestValue = 0, MySecondValue = "hi"; 匈牙利類型標記法 在以 Pascal 標記法命名的變量前附加一個小寫字母(或小寫字母序列),說明該變量的類型。例如,i 表示整數,s 表示字符串,如下所示“ Var iMyTestValue = 0, sMySecondValue = "hi"; 命名規范2.2:常量和標識符
常量:直接在程序中出現的數據值
標識符:
? ? ? ? ?
3.JS的數據類型
? ? ???
number ----- 數值boolean ----- 布爾值string ----- 字符串undefined ----- undefinednull ----- null3.1:數字類型(number)
- 不區分整型數值和浮點型數值;
- 所有數字都采用64位浮點格式存儲,相當于Java和C語言中的double格式
- 能表示的最大值是±1.7976931348623157 x 10308
- 能表示的最小值是±5 x 10 -324
整數:
? ? ? ? ? ?在JavaScript中10進制的整數由數字的序列組成
? ? ? ? ? ?精確表達的范圍是?-9007199254740992 (-253) 到 9007199254740992 (253)
? ? ? ? ? ?超出范圍的整數,精確度將受影響
浮點數:
? ? ? ? ? ?使用小數點記錄數據
? ? ? ? ? ?例如:3.4,5.6
? ? ? ? ? ?使用指數記錄數據
? ? ? ? ? ?例如:4.3e23 = 4.3 x 1023
16進制和8進制數的表達:
? ? ? ? ? ?16進制數據前面加上0x,八進制前面加0;16進制數是由0-9,A-F等16個字符組成;8進制數由0-7等8個數字組成
3.2:字符串類型(string)
是由Unicode字符、數字、標點符號組成的序列;字符串常量首尾由單引號或雙引號括起;JavaScript中沒有字符類型;常用特殊字符在字符串中的表達
字符串中部分特殊字符必須加上右斜杠\;常用的轉義字符:
\n:換行 \':單引號 \":雙引號 \\:右斜杠
3.3:布爾類型(boolean)
Boolean類型僅有兩個值:true和false,也代表1和0,實際運算中true=1,false=0
布爾值也可以看作on/off、yes/no、1/0對應true/false
Boolean值主要用于JavaScript的控制語句,例如:
f (x==1){y=y+1; }else{y=y-1;}3.4:Null & Undefined類型
Undefined類型
Undefined 只有一個值,即undefined。當生命的變量未初始化時,該變量的默認值是undefined。當函數無明確返回值時,返回的也是值“undefined”;
Null類型
另一種只有一個值的類型是Null,它只有一個專用值null,即它的字面量。值undefined實際上是從值null派生來的,因此ECMAScript把他們定義為相等的。
盡管這兩個值相等,但它們的含義不同。undefined是聲明了變量但未對其初始化時賦予該變量的值,null則用于表示尚未存在的對象(在討論typeof運算符時,簡單的介紹過這一點)。如果函數或方法要返回的是對象,name找不到該對象時,返回的通常是null。
4.運算符
算術運算符:+ - * / % ++(自加一) -- 比較運算符:> >= < <= != == === !==邏輯運算符:&& || ! (邏輯與或非)賦值運算符:= += -= *= /=字符串運算符:+ 連接,兩邊操作數有一個或兩個是字符串就做連接運算4.1:算術運算符
(1)自加自減
假如x=2,那么x++表達式執行后的值為3,x--表達式執行后的值為1;i++相當于i=i+1,i--相當于i=i-1;
遞增和遞減運算符可以放在變量前也可以放在變量后:--i
(2)單元運算符
- 除了可以表示減號還可以表示負號 例如:x=-y+ 除了可以表示加法運算還可以用于字符串的連接 例如:"abc"+"def"="abcdef"JS不同于python,是一門弱類型語言
靜態類型語言 一種在編譯期間就確定數據類型的語言。大多數靜態類型語言是通過要求在使用任一變量之前聲明其數據類型來保證這一點的。Java 和 C 是靜態類型語言。 動態類型語言 一種在運行期間才去確定數據類型的語言,與靜態類型相反。VBScript 和 Python 是動態類型的,因為它們確定一個變量的類型是在您第一次給它賦值的時候。 強類型語言 一種總是強制類型定義的語言。Java 和 Python 是強制類型定義的。您有一個整數,如果不明確地進行轉換 ,不能將把它當成一個字符串去應用。 弱類型語言 一種類型可以被忽略的語言,與強類型相反。JS 是弱類型的。在JS中,可以將字符串 '12' 和整數 3 進行連接得到字符串'123',然后可以把它看成整數 123 ,所有這些都不需要任何的顯示轉換。 所以說 Python 既是動態類型語言 (因為它不使用顯示數據類型聲明),又是強類型語言 (因為只要一個變量獲得了一個數據類型,它實際上就一直是這個類型了)。(3)NaN
var d="yuan";d=+d;alert(d);//NaN:屬于Number類型的一個特殊值,當遇到將字符串轉成數字無效時,就會得到一個NaN數據alert(typeof(d));//Number//NaN特點:var n=NaN;alert(n>3);alert(n<3);alert(n==3);alert(n==NaN);alert(n!=NaN);//NaN參與的所有的運算都是false,除了!= var d="yuan";d=+d;alert(d);//NaN:屬于Number類型的一個特殊值,當遇到將字符串轉成數字無效時,就會得到一個NaN數據alert(typeof(d));//Number//NaN特點:var n=NaN;alert(n>3);alert(n<3);alert(n==3);alert(n==NaN);alert(n!=NaN);//NaN參與的所有的運算都是false,除了!=4.2:比較運算符
> >= < <= != == === !==用于控制語句時:
if (2>1){ // 3 0 false null undefined []console.log("條件成立!")}等號和非等號的同類運算符是全等號和非全等號。這兩個運算符所做的與等號和非等號相同,只是它們在檢查相等性前,不執行類型轉換。
console.log(2==2); console.log(2=="2"); #自動執行類型轉換 console.log(2==="2"); #不執行類型轉換 console.log(2!=="2"); #不執行類型轉換注意1:
比較運算符兩側如果一個是數字類型,一個是其他類型,會將其類型轉換成數字類型.
比較運算符兩側如果都是字符串類型,比較的是最高位的asc碼,如果最高位相等,繼續取第二位比較.
注意2:
等性運算符:執行類型轉換的規則如下:如果一個運算數是 Boolean 值,在檢查相等性之前,把它轉換成數字值。false 轉換成 0,true 為 1。 如果一個運算數是字符串,另一個是數字,在檢查相等性之前,要嘗試把字符串轉換成數字。 如果一個運算數是對象,另一個是字符串,在檢查相等性之前,要嘗試把對象轉換成字符串。 如果一個運算數是對象,另一個是數字,在檢查相等性之前,要嘗試把對象轉換成數字。 在比較時,該運算符還遵守下列規則:值 null 和 undefined 相等。 在檢查相等性時,不能把 null 和 undefined 轉換成其他值。 如果某個運算數是 NaN,等號將返回 false,非等號將返回 true。 如果兩個運算數都是對象,那么比較的是它們的引用值。如果兩個運算數指向同一對象,那么等號返回 true,否則兩個運算數不等。5.流程控制
5.1:順序結構
<script>console.log(“星期一”);console.log(“星期二”);console.log(“星期三”);</script>5.2:分支結構
if-else結構:
if (表達式){語句1;......}else{語句2;.....}
如果表達式的值為true則執行語句1,否則執行語句2
if-elif-else結構:
if (表達式1) {語句1; }else if (表達式2){語句2; }
else if (表達式3){語句3; }
else{語句4; }
seitch-case結構
switch比else if結構更加簡潔清晰,使程序可讀性更強,效率更高。
switch基本格式 switch (表達式) {case 值1:語句1;break;case 值2:語句2;break;case 值3:語句3;break;default:語句4; }var week=3;switch (week){case 1:console.log("禮拜一");break;case 2:console.log("禮拜2");break;case 3:console.log("禮拜3");break;case 4:console.log("禮拜4");break;case 5:console.log("禮拜5");break;case 6:console.log("禮拜6");break;case 7:console.log("禮拜7");break;default:console.log("輸入錯誤")} 示例
5.2:循環結構
for循環:條件循環
語法規則:for(初始表達式;條件表達式;自增或自減){執行語句……}功能說明:實現條件循環,當條件成立時,執行語句1,否則跳出循環體
for循環的另一種形式:遍歷循環
for( 變量 in 數組或對象){執行語句……}white循環:
語法規則:while (條件){語句1;... }功能說明:運行功能和for類似,當條件成立循環執行語句花括號{}內的語句,否則跳出循環;同樣支持continue與break語句。
5.3:異常處理
try {//這段代碼從上往下運行,其中任何一個語句拋出異常該代碼塊就結束運行 } catch (e) {// 如果try代碼塊中拋出了異常,catch代碼塊中的代碼就會被執行。//e是一個局部變量,用來指向Error對象或者其他拋出的對象 } finally {//無論try中代碼是否有異常拋出(甚至是try代碼塊中有return語句),finally代碼塊中始終會被執行。 } 注:主動拋出異常 throw Error('xxxx')三、JavaScript的對象
簡介:
在JavaScript中除了null和undefined以外其他的數據類型都被定義成了對象,也可以用創建對象的方法定義變量,String、Math、Array、Date、RegExp都是JavaScript中重要的內置對象,在JavaScript程序大多數功能都是基于對象實現的。
<script language="javascript"> var aa=Number.MAX_VALUE; //利用數字對象獲取可表示最大數 var bb=new String("hello JavaScript"); //創建字符串對象 var cc=new Date(); //創建日期對象 var dd=new Array("星期一","星期二","星期三","星期四"); //數組對象 </script>? ?
3.1:string對象
3.1.1:字符串對象創建
字符串對象創建(兩種方式)
(1)變量=“字符串”
(2)字符串對象名稱=newstring(字符串)
var str1="hello world"; var str1= new String("hello word");3.1.2:字符串對象的屬性和函數
x.length ----獲取字符串的長度x.toLowerCase() ----轉為小寫x.toUpperCase() ----轉為大寫x.trim() ----去除字符串兩邊空格 ----字符串查詢方法x.charAt(index) ----str1.charAt(index);----獲取指定位置字符,其中index為要獲取的字符索引x.indexOf(findstr,index)----查詢字符串位置 x.lastIndexOf(findstr) x.match(regexp) ----match返回匹配字符串的數組,如果沒有匹配則返回null x.search(regexp) ----search返回匹配字符串的首字符位置索引示例:var str1="welcome to the world of JS!";var str2=str1.match("world");var str3=str1.search("world");alert(str2[0]); // 結果為"world"alert(str3); // 結果為15----子字符串處理方法x.substr(start, length) ----start表示開始位置,length表示截取長度 x.substring(start, end) ----end是結束位置x.slice(start, end) ----切片操作字符串示例:var str1="abcdefgh";var str2=str1.slice(2,4);var str3=str1.slice(4);var str4=str1.slice(2,-1);var str5=str1.slice(-3,-1);alert(str2); //結果為"cd"alert(str3); //結果為"efgh"alert(str4); //結果為"cdefg"alert(str5); //結果為"fg"x.replace(findstr,tostr) ---- 字符串替換x.split(); ----分割字符串var str1="一,二,三,四,五,六,日"; var strArray=str1.split(",");alert(strArray[1]);//結果為"二"x.concat(addstr) ---- 拼接字符串? 3.2:Array對象
3.2.1:數組創建
創建數組的三種方式:
創建方式1: var arrname = [元素0,元素1,….]; // var arr=[1,2,3];創建方式2: var arrname = new Array(元素0,元素1,….); // var test=new Array(100,"a",true);創建方式3: var arrname = new Array(長度); // 初始化數組對象:var cnweek=new Array(7);cnweek[0]="星期日";cnweek[1]="星期一";...cnweek[6]="星期六"; var cnweek=new Array(7); for (var i=0;i<=6;i++){cnweek[i]=new Array(2); } cnweek[0][0]="星期日"; cnweek[0][1]="Sunday"; cnweek[1][0]="星期一"; cnweek[1][1]="Monday"; ... cnweek[6][0]="星期六"; cnweek[6][1]="Saturday"; 創建二維數組3.2.2:數組對象的屬性和方法
(1)join方法:將數組元素拼接成字符串
x.join(bystr) ----將數組元素拼接成字符串var arr1=[1, 2, 3, 4, 5, 6, 7];var str1=arr1.join("-");alert(str1); //結果為"1-2-3-4-5-6-7"(2)concat方法:連接兩個字符串
toString方法(原生類方法):將對象轉換成字符串
x.concat(value,...) ---- var a = [1,2,3];var b=a.concat(4,5) ;alert(a.toString()); //返回結果為1,2,3 alert(b.toString()); //返回結果為1,2,3,4,5(3)數組排序-reverse(反轉) sort:
//x.reverse() //x.sort()var arr1=[32, 12, 111, 444]; //var arr1=["a","d","f","c"]; arr1.reverse(); //顛倒數組元素 alert(arr1.toString()); //結果為444,111,12,32 arr1.sort(); //排序數組元素 alert(arr1.toString()); //結果為111,12,32,444,sort排序默認會以最高位的asc碼來排(4)數組切片操作:slice
//x.slice(start, end) // //使用注解 // //x代表數組對象 //start表示開始位置索引 //end是結束位置下一數組元素索引編號 //第一個數組元素索引為0 //start、end可為負數,-1代表最后一個數組元素 //end省略則相當于從start位置截取以后所有數組元素var arr1=['a','b','c','d','e','f','g','h']; var arr2=arr1.slice(2,4); var arr3=arr1.slice(4); var arr4=arr1.slice(2,-1);alert(arr2.toString()); //結果為"c,d" alert(arr3.toString()); //結果為"e,f,g,h" alert(arr4.toString()); //結果為"c,d,e,f,g" View Code(5)刪除子數組:splice
//x. splice(start, deleteCount, value, ...)//使用注解//x代表數組對象 //splice的主要用途是對數組指定位置進行刪除和插入 //start表示開始位置索引 //deleteCount刪除數組元素的個數 //value表示在刪除位置插入的數組元素 //value參數可以省略 var a = [1,2,3,4,5,6,7,8]; a.splice(1,2);alert(a.toString());//a變為 [1,4,5,6,7,8] a.splice(1,1);alert(a.toString());//a變為[1,5,6,7,8] a.splice(1,0,2,3);alert(a.toString());//a變為[1,2,3,5,6,7,8] View Code(6)數組的push和pop
//push pop這兩個方法模擬的是一個棧操作//x.push(value, ...) 壓棧 //x.pop() 彈棧 //使用注解 // //x代表數組對象 //value可以為字符串、數字、數組等任何值 //push是將value值添加到數組x的結尾 //pop是將數組x的最后一個元素刪除var arr1=[1,2,3]; arr1.push(4,5); alert(arr1); //結果為"1,2,3,4,5" arr1.push([6,7]); alert(arr1) //結果為"1,2,3,4,5,6,7" arr1.pop(); alert(arr1); //結果為"1,2,3,4,5" View Code(7)數組的shift和unshift
//x.unshift(value,...) //x.shift() //使用注解//x代表數組對象 //value可以為字符串、數字、數組等任何值 //unshift是將value值插入到數組x的開始 //shift是將數組x的第一個元素刪除var arr1=[1,2,3]; arr1.unshift(4,5); alert(arr1); //結果為"4,5,1,2,3" arr1. unshift([6,7]); alert(arr1); //結果為"6,7,4,5,1,2,3" arr1.shift(); alert(arr1); //結果為"4,5,1,2,3" View Code3.3:Date對象
3.3.1:創建date對象
//方法1:不指定參數 var nowd1=new Date(); alert(nowd1.toLocaleString( )); //方法2:參數為日期字符串 var nowd2=new Date("2004/3/20 11:12"); alert(nowd2.toLocaleString( )); var nowd3=new Date("04/03/20 11:12"); alert(nowd3.toLocaleString( )); //方法3:參數為毫秒數 var nowd3=new Date(5000); alert(nowd3.toLocaleString( )); alert(nowd3.toUTCString());//方法4:參數為年月日小時分鐘秒毫秒 var nowd4=new Date(2004,2,20,11,12,0,300); alert(nowd4.toLocaleString( ));//毫秒并不直接顯示3.3.2:Date對象的方法--獲取日期和時間
獲取日期和時間 getDate() 獲取日 getDay () 獲取星期 getMonth () 獲取月(0-11) getFullYear () 獲取完整年份 getYear () 獲取年 getHours () 獲取小時 getMinutes () 獲取分鐘 getSeconds () 獲取秒 getMilliseconds () 獲取毫秒 getTime () 返回累計毫秒數(從1970/1/1午夜)3.3.3:Date對象的方法—設置日期和時間
//設置日期和時間 //setDate(day_of_month) 設置日 //setMonth (month) 設置月 //setFullYear (year) 設置年 //setHours (hour) 設置小時 //setMinutes (minute) 設置分鐘 //setSeconds (second) 設置秒 //setMillliseconds (ms) 設置毫秒(0-999) //setTime (allms) 設置累計毫秒(從1970/1/1午夜)var x=new Date(); x.setFullYear (1997); //設置年1997 x.setMonth(7); //設置月7 x.setDate(1); //設置日1 x.setHours(5); //設置小時5 x.setMinutes(12); //設置分鐘12 x.setSeconds(54); //設置秒54 x.setMilliseconds(230); //設置毫秒230 document.write(x.toLocaleString( )+"<br>"); //返回1997年8月1日5點12分54秒 x.setTime(870409430000); //設置累計毫秒數 document.write(x.toLocaleString( )+"<br>"); //返回1997年8月1日12點23分50秒 View Code3.4:Math對象
//該對象中的屬性方法 和數學有關. abs(x) 返回數的絕對值。 exp(x) 返回 e 的指數。 floor(x)對數進行下舍入。 log(x) 返回數的自然對數(底為e)。 max(x,y) 返回 x 和 y 中的最高值。 min(x,y) 返回 x 和 y 中的最低值。 pow(x,y) 返回 x 的 y 次冪。 random() 返回 0 ~ 1 之間的隨機數。 round(x) 把數四舍五入為最接近的整數。 sin(x) 返回數的正弦。 sqrt(x) 返回數的平方根。 tan(x) 返回角的正切。//方法練習://alert(Math.random()); // 獲得隨機數 0~1 不包括1.//alert(Math.round(1.5)); // 四舍五入//練習:獲取1-100的隨機整數,包括1和100//var num=Math.random();//num=num*10;//num=Math.round(num);//alert(num)//============max min=========================/* alert(Math.max(1,2));// 2alert(Math.min(1,2));// 1 *///-------------pow--------------------------------alert(Math.pow(2,4));// pow 計算參數1 的參數2 次方.3.5:Function對象(重點)
3.5.1:函數的定義
function 函數名 (參數){?<br> 函數體;return 返回值; }功能說明:
可以使用變量、常量或表達式作為函數調用的參數,
函數由關鍵字function定義,
函數名的定義規則與標識符一致,大小寫是敏感的,
返回值必須使用return,
function類可以表示開發者定義的任何函數。
用Function類直接創建函數的語法如下:
var 函數名 = new Function("參數1","參數n","function_body");雖然由于字符串的關系,第二種形式寫起來有些困難,但有助于理解函數只不過是一種引用類型,它們的行為與用Function類明確創建的函數行為是相同的
function func1(name){alert('hello'+name);return 8 }ret=func1("alex");alert(ret);var func2=new Function("name","alert(\"hello\"+name);") func2("amos")
注意:js的函數加載執行與python不同,它是整體加載完才會執行,所以執行函數放在函數聲明上面或下面都可以
3.5.2:函數的內置對象arguments
arguments:可以接收任何參數,相當于python的*args
function add(a,b){console.log(a+b);//3console.log(arguments.length);//2console.log(arguments);//[1,2] }add(1,2)------------------arguments的用處1 ------------------function nxAdd(){var result=0;for (var num in arguments){result+=arguments[num]}alert(result)}nxAdd(1,2,3,4,5)// ------------------arguments的用處2 ------------------function f(a,b,c){if (arguments.length!=3){throw new Error("function f called with "+arguments.length+" arguments,but it just need 3 arguments")}else {alert("success!")}}f(1,2,3,4,5) View Code3.5.3:匿名函數
// 匿名函數var func = function(arg){return "tony";}// 匿名函數的應用(function(){alert("tony");} )()(function(arg){console.log(arg);})('123') View Code四、BOM對象
window(窗口)對象
所有瀏覽器都支持 window 對象。概念上講.一個html文檔對應一個window對象.
功能上講: 控制瀏覽器窗口的.
使用上講: window對象不需要創建對象,直接使用即可.
? 4.1:window對象方法
alert() 顯示帶有一段消息和一個確認按鈕的警告框。 confirm() 顯示帶有一段消息以及確認按鈕和取消按鈕的對話框。 prompt() 顯示可提示用戶輸入的對話框。open() 打開一個新的瀏覽器窗口或查找一個已命名的窗口。 close() 關閉瀏覽器窗口。setInterval() 按照指定的周期(以毫秒計)來調用函數或計算表達式。 clearInterval() 取消由 setInterval() 設置的 timeout。 setTimeout() 在指定的毫秒數后調用函數或計算表達式。 clearTimeout() 取消由 setTimeout() 方法設置的 timeout。 scrollTo() 把內容滾動到指定的坐標。方法使用
setInterval,clearInterval
setinterval()方法會不停地調用函數,直到clearInterval()被調用或者窗口被關閉。由setinterval()返回的ID值可作clearinterval()方法的參數。
語法:setInterval(code,millisec) 其中,code為要調用的函數或要執行的代碼串。millisec周期性執行或調用 code 之間的時間間隔,以毫秒計。 <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta http-equiv="x-ua-compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Title</title><script>var ID;function start() {if (ID==undefined){foo();ID=setInterval(foo,1000)}}function foo() {var timer=new Date().toString(); //獲取當前時間字符串var ele=document.getElementById("time"); // 獲取操作標簽對象ele.value=timer; // 對操作標簽對象進行賦值 }function end() {clearInterval(ID);ID=undefined}</script> </head> <body> <input type="text" id="time"><button οnclick="start()">start</button> <button οnclick="end()">end</button></body> </html> 示例五、DOM對象
5.1:什么是HTML DOM
- HTML? Document Object Model(文檔對象模型)
- HTML DOM 定義了訪問和操作HTML文檔的標準方法
- HTML DOM 把 HTML 文檔呈現為帶有元素、屬性和文本的樹結構(節點樹)
5.2:DOM樹
? ? ? ??
5.3:DOM節點
5.3.1:節點類型
HTML文檔中的每個成分都是一個節點。
DOM是這樣規定的:
- 整個文檔是一個文檔節點
- 每個HTML標簽是一個元素節點
- 包含在HTML元素中的文本是文本節點
- 每一個HTML屬性是一個屬性節點
其中,document與element節點是重點。
5.3.2:節點關系
節點樹中的節點彼此擁有層級關系。
父(parent),子(child)和同胞(sibling)等術語用于描述這些關系。父節點擁有子節點。同級的子節點被稱為同胞(兄弟或姐妹)。
- ??? 在節點樹中,頂端節點被稱為根(root)
- ??? 每個節點都有父節點、除了根(它沒有父節點)
- ??? 一個節點可擁有任意數量的子
- ??? 同胞是擁有相同父節點的節點
5.3.3:節點查找
直接查找節點
document.getElementById(“idname”) #通過ID查找下面的取出來是多個標簽,以數組的形式顯示 document.getElementsByTagName(“tagname”) #通過標簽名查找 document.getElementsByName(“name”) #通過name查找 document.getElementsByClassName(“name”) #通過class查找導航節點屬性
parentElement // 父節點標簽元素 children // 所有子標簽 firstElementChild // 第一個子標簽元素 lastElementChild // 最后一個子標簽元素 nextElementtSibling // 下一個兄弟標簽元素 previousElementSibling // 上一個兄弟標簽元素 注意,js中沒有辦法找到所有的兄弟標簽! 可以找到所有父標簽的子標簽,然后排除自己? 5.3.4:節點操作
(1)創建節點
createElement(標簽名) :創建一個指定名稱的元素。例:var tag=document.createElement(“input")tag.setAttribute('type','text');(2)添加節點:父節點添加子節點
追加一個子節點(作為最后的子節點) 父標簽.appendChild(添加標簽)把增加的節點放到某個節點的前邊 #兄弟之間的添加 somenode.insertBefore(newnode,某個節點);(3)刪除節點:父節點刪除子節點
父標簽.removeChild(要刪除的標簽):獲得要刪除的元素,通過父元素調用刪除(4)替換節點
父標簽.replaceChild(新節點, 父標簽中的某個節點);(5)拷貝節點
cloneNode():淺拷貝,只拷貝標簽 cloneNode(true):深拷貝,連同標簽內的標簽也一起拷貝過去 注意:拷貝會把ID也拷貝過去(6)節點屬性操作
1.獲取文本節點的值:
innerText(不認標簽,只認文本):賦值時都會賦成純文本 innerHTML(標簽文本都可以識別):賦值時可以賦標簽, 都會刪除原來的內容然后添加內容2.取值操作:
方式一:element.getAttribute(屬性名)(可以取到自定義屬性)
方式二: element.屬性名(推薦,只能取到固有屬性,取不到自定義屬性) 3.賦值操作: 方式一:
element.setAttribute(屬性名,屬性值)
方式二:
element.屬性名="屬性值"
4.select標簽操作
this.selectedIndex 拿到和用戶選中標簽索引 this.options 相當于拿到子標簽 this.options[this.selectedIndex].innerText 拿到選中標簽的值ele_select.options.length=0 清空select標簽的集合,可以設定保留幾個值5.4:DOM Event(事件)
5.4.1:事件類型:事件都是由操作系統監聽的
onclick 當用戶點擊某個對象時調用的事件句柄。 ondblclick 當用戶雙擊某個對象時調用的事件句柄。onfocus 元素獲得焦點。 練習:輸入框 onblur 元素失去焦點。 應用場景:用于表單驗證,用戶離開某個輸入框時,代表已經輸入完了,我們可以對它進行驗證. onchange 域的內容被改變(主要應用于select標簽)。 應用場景:通常用于表單元素,當元素內容被改變時觸發.(三級聯動)onkeydown 某個鍵盤按鍵被按下。 應用場景: 當用戶在最后一個輸入框按下回車按鍵時,表單提交. onkeypress 某個鍵盤按鍵被按下并松開。 onkeyup 某個鍵盤按鍵被松開。window.onload 一張頁面或一幅圖像完成加載。 onmousedown 鼠標按鈕被按下。和onclick不同的是他里面還可以配合onmousemove使用 onmousemove 鼠標被移動。 onmouseout 鼠標從某元素移開。 onmouseover 鼠標移到某元素之上。 onmouseleave 鼠標從元素離開//onmouseout和onmouseleave的區別 // 1.不論鼠標指針離開被選元素還是任何子元素,都會觸發 mouseout 事件。 // 2.只有在鼠標指針離開被選元素時,才會觸發 mouseleave 事件。 onselect 文本被選中。 onsubmit 確認按鈕被點擊(用于form表單)。5.4.2:綁定事件方式
方式一:
<div id="div" οnclick="foo(this)">點我呀</div><script>function foo(self){ // 形參不能是this;console.log("點你大爺!");console.log(self); } </script>方式二
<p id="abc">試一試!</p><script>var ele=document.getElementById("abc");ele.onclick=function(){console.log("ok");console.log(this); // this直接用 };</script>5.4.3:事件介紹
1.onload:
onload屬性在開發中只給body元素加,這個屬性的觸發標志著頁面內容被加載完成,應用場景:當有些事情我們希望頁面加載完立刻執行,那么可以使用該事件屬性。
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title><script>window.onload=function () {var ele=document.getElementById("c1");ele.style.color="green";};</script></head> <body><div id="c1">div</div></body> </html> View Code2.onsubmit:
當表單在提交時觸發,該屬性也只能給form元素使用,應用場景:在表單提交驗證用戶輸入是否正確,如果驗證失敗,在該方法中我們應該阻止表單的提交
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta http-equiv="x-ua-compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Title</title> </head> <body> <form action="" id="form"><p>姓名 <input type="text" id="name"></p><p>密碼 <input type="password" id="psw"></p><input type="submit"> </form> <script>var ele_form=document.getElementById("form");var ele_name=document.getElementById("name");var ele_psw=document.getElementById("psw");ele_form.onsubmit=function () {if (ele_name.value.length < 5){var ele_err=document.createElement("span");ele_err.innerHTML="輸入字符必須大于5";ele_err.style.color="red";ele_form.appendChild(ele_err);return false}} </script> </body> </html> View Code3.事件傳播:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta http-equiv="x-ua-compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Title</title><style>.outer{width: 400px;height: 400px;background-color: #396bb3;}.inner{width: 200px;height: 200px;background-color: #e59373;}</style> </head> <body> <div class="outer"><div class="inner"></div> </div> </body> <script>var ele_outer=document.getElementsByClassName("outer")[0];var ele_inner=document.getElementsByClassName("inner")[0];ele_outer.onclick=function () {alert(123)};ele_inner.onclick=function (e) {alert(456);e.stopPropagation() //阻止事件傳播 } </script> </html> View Code4.onselect:文本被選中時
<input type="text"><script>var ele=document.getElementsByTagName("input")[0];ele.onselect=function(){alert(123);}</script> View Code5.onchange
<select name="" id=""><option value="">111</option><option value="">222</option><option value="">333</option> </select><script>var ele=document.getElementsByTagName("select")[0];ele.onchange=function(){alert(123);}</script> View Code6.onkeydown:
Event對象:Event對象代表事件的狀態,比如事件在其中發生的元素、鍵盤按鍵的狀態、鼠標的位置、鼠標按鈕的狀態。
事件通常與函數結合使用,函數不會在事件發生前被執行!event對象在事件發生時系統已經創建好了,并且會在事件函數被調用時傳給事件函數,我們獲得僅僅需要接收一下即可,比如onkeydown,我們想知道哪個鍵被按下了,需要問下event對象的屬性,這里就是keyCode。
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta http-equiv="x-ua-compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Title</title> </head> <body> <input type="text" id="user"></body> <script>var ele=document.getElementById("user");// event對象是保存事件觸發狀態的對象,由操作系統發送ele.οnkeydοwn=function (e) {e=e||window.event;console.log(String.fromCharCode(e.keyCode));//e.keyCode拿到的是按下鍵的asc碼,然后用String.fromCharCode方法拿到用戶按下的鍵 } </script> </html> View Code7.onmouseout與onmouseleave事件的區別:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title><style>#container{width: 300px;}#title{cursor: pointer;background: #ccc;}#list{display: none;background:#fff;}#list div{line-height: 50px;}#list .item1{background-color: green;}#list .item2{background-color: rebeccapurple;}#list .item3{background-color: lemonchiffon;}</style> </head> <body><p>先看下使用mouseout的效果:</p><div id="container"><div id="title">使用了mouseout事件↓</div><div id="list"><div class="item1">第一行</div><div class="item2">第二行</div><div class="item3">第三行</div></div> </div><script>// 1.不論鼠標指針離開被選元素還是任何子元素,都會觸發 mouseout 事件。// 2.只有在鼠標指針離開被選元素時,才會觸發 mouseleave 事件。var container=document.getElementById("container");var title=document.getElementById("title");var list=document.getElementById("list");title.onmouseover=function(){list.style.display="block";};container.onmouseleave=function(){ // 改為mouseout試一下list.style.display="none";};/*因為mouseout事件是會冒泡的,也就是onmouseout事件可能被同時綁定到了container的子元素title和list 上,所以鼠標移出每個子元素時也都會觸發我們的list.style.display="none";*//*思考:if:list.οnmοuseοut=function(){list.style.display="none";};為什么移出第一行時,整個list會被隱藏?其實是同樣的道理,onmouseout事件被同時綁定到list和它的三個子元素item上,所以離開任何一個子元素同樣會觸發list.style.display="none";*/</script> </body> </html> View Code六、實例練習
1.二級聯動 <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta http-equiv="x-ua-compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Title</title> </head> <body> <select name="" id="s1"><option value="">請選擇省份</option><option value="">山西</option><option value="">河北</option> </select><select name="" id="s2"><option value="">請選擇城市</option> </select></body> <script>data={"山西":["太原","陽泉","大同"],"河北":["石家莊","邯鄲"]};var ele=document.getElementById("s1");var ele2=document.getElementById("s2");ele.onchange=function () {ele2.options.length=0;var ele_pro=this.children[this.selectedIndex].innerText;for (var i in data){if (i==ele_pro){for (var j in data[i]){var city= document.createElement("option");city.innerHTML=data[i][j];ele2.appendChild(city)}}}} </script> </html> View Code2.模態對話框
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title><style>.back{background-color: white;height: 2000px;}.shade{position: fixed;top: 0;bottom: 0;left:0;right: 0;background-color: grey;opacity: 0.4;}.hide{display: none;}.models{position: fixed;top: 50%;left: 50%;margin-left: -100px;margin-top: -100px;height: 200px;width: 200px;background-color: wheat;}</style> </head> <body> <div class="back"><input class="c" type="button" value="click"> </div><div class="shade hide handles"></div><div class="models hide handles"><input class="c" type="button" value="cancel"> </div><script>var eles=document.getElementsByClassName("c");var handles=document.getElementsByClassName("handles");for(var i=0;i<eles.length;i++){eles[i].onclick=function(){if(this.value=="click"){for(var j=0;j<handles.length;j++){handles[j].classList.remove("hide");}}else {for(var j=0;j<handles.length;j++){handles[j].classList.add("hide");}}}}</script></body> </html> View Code3.懸浮下拉菜單
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta http-equiv="x-ua-compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Title</title><style>.container{width: 300px;}.title{background-color: gray;line-height: 44px;text-align: center;}.list{display: none;}.list div{line-height: 40px;}.item1{background-color: #396bb3;}.item2{background-color: #ffc392;}.item3{background-color: #ff487f;}</style> </head> <body> <div class="container"><div class="title">text</div><div class="list"><div class="item1">111</div><div class="item2">222</div><div class="item3">333</div></div> </div> <script>var ele=document.getElementsByClassName("title")[0];var ele_list=document.getElementsByClassName("list")[0];var ele_box=document.getElementsByClassName("container")[0];ele.onmouseover=function () {ele_list.style.display="block";};ele_box.onmouseleave=function () {ele_list.style.display="none"} </script> </body> </html> View Code4.圖書管理系統
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta http-equiv="x-ua-compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Title</title><style>*{margin: 0;padding: 0;}.navbar{float: left;width: 100%;height: 50px;background-color: #272425;}.left_menu{float: left;width: 20%;margin-left: -1px;height: 500px;border-right: 1px solid;}.right_content{position: relative;top: 0;left: 0;float: left;width: 77%;height: 500px;padding-left: 40px;margin-right: -1px;}.operation{margin-top: 20px;color: white;width: 100%;height: 30px;text-align: center;line-height: 30px;background-color: #396bb3;}.operation_list{list-style: none;}.operation_list li{margin: 10px;font-size: 14px;}.operation_list li a{color: #396bb3;text-decoration: none;}.book_info{width: 100%;font-size: 14px;}td{width: 50px;height: 40px;border-top: 1px solid #e1e1e1;}.search_box{width: 100%;height: 100px;}#search_bar{padding: 10px;position: absolute;right: 144px;top: 36px;width: 200px;border-radius: 7px;border: 1px solid #e1e1e1;}.search_btn{color: white;border-radius: 5px;padding: 9px;background-color: #396bb3;position: absolute;right: 93px;top: 34px;}.hide{display: none;}.shade{position: fixed;top: 0;bottom: 0;left: 0;right: 0;background-color: black;opacity: 0.4;}.model,.model2{width: 500px;height: 400px;background-color:white;position: fixed;top: 50%;left:50%;margin-top: -200px;margin-left: -250px;}.btn{width: 50px;height: 30px;border-radius: 5px;color: white;}.btn1{background-color: #ff1732;}.btn2{background-color: #396bb3;}.btn3{background-color: #4cff82;}.btn4{background-color: #ffdd3f;}.input_field,.input_field2{height: 30px;border-radius: 5px;margin: 10px;}.model,.model2{padding-left: 150px;}#put,#update{margin-left: 100px;}#cancle,#quit{margin-left: 50px;}.head{width: 80%;height: 100%;margin: 0 auto;}.title{float: left;color: white;font-size: 28px;line-height: 100%;margin-top: 8px;}.index_link{float: left;color: #e1e1e1;font-size: 15px;margin-top: 15px;margin-left: 80px;text-decoration: none;}.copyright{line-height: 30px;text-align: center;font-size: 14px;}</style> </head> <body> <div class="outer"><div class="navbar"><div class="head"><div class="title">圖書管理系統</div><div ><a href="" class="index_link">首頁</a></div></div></div><div class="left_menu"><div class="operation">操作</div><ul class="operation_list"><!--<li><a href="" >>>>添加書籍</a></li>--><li><a href="" >>>>草稿箱</a></li><li><a href="" >>>>設置默認編輯器</a></li><li><a href="" >>>>備份書籍</a></li></ul></div><div class="right_content"><div class="search_box"><form action=""><input type="text" placeholder="Title" id="search_bar"></form><button class="search_btn">查找</button></div><button class="btn2 btn">添加</button><table class="book_info"><tr><td>圖書編號</td><td>書名</td><td>作者</td><td>價格</td><td>分類</td><td>上架時間</td><td>操作</td></tr><tr><td>1</td><td>囚徒健身</td><td>保羅·威德(美)</td><td>79¥</td><td>健身</td><td>2013年10月</td><td><button class="btn4 btn">編輯</button><button class="btn1 btn">刪除</button></td></tr><tr><td>2</td><td>萬歷十五年</td><td>黃仁宇</td><td>18¥</td><td>歷史</td><td>1990年1月1日</td><td><button class="btn4 btn">編輯</button><button class="btn1 btn">刪除</button></td></tr></table></div><div class="shade hide"></div><div class="model hide"><div>圖書編號:<input type="text" class="input_field" value=""></div><div> 書名:<input type="text" class="input_field" value=""></div><div> 作者:<input type="text" class="input_field" value=""></div><div> 價格:<input type="text" class="input_field" value=""></div><div> 分類:<input type="text" class="input_field" value=""></div><div>上架時間:<input type="text" class="input_field" value=""></div><button class="btn3 btn" id="put">提交</button><button class="btn1 btn" id="cancle">取消</button></div><div class="model2 hide"><div>圖書編號:<input type="text" class="input_field2" value=""></div><div> 書名:<input type="text" class="input_field2" value=""></div><div> 作者:<input type="text" class="input_field2" value=""></div><div> 價格:<input type="text" class="input_field2" value=""></div><div> 分類:<input type="text" class="input_field2" value=""></div><div>上架時間:<input type="text" class="input_field2" value=""></div><button class="btn3 btn" id="update">更新</button><button class="btn1 btn" id="quit">退出</button></div><div class="copyright"><p>©All rights reserved</p><p><b>Powered by</b> Amos</p></div> </div> <script>//拿到所有的button標簽var eles_btn=document.getElementsByTagName("button");//刪除表格一行的函數function cancel() {var ele_grand=this.parentElement.parentElement.parentElement;var ele_father=this.parentElement.parentElement;ele_grand.removeChild(ele_father);}//編輯函數function compile() {var ele_shade=this.parentElement.parentElement.parentElement.parentElement.nextElementSibling;var ele_model2=ele_shade.nextElementSibling.nextElementSibling;ele_shade.classList.remove("hide");ele_model2.classList.remove("hide");var eles_info=this.parentElement.parentElement.children;var eles_value=document.getElementsByClassName("input_field2");edit_obj=this.parentElement.parentElement;for (var i=0;i<eles_info.length-1;i++){eles_value[i].value=eles_info[i].innerText;}}//循環每個按鈕,對應按鈕進行操作for (var i=0;i<eles_btn.length;i++){//按鈕被點擊的時候eles_btn[i].οnclick=function () {//如果被點擊的是添加按鈕:彈出對話框if (this.innerText=="添加"){var eles_val=document.getElementsByClassName("input_field");for (var i in eles_val){eles_val[i].value='';}var ele_shade=this.parentElement.nextElementSibling;var ele_model=ele_shade.nextElementSibling;ele_shade.classList.remove("hide");ele_model.classList.remove("hide");}//如果被點擊的是提交按鈕: // 1.拿到用戶輸入的值 // 2.添加一行表格 // 3.把用戶輸入的值添加到本行 // 4.添加刪除按鈕 // 5.關閉對話框else if(this.innerText=="提交"){var eles_val=document.getElementsByClassName("input_field");var eles_book_info=document.getElementsByClassName("book_info");var ele_tr=document.createElement("tr");eles_book_info[0].appendChild(ele_tr);for (i=0;i<eles_val.length;i++){var ele_td=document.createElement("td");ele_td.innerText=eles_val[i].value;ele_tr.appendChild(ele_td);}//創建刪除,編輯按鈕var ele_td2=document.createElement("td");ele_tr.appendChild(ele_td2);var ele_cancel_btn = document.createElement('button');ele_cancel_btn.innerText="刪除";ele_cancel_btn.classList.add("btn1");ele_cancel_btn.classList.add("btn");ele_cancel_btn.onclick=cancel;var ele_edit_btn=document.createElement("button");ele_edit_btn.innerText="編輯";ele_edit_btn.onclick=compile;ele_edit_btn.classList.add("btn4");ele_edit_btn.classList.add("btn");ele_td2.appendChild(ele_edit_btn);ele_td2.appendChild(ele_cancel_btn);//隱藏對話框var ele_model=this.parentElement;var ele_shade=ele_model.previousElementSibling;ele_shade.classList.add("hide");ele_model.classList.add("hide");}else if(this.innerText=="取消"){//隱藏對話框var ele_model=this.parentElement;var ele_shade=ele_model.previousElementSibling;ele_shade.classList.add("hide");ele_model.classList.add("hide");}else if(this.innerText=="刪除"){var ele_grand=this.parentElement.parentElement.parentElement;var ele_father=this.parentElement.parentElement;ele_grand.removeChild(ele_father);}else if(this.innerText=="編輯"){//把表格中的數據顯示到對話框中var eles_info=this.parentElement.parentElement.children;var eles_value=document.getElementsByClassName("input_field2");var ele_table=this.parentElement.parentElement.parentElement.parentElement;edit_obj=this.parentElement.parentElement;for (var i=0;i<eles_info.length-1;i++){eles_value[i].value=eles_info[i].innerText;}//顯示對話框var ele_shade=ele_table.parentElement.nextElementSibling;var ele_model2=ele_shade.nextElementSibling.nextElementSibling;ele_shade.classList.remove("hide");ele_model2.classList.remove("hide");}else if(this.innerText=="更新"){ // 1.拿到用戶輸入的值, // 2.循環創建td標簽,并賦值 // 3.創建tr標簽,添加td標簽, // 4.找到目標標簽替換 // 5.隱藏對話框var eles_value=document.getElementsByClassName("input_field2");var new_tr=document.createElement("tr");for (var i=0;i<eles_value.length;i++){var new_td=document.createElement("td");new_td.innerText=eles_value[i].value;new_tr.appendChild(new_td);}//拿到新tr標簽中的每一個td標簽//然后用新td的值替換舊td的值var new_tr_child=new_tr.children;var old_tr_child=edit_obj.children;for (var i=0;i<new_tr_child.length;i++){old_tr_child[i].innerText=new_tr_child[i].innerText;}//隱藏對話框var ele_model2=this.parentElement;var ele_shade=ele_model2.previousElementSibling.previousElementSibling;ele_shade.classList.add("hide");ele_model2.classList.add("hide");}else if(this.innerText=="退出"){//隱藏對話框var ele_model2=this.parentElement;var ele_shade=ele_model2.previousElementSibling.previousElementSibling;ele_shade.classList.add("hide");ele_model2.classList.add("hide");}};}</script> </body> </html> View Code七、JS擴展
1.JS的作用域
作用域是JavaScript最重要的概念之一,在JavaScript中,變量的作用域有全局作用域和局部作用域兩種。
1.1:全局作用域(global scope)
在代碼中任何地方都能訪問到的對象擁有全局作用域,一般來說以下幾種情況擁有全局作用域:
(1)最外層函數和在最外層函數外面定義的變量擁有全局作用域
var name="amos";function foo(){var age=23;function inner(){console.log(age);}inner();}console.log(name); // amos//console.log(age); // Uncaught ReferenceError: age is not definedfoo(); // 23inner(); // Uncaught ReferenceError: inner is not defined(2)所有未定義直接復制的變量自動聲明為擁有全局作用域,例如:
var name="amos";function foo(){age=23;var sex="male"}foo();console.log(age); // 23console.log(sex); // sex is not defined變量age擁有全局作用域,而sex在函數外部無法訪問到。
(3)所有window對象的屬性擁有全局作用域
一般情況下,window對象的內置屬性都擁有全局作用域,例如window.alert()、window.location、window.top等等。
1.2:局部作用域(Local Scope)
和全局作用域相反,局部作用域一般只在固定的代碼片段內可訪問到,最常見的例如函數內部,所有在一些地方也會看到有人把這種作用域稱為函數作用域。
js中if/for沒有自己的作用域。
2.作用域鏈(Scope chain)
在JavaScript中,函數也是對象,實際上,JavaScript里一切都是對象。函數對象和其它對象一樣,擁有可以通過代碼訪問的屬性和一系列僅供JavaScript引擎訪問的內部屬性。其中一個內部屬性是[[Scope]],由ECMA-262標準第三版定義,該內部屬性包含了函數被創建的作用域中對象的集合,這個集合被稱為函數的作用域鏈,它決定了哪些數據能被函數訪問。
2.1:示例演示
//-----**********************例1*********************************var s=12;function f(){console.log(s);var s=12; // if s=12 console.log(s)}f();//-----**********************例2*********************************var s=10; function foo(){console.log(s);var s=5;console.log(s);function s(){console.log("ok")}// 函數的定于或聲明是在詞法分析時完成的,執行時已不再有任何操作 console.log(s); }foo();//-----***********************例3********************************function bar(age) {console.log(age);var age = 99;var sex= 'male';console.log(age);function age() {alert(123)};console.log(age);return 100; }result=bar(5);//-----********************************************************2.2:結果分析
我相信大家一定會有想不到的結果,接下來我們就以最復雜的例3來分析整個過程。
當一個函數創建后,它的作用域鏈會被創建此函數的作用域中可訪問的數據對象填充。在函數bar創建時,它的作用域鏈中會填入一個全局對象,該全局對象包含了所有全局變量,如下圖所示:
解析到函數調用時,即bar(5),會生成一個active object的對象,該對象包含了函數的所有局部變量、命名參數、參數集合以及this,然后此對象會被推入作用域鏈的前端,當運行期上下文被銷毀,活動對象也隨之銷毀。新的作用域鏈如下圖所示:
過程解析:
function bar(age) {console.log(age);var age = 99;var sex="male";console.log(age);function age(){alert(123);} ;console.log(age);return 100; }result=bar(5);一 詞法分析過程(涉及參數,局部變量聲明,函數聲明表達式):1-1 、分析參數,有一個參數,形成一個 AO.age=undefine;1-2 、接收參數 AO.age=5;1-3 、分析變量聲明,有一個 var age, 發現 AO 上面有一個 AO.age ,則不做任何處理1-4 、分析變量聲明,有一個 var sex,形成一個 AO.sex=undefine;1-5 、分析函數聲明,有一個 function age(){} 聲明, 則把原有的 age 覆蓋成 AO.age=function(){}; 二 執行過程:2-1 、執行第一個 console.log(age) 時,當前的 AO.age 是一個函數,所以輸出的一個函數2-2 、這句 var age=99; 是對不 AO.age 的屬性賦值, AO.age=99 ,所以在第二個輸出的age是 99;2-3 、同理第三個輸出的是 99, 因為中間沒有改變 age 值的語句了。注意:執行階段:function age(){alert(123)} ;不進行任何操作,將執行語句復制給age這部操作是在詞法分析時,即運行前完成的。?
轉載于:https://www.cnblogs.com/78pikaqiu/p/7300965.html
總結
以上是生活随笔為你收集整理的【前端】JavaScript的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mvcpager之学习
- 下一篇: solr入门之參考淘宝搜索提示功能优化拼