一、簡介
JavaScript是一門編程語言,瀏覽器內置了JavaScript語言的解釋器,所以在瀏覽器上按照JavaScript語言的規則編寫相應代碼之,瀏覽器可以解釋並做出相應的處理。學習了html和css做出來的網頁只是靜態的網頁,如果需要網頁出現各種效果,那么需要學習一門新的語言JavaScript和DOM才能讓網頁編程動態。
二、代碼存放位置
理論上放在body和head中都可以,但是推薦放在body代碼塊底部,因為Html代碼是從上到下執行,如果Head中的js代碼耗時嚴重,就會導致用戶長時間無法看到頁面,如果放置在body代碼塊底部,那么即使js代碼耗時嚴重,也不會影響用戶看到頁面效果,只是js實現特效慢而已。
Js代碼可以放在一個單獨的文件中,然后通過 <script src="common.js" type="text/javascript"></script>可以將其導入進來,或者直接在html文件中直接書寫代碼,如下面所示,其中兩種方式的 type都可以不用寫,因為瀏覽器默認的便是javascript
方式一:type="text/javascript"可以省略
<head> <meta charset='utf8'> <title></title> <script src='common.js'></script> </head>
方式二:type="text/javascript"可以省略 <body> <script> Js代碼內容..... </script> </body>
三、變量
JavaScript中變量的聲明是一個非常容易出錯的點,
局部變量:函數內局部變量必須一個 var 開頭,函數內如果未使用var也是定義局部變量,所以為了不搞混,局部變量var開頭,重新賦值也要用var
全局變量:函數外則默認表示聲明的是全局變量。
<script> name = 'seven'; // 不加var,全局變量 function func(){ var age = 18; // 加var,局部變量 age = 21; // 對局部變量重新賦值,所以定義局部變量也好,修改局部變量也好都加上var就不會亂了 var age = 28; name = "tomcat"; // 對全局變量重新賦值 gender = "女"; // 這是局部變量,別亂了,所以定義局部變量使用var
alert(age); alert(name);
alert(gender); } alert(name); func() </script>
JavaScript中代碼注釋:
- 單行 //
- 多行 /* */
注意:此注釋僅在Script塊中生效。
四、數據類型
JavaScript 中的數據類型分為原始類型和對象類型:
原始類型:
- 數字
- 字符串
- 布爾值
對象類型:
- 數組
- “字典”
- ...
特別的,數字、布爾值、null、undefined、字符串是不可變。
// null、undefined null是JavaScript語言的關鍵字,它表示一個特殊值,常用來描述“空值”。 undefined是一個特殊值,表示變量未定義。
1、數字(Number)
JavaScript中不區分整數值和浮點數值,JavaScript中所有數字均用浮點數值表示。
轉換:
- parseInt(..) 將某值轉換成數字,不成功則NaN
- parseFloat(..) 將某值轉換成浮點數,不成功則NaN
特殊值:
- NaN,非數字。可使用 isNaN(num) 來判斷。
- Infinity,無窮大。可使用 isFinite(num) 來判斷。
<script>
num1 = 123; // 定義一個數字
num2 = new Number(456); // 創建數字對象
num3 = new Number(789);
console.log(num1,num2,num3.valueOf()); // 輸出123 Number { 456 } 789
a = '888';
console.log(typeof a); // 輸出string
num4 = parseInt(a); // 將字符串轉換成數字
console.log(num4); // 輸出888
b = 'a123';
num5 = parseInt(b); // 無法轉換則返回NaN
console.log(num5); // 輸出NaN
if(isNaN(num5)){
console.log('b無法轉換成數字,所以返回NaN');
}
else{
cosole.log('b能轉換成數字');
}
console.log(isFinite(num1)); // 判斷是否為有限值,輸出true
console.log(typeof num1); // 輸出什么類型,輸出number
num6 = 12.888888;
console.log(num6.toFixed(2)); // 保留小數位,輸出12.89
console.log(num6.toExponential(3)); // 12.89e+1
</script>
2、字符串(String)
字符串是由字符組成的數組,但在JavaScript中字符串是不可變的:可以訪問字符串任意位置的文本,但是JavaScript並未提供修改已知字符串內容的方法。
常見功能:
obj.length 長度
obj.trim() 移除空白
obj.trimLeft()
obj.trimRight)
obj.charAt(n) 返回字符串中的第n個字符
obj.concat(value, ...) 拼接
obj.indexOf(substring,start) 子序列位置
obj.lastIndexOf(substring,start) 子序列位置
obj.substring(from, to) 根據索引獲取子序列
obj.slice(start, end) 切片
obj.toLowerCase() 大寫
obj.toUpperCase() 小寫
obj.split(delimiter, limit) 分割
obj.search(regexp) 從頭開始匹配,返回匹配成功的第一個位置(g無效)
obj.match(regexp) 全局搜索,如果正則中有g表示找到全部,否則只找到第一個。
obj.replace(regexp, replacement) 替換,正則中有g則替換所有,否則只替換第一個匹配項,
$數字:匹配的第n個組內容;
$&:當前匹配的內容;
$`:位於匹配子串左側的文本;
$':位於匹配子串右側的文本
$$:直接量$符號
3、布爾類型(Boolean)
布爾類型僅包含真假,與Python不同的是其首字母小寫。
== 比較值相等 != 不等於 === 比較值和類型相等 !== 不等於 || 或 && 且
<script> console.log(1 == '1'); //true console.log(1 != '1'); //false console.log(1 === '1'); //false console.log(1 !== '1'); //true </script>
4、數組
JavaScript中的數組類似於Python中的列表
常見功能:
obj.length 數組的大小
obj.push(ele) 尾部追加元素
obj.pop() 尾部獲取一個元素
obj.unshift(ele) 頭部插入元素
obj.shift() 頭部移除元素
obj.splice(start, deleteCount, value, ...) 插入、刪除或替換數組的元素
obj.splice(n,0,val) 指定位置插入元素
obj.splice(n,1,val) 指定位置替換元素
obj.splice(n,1) 指定位置刪除元素
obj.slice( ) 切片
obj.reverse( ) 反轉
obj.join(sep) 將數組元素連接起來以構建一個字符串
obj.concat(val,..) 連接數組
obj.sort( ) 對數組元素進行排序
<script> li = [11,22,33,44,55]; console.log(li.length); li.push(66); console.log(li); li.pop(); console.log(li); li.unshift(0); console.log(li); li.shift(); console.log(li); l1 = li.slice(1,3); console.log(l1); console.log('***************************************') li.splice(1,0,'first'); console.log(li); li.splice(2,1,'second'); console.log(li); li.splice(2,2,'second'); console.log(li); li.splice(2,1); console.log(li); console.log('***************************************') b = ['a','b','c'] console.log(b.concat(li)); console.log(b.join('*')); console.log(li.reverse()); console.log([4,2,1,5].sort()) </script>
五、其他雜項
1、序列化
JSON.stringify(obj) # 序列化,將其他類型轉換成字符串
JSON.parse(str) # 反序列化,將字符串類型的數組字典轉換成當前類型
<script>
a = [11,22,33,44];
console.log(typeof a);
console.log(a);
ret = JSON.stringify(a);
console.log(typeof ret);
console.log(ret);
console.log(JSON.parse(ret));
</script>
2、轉義
decodeURI( ) URl中未轉義的字符
decodeURIComponent( ) URI組件中的未轉義字符
encodeURI( ) URI中的轉義字符
encodeURIComponent( ) 轉義URI組件中的字符
escape( ) 對字符串轉義
unescape( ) 給轉義字符串解碼
URIError 由URl的編碼和解碼方法拋出
<script>
url = 'https://www.baidu.com/?name=斗魚';
console.log(encodeURI(url));
console.log(decodeURI(encodeURI(url)));
console.log(encodeURIComponent(url));
console.log(decodeURIComponent(encodeURIComponent(url)));
</script>
3、eval
JavaScript中的eval是Python中eval和exec的合集,既可以編譯代碼也可以獲取返回值。
eval()
EvalError 執行字符串中的JavaScript代碼
4、正則表達式
(1)定義正則表達式
- /.../ 用於定義正則表達式
- /.../g 表示全局匹配
- /.../i 表示不區分大小寫
- /.../m 表示多行匹配
- JS正則匹配時本身就是支持多行,此處多行匹配只是影響正則表達式^和$,m模式也會使用^$來匹配換行的內容)
var pattern = /^Java\w*/gm; var text = "JavaScript is more fun than \nJavaEE or JavaBeans!"; result = pattern.exec(text) result = pattern.exec(text) result = pattern.exec(text)
注:定義正則表達式也可以 reg= new RegExp()
(2)匹配
JavaScript中支持正則表達式,其主要提供了兩個功能:
- test(string) 檢查字符串中是否和正則匹配
n = 'uui99sdf' reg = /\d+/ reg.test(n) ---> true # 只要正則在字符串中存在就匹配,如果想要開頭和結尾匹配的話,就需要在正則前后加 ^和$
- exec(string) 獲取正則表達式匹配的內容,如果未匹配,值為null,否則,獲取匹配成功的數組。
獲取正則表達式匹配的內容,如果未匹配,值為null,否則,獲取匹配成功的數組。
非全局模式
獲取匹配結果數組,注意:第一個元素是第一個匹配的結果,后面元素是正則子匹配(正則內容分組匹配)
var pattern = /\bJava\w*\b/;
var text = "JavaScript is more fun than Java or JavaBeans!";
result = pattern.exec(text)
var pattern = /\b(Java)\w*\b/;
var text = "JavaScript is more fun than Java or JavaBeans!";
result = pattern.exec(text)
全局模式
需要反復調用exec方法,來一個一個獲取結果,直到匹配獲取結果為null表示獲取完畢
var pattern = /\bJava\w*\b/g;
var text = "JavaScript is more fun than Java or JavaBeans!";
result = pattern.exec(text)
var pattern = /\b(Java)\w*\b/g;
var text = "JavaScript is more fun than Java or JavaBeans!";
result = pattern.exec(text)
(3)字符串中相關方法
obj.search(regexp) 獲取索引位置,搜索整個字符串,返回匹配成功的第一個位置(g模式無效)
obj.match(regexp) 獲取匹配內容,搜索整個字符串,獲取找到第一個匹配內容,如果正則是g模式找到全部
obj.replace(regexp, replacement) 替換匹配替換,正則中有g則替換所有,否則只替換第一個匹配項,
$數字:匹配的第n個組內容;
$&:當前匹配的內容;
$`:位於匹配子串左側的文本;
$':位於匹配子串右側的文本
$$:直接量$符號
5、時間
在JavaScript中,Date對象用來表示日期和時間。JavaScript中提供了時間相關的操作,分別為獲取時間和設置時間,時間操作中分為兩種時間,統一時間(UTC),以及本地時間(東8區)
var now = new Date(); now.getFullYear(); now.getMonth(); // 6, 月份,注意月份范圍是0~11,6表示7月 now.getDate(); // 7, 表示7號 now.getDay(); // 3, 表示星期三 now.getHours(); // 19, 24小時制 now.getMinutes(); // 49, 分鍾 now.getTime(); // 1435146562875, 以number形式表示的時間戳
六、語句和異常
JavaScript中支持兩個中條件語句,分別是:if 和 switch
if(條件){ }else if(條件){ }else{ }
switch(name){ case '1': age = 123; break; case '2': age = 456; break; default : age = 777; }
2、循環語句
JavaScript中支持三種循環語句,分別是:
方式一: var names = ["alex", "tony", "rain"]; for(var i=0;i<names.length;i++){ console.log(i); console.log(names[i]); } 方式二: var names = ["alex", "tony", "rain"]; for(var index in names){ console.log(index); console.log(names[index]); } 方式三: while(條件){ // break; // continue; }
注意:index是索引,不是內容
3、異常處理
try {
//這段代碼從上往下運行,其中任何一個語句拋出異常該代碼塊就結束運行
}
catch (e) {
// 如果try代碼塊中拋出了異常,catch代碼塊中的代碼就會被執行。
//e是一個局部變量,用來指向Error對象或者其他拋出的對象
}
finally {
//無論try中代碼是否有異常拋出(甚至是try代碼塊中有return語句),finally代碼塊中始終會被執行。
}
七、函數
1、函數類型
JavaScript中函數基本上可以分為一下三類,普通函數,匿名函數,自執行函數,此外需要注意的是對於JavaScript中函數參數,實際參數的個數可能小於形式參數的個數,函數內的特殊值arguments中封裝了所有實際參數。
// 普通函數
function func(arg){
return true;
}
// 匿名函數
var func = function(arg){
return "tony";
}
// 自執行函數
(function(arg){
console.log(arg);
})('123')
注意:對於JavaScript中函數參數,實際參數的個數可能小於形式參數的個數,函數內的特殊值arguments中封裝了所有實際參數。
2、作用域
JavaScript中每個函數都有自己的作用域,當出現函數嵌套時,就出現了作用域鏈。當內層函數使用變量時,會根據作用域鏈從內到外一層層的循環,如果不存在,則異常。
切記:所有的作用域在創建函數且未執行時候就已經存在。
(1)“JavaScript中無塊級作用域”
function Main(){
if(1==1){
var name = 'seven';
}
console.log(name);
}
// 輸出: seven
補充:標題之所以添加雙引號是因為JavaScript6中新引入了 let 關鍵字,用於指定變量屬於塊級作用域。
(2)JavaScript采用函數作用域
在JavaScript中每個函數作為一個作用域,在外部無法訪問內部作用域中的變量。
function Main(){
var innerValue = 'seven';
}
Main();
console.log(innerValue);
// 報錯:Uncaught ReferenceError: innerValue is not defined
(3)JavaScript的作用域鏈
由於JavaScript中的每個函數作為一個作用域,如果出現函數嵌套函數,則就會出現作用域鏈。
xo = 'tomcat';
function Func(){
var xo = "seven";
function inner(){
var xo = 'alvin';
console.log(xo);
}
inner();
}
Func();
如上述代碼則出現三個作用域組成的作用域鏈,如果出現作用域鏈后,那么尋找變量時候就會出現順序,對於上述實例:
當執行console.log(xo)時,其尋找順序為根據作用域鏈從內到外的優先級尋找,如果內層沒有就逐步向上找,直到沒找到拋出異常。
(4)JavaScript的作用域鏈執行前已創建
JavaScript的作用域在被執行之前已經創建,日后再去執行時只需要按照作用域鏈去尋找即可。
示例一:
xo = 'tomcat';
function Func(){
var xo = "seven";
function inner(){
console.log(xo);
}
return inner;
}
var ret = Func();
ret();
// 輸出結果: seven
上述代碼,在函數被調用之前作用域鏈已經存在:
- 全局作用域 -> Func函數作用域 -> inner函數作用域
當執行【ret();】時,由於其代指的是inner函數,此函數的作用域鏈在執行之前已經被定義為:全局作用域 -> Func函數作用域 -> inner函數作用域,所以,在執行【ret();】時,會根據已經存在的作用域鏈去尋找變量。
示例二:
xo = 'tomcat';
function Func(){
var xo = "mei";
function inner(){
console.log(xo);
}
xo = 'seven';
return inner;
}
var ret = Func();
ret();
// 輸出結果: seven
上述代碼和示例一的目的相同,也是強調在函數被調用之前作用域鏈已經存在:
- 全局作用域 -> Func函數作用域 -> inner函數作用域
不同的時,在執行【var ret = Func();】時,Func作用域中的xo變量的值已經由 “eric” 被重置為 “seven”,所以之后再執行【ret();】時,就只能找到“seven”。
示例三:
xo = 'tomcat';
function Bar(){
console.log(xo);
}
function Func(){
var xo = "seven";
return Bar;
}
var ret = Func();
ret();
// 輸出結果: tomcat
上述代碼,在函數被執行之前已經創建了兩條作用域鏈:
- 全局作用域 -> Bar函數作用域
- 全局作用域 -> Func函數作用域
當執行【ret();】時,ret代指的Bar函數,而Bar函數的作用域鏈已經存在:全局作用域 -> Bar函數作用域,所以,執行時會根據已經存在的作用域鏈去尋找。
(5)提前聲明變量
在JavaScript中如果不創建變量,直接去使用,則報錯:
console.log(xxoo); // 報錯:Uncaught ReferenceError: xxoo is not defined
JavaScript中如果創建值而不賦值,則該值為 undefined,如:
var xxoo; console.log(xxoo); // 輸出:undefined
在函數內如果這么寫:
function Foo(){
console.log(xo);
var xo = 'seven';
}
Foo();
// 輸出:undefined
上述代碼,不報錯而是輸出 undefined,其原因是:JavaScript的函數在被執行之前,會將其中的變量全部聲明,而不賦值。所以,相當於上述實例中,函數在“預編譯”時,已經執行了var xo;所以上述代碼中輸出的是undefined。
3、閉包
「閉包」,是指擁有多個變量和綁定了這些變量的環境的表達式(通常是一個函數),因而這些變量也是該表達式的一部分。
閉包是個函數,而它「記住了周圍發生了什么」。表現為由「一個函數」體中定義了「另個函數」
由於作用域鏈只能從內向外找,默認外部無法獲取函數內部變量。閉包,在外部獲取函數內部的變量。
function f2(){
var arg= [11,22];
function f3(){
return arg;
}
return f3;
}
ret = f2();
ret();
4、面向對象
function Foo (name,age) {
this.Name = name;
this.Age = age;
this.Func = function(arg){
return this.Name + arg;
}
}
var obj = new Foo('tomcat', 18);
var ret = obj.Func("python");
console.log(ret);
對於上述代碼需要注意:
- Foo充當的構造函數
- this代指對象
- 創建對象時需要使用 new
上述代碼中每個對象中均保存了一個相同的Func函數,從而浪費內存。使用原型和可以解決該問題:
function Foo (name,age) {
this.Name = name;
this.Age = age;
}
Foo.prototype = {
GetInfo: function(){
return this.Name + this.Age
},
Func : function(arg){
return this.Name + arg;
}
}
