javascript是一門重要弱類型的語言,由於它是web瀏覽器的語言,它與瀏覽器的結合使他成爲世界上最流行的編程語言之一。javascript
js歷史html
Nombas 和 ScriptEasejava
大概在 1992 年,一家稱做 Nombas 的公司開發了一種叫作 C 減減(C-minus-minus,簡稱 Cmm)的嵌入式腳本語言。Cmm 背後的理念很簡單:一個足夠強大能夠替代宏操做(macro)的腳本語言,同時保持與 C (和 C ++)足夠的類似性,以便開發人員能很快學會。這個腳本語言捆綁在一個叫作 CEnvi 的共享軟件中,它首次向開發人員展現了這種語言的威力。node
Nombas 最終把 Cmm 的名字改爲了 ScriptEase,緣由是後面的部分(mm)聽起來過於消極,同時字母 C 「使人懼怕」。angularjs
如今 ScriptEase 已經成爲了 Nombas 產品背後的主要驅動力。web
Netscape 發明了 JavaScript正則表達式
當 Netscape Navigator 嶄露頭角時,Nombas 開發了一個能夠嵌入網頁中的 CEnvi 的版本。這些早期的試驗被稱爲 Espresso Page(濃咖啡般的頁面),它們表明了第一個在萬維網上使用的客戶端語言。而 Nombas 絲毫沒有料到它的理念將會成爲萬維網的一塊重要基石。編程
當網上衝浪愈來愈流行時,對於開發客戶端腳本的需求也逐漸增大。此時,大部分因特網用戶還僅僅經過 28.8 kbit/s 的調制解調器鏈接到網絡,即使這時網頁已經不斷地變得更大和更復雜。而更加加重用戶痛苦的是,僅僅爲了簡單的表單有效性驗證,就要與服務器進行屢次地往返交互。設想一下,用戶填完一個表單,點擊提交按鈕,等待了 30 秒的處理後,看到的倒是一條告訴你忘記填寫一個必要的字段。數組
那時正處於技術革新最前沿的 Netscape,開始認真考慮開發一種客戶端腳本語言來解決簡單的處理問題。瀏覽器
當時工做於 Netscape 的 Brendan Eich,開始着手爲即將在 1995 年發行的 Netscape Navigator 2.0 開發一個稱之爲 LiveScript 的腳本語言,當時的目的是在瀏覽器和服務器(原本要叫它 LiveWire)端使用它。Netscape 與 Sun 及時完成 LiveScript 實現。
就在 Netscape Navigator 2.0 即將正式發佈前,Netscape 將其改名爲 JavaScript,目的是爲了利用 Java 這個因特網時髦詞彙。Netscape 的賭注最終獲得回報,JavaScript 今後變成了因特網的必備組件。
javascript的函數(主要)基於詞法做用域(lexical scoping)的頂級對象。
hello world
demo.html <!DOCTYPE html> <html> <head> <title>javascript demo</title> </head> <body> <pre> <script type="text/javascript" src="demo.js"></script> </pre> </body> </html> demo.js document.writeln('hello world')
<!DOCTYPE html> <html> <head> <title>html text</title> </head> <body> <script type="text/javascript"> document.write('hello js') </script> </body> </html> <!-- javascript 生產普通文本和標籤 --> <!DOCTYPE html> <html> <!-- javascript 生產普通文本和標籤 --> <head> <title>html text</title> </head> <body> <script type="text/javascript"> document.write('<h1>hello js</h1>') </script> </body> </html> <!-- javascript head 部分 onload事件 --> <!DOCTYPE html> <html> <!-- javascript head 部分 onload事件 --> <head> <title>html text</title> <script type="text/javascript"> function msg(){ alert("onload event on head parts") } </script> </head> <body onload="msg()"> </body> </html> <!-- javascript 點擊事件調用函數 --> <!DOCTYPE html> <html> <!-- javascript 點擊事件調用函數 --> <head> <title>html text</title> <script type="text/javascript"> function myFun(){ <!--JavaScript 語句向瀏覽器發出的命令。語句的做用是告訴瀏覽器該作什麼。下面的 JavaScript 語句向 id="demo" 的 HTML 元素輸出文本 "Hello World",在 JavaScript 中,用分號來結束語句是可選的。--> document.getElementById('demo').innerHTML='My html' } </script> </head> <body> <p id = "demo">My link</p> <button type="button" onclick="myFun()">try it</button> </body> </html> <!-- 請使用 document.write() 僅僅向文檔輸出寫內容。若是在文檔已完成加載後執行 document.write,整個 HTML 頁面將被覆蓋--> <!DOCTYPE html> <html> <!-- 請使用 document.write() 僅僅向文檔輸出寫內容。若是在文檔已完成加載後執行 document.write,整個 HTML 頁面將被覆蓋--> <head> <title>html text</title> </head> <body> <p id = "demo">My msg</p> <button type="button" onclick="myFun()">try it</button> <script type="text/javascript"> function myFun(){ document.write('output msg,then whole page will be overide') } </script> </body> </html> <!-- 你能夠在文本字符串中使用反斜槓對代碼行進行換行。--> <!DOCTYPE html> <html> <head> <title>html text</title> </head> <body> <script type="text/javascript"> document.write('hi \ jim') </script> </body> </html> <!-- 變量是存儲信息的容器 --> <!DOCTYPE html> <html> <head> <title>html</title> <script type="text/javascript"> function fun() { var num1 = 1; var num2 = 2; var num3 = num1 + num2; document.write(num3);//點擊try it按鈕,打出計算結果 3 } </script> </head> <body> <button type="button" onclick="fun()">try it</button> </body> </html> <!-- js建立數組 --> <!DOCTYPE html> <html> <head> <title>html</title> </head> <body> <script type="text/javascript"> var cars = new Array(); cars[0] = 'aodi'; cars[1] = 'baoma'; cars[2] = 'benchi'; for(var i = 0;i<cars.length;i++){ document.write(cars[i]+'<br/>') } </script> </body> </html> <!-- js建立對象而且獲取對象 --> <!DOCTYPE html> <html> <head> <title>html</title> </head> <body> <script type="text/javascript"> var cars = { 'name1':'baoma', 'name2':'aodi', 'name3':'dazhong' } document.write(cars.name1) </script> </body> </html>
1,語法
1.1 空格
var that = this;
var 和that之間的空白不能移除,可是其餘的空格都是能夠移除的。
註釋
js的註釋有兩種方法:/ / 和//
/ var rm_a = /a/.match(s) */就會致使錯誤,因此通常註釋用//.
1.2 標識符
標識符有一個字母開頭,能夠選擇性的加上一個或是多個字母,數字或下劃線,可是不能使用下面的保留字
abstract,boolean,break,byte,case,catch,char,class,const,continue,debugger,default,delete,do,double,else,enum,export,extends,false,final,finally,float,for,function,goto,if,implements,import,in,instanceof,int,interface,long,native,new,null,package,private,protected,public,return,short,static,super,switch,synchronized,this,throw,thransient,true,try,typeof,while,with
2,對象
js中,對象是可變的鍵控集合(keyed collections),在js中,數組是對象,函數是對象,正則表達式是對象。
對象字面量:對象字面量提供了一種很是方便的建立新對象值的表達法,一個對象字面量就是包圍在一對花括號中的零或多個"鍵/值"對。
var name = { "name1":"mike", "name2":"mike2" }
對象也能夠嵌套使用:
var flight = { airline:"oceanic", number:125, departure:{ city:"beijing", time:"2015/01/05" }, arrival:{ city:"amrica", time:"2015/01/06" } }
2.1 對象的檢索
檢索對象中包含的值,能夠採用在[]後綴中括住一個字符串表達式。
name["name1"] //mike1 flight.arrival.city //amrica
2.2屬性值更新
name["name1"] = "Jet li"
2.3引用傳遞對象
對象經過引用來傳遞
var = {},b = {},c = {}//a,b,c 都引用一個不一樣的空對象
a = b = c = {} //a b,c都引用同一個空對象
3.2 原型
http://www.crockford.com/java...
原型是一個對象,其餘對象能夠經過它實現屬性繼承。
每一個對象都鏈接到一個原型對象,而且他能夠從中能夠繼承屬性,原型鏈接在屬性更新的時候是不起做用的,原型鏈接只用在檢索的時候纔會被用到,若是咱們嘗試去獲取對象的某個屬性值,且該對象沒有此屬性值,那麼js會嘗試從原型對象上獲取,若是也沒找到,返回undefined,這個過程叫委託
typeof
typeof 運算符有一個參數,即要檢查的變量或值
var a = "str"; alert(typeof a);//string var a = 'str'; alert(typeof 123);// number
對變量或值調用 typeof 運算符將返回下列值之一:
undefined - 若是變量是 Undefined 類型的 boolean - 若是變量是 Boolean 類型的 number - 若是變量是 Number 類型的 string - 若是變量是 String 類型的 object - 若是變量是一種引用類型或 Null 類型的
爲何 typeof 運算符對於 null 值會返回 "Object"。這其實是 JavaScript 最初實現中的一個錯誤,而後被 ECMAScript 沿用了。如今,null 被認爲是對象的佔位符,從而解釋了這一矛盾,但從技術上來講,它仍然是原始值。
Undefined 類型
如前所述,Undefined 類型只有一個值,即 undefined。當聲明的變量未初始化時,該變量的默認值是 undefined。
var str; console.log(str==undefined)//true var str; console.log(typeof str)//undefined
Null 類型
另外一種只有一個值的類型是 Null,它只有一個專用值 null,即它的字面量。值 undefined 其實是從值 null 派生來的,所以 ECMAScript 把它們定義爲相等的。
var str = null; console.log(str==undefined)//true
儘管這兩個值相等,但它們的含義不一樣。undefined 是聲明瞭變量但未對其初始化時賦予該變量的值,null 則用於表示還沒有存在的對象(在討論 typeof 運算符時,簡單地介紹過這一點)。若是函數或方法要返回的是對象,那麼找不到該對象時,返回的一般是 null。
Boolean 類型
它有兩個值 true 和 false (即兩個 Boolean 字面量)。
即便 false 不等於 0,0 也能夠在必要時被轉換成 false,這樣在 Boolean 語句中使用二者都是安全的。
注意數值的表示法 var str = !0;console.log(str)//true var str = !1;console.log(str)//false
Number 類型
ECMA-262 中定義的最特殊的類型是 Number 類型。這種類型既能夠表示 32 位的整數,還能夠表示 64 位的浮點數。
直接輸入的(而不是從另外一個變量訪問的)任何數字都被看作 Number 類型的字面量。例如,下面的代碼聲明瞭存放整數值的變量,它的值由字面量 32 定義:
var num = 32;console.log(num)//32
JavaScript 擁有動態類型
JavaScript 擁有動態類型。這意味着相同的變量可用做不一樣的類型:
Undefined 和 Null
Undefined 這個值表示變量不含有值。
能夠經過將變量的值設置爲 null 來清空變量。
<!--能夠經過null來清空對象--> <!DOCTYPE html> <html> <head> <title>html</title> </head> <body> <script type="text/javascript"> var cars='baoma'; document.write(cars+'<br/>') cars = null; document.write(cars) alert(cars==undefined)//true </script> </body> </html>
聲明變量類型
當您聲明新變量時,可使用關鍵詞 "new" 來聲明其類型:
<!DOCTYPE html> <html> <!-- 聲明新變量時,可使用關鍵詞 "new" 來聲明其類型 --> <head> <title>html</title> </head> <body> <script type="text/javascript"> var str = new String; var bo = new Boolean; var num = new Number; var cars = new Array; var person = new Object; alert(typeof str) alert(typeof bo) alert(typeof num) alert(typeof cars) </script> </body> </html>
建立 JavaScript 對象
JavaScript 中的幾乎全部事務都是對象:字符串、數字、數組、日期、函數,等等。
對象(object)定義爲「屬性的無序集合,每一個屬性存放一個原始值、對象或函數」。嚴格來講,這意味着對象是無特定順序的值的數組。
面嚮對象語言的要求
一種面嚮對象語言須要向開發者提供四種基本能力:
封裝 - 把相關的信息(不管數據或方法)存儲在對象中的能力 彙集 - 把一個對象存儲在另外一個對象內的能力 繼承 - 由另外一個類(或多個類)得來類的屬性和方法的能力 多態 - 編寫能以多種方法運行的函數或方法的能力
對象由特性(attribute)構成,特性能夠是原始值,也能夠是引用值。若是特性存放的是函數,它將被看做對象的方法(method),不然該特性被看做對象的屬性(property)。
你也能夠建立本身的對象。
<!DOCTYPE html> <html> <!-- 建立 JavaScript 對象--> <head> <title>html</title> </head> <body> <script type="text/javascript"> var person= new Object(); person.name1='mike'; person.age=23; person.color1 = 'yellow'; document.write('A person named '+ person.name1+' is '+ person.age +' years old') </script> </body> </html>
訪問對象的屬性和方法
<!DOCTYPE html> <html> <!--訪問對象的屬性和方法--> <head> <title>html</title> </head> <body> <script type="text/javascript"> var str = 'Hellojs' document.write('Len: '+str.length+' <br/>Up: '+str.toUpperCase()) </script> </body> </html>
調用帶參數的函數
在調用函數時,您能夠向其傳遞值,這些值被稱爲參數。
變量和參數必須以一致的順序出現。第一個變量就是第一個被傳遞的參數的給定的值,以此類推。
<!DOCTYPE html> <html> <!--JavaScript 調用帶參數的函數--> <head> <title>html</title> <script type="text/javascript"> function fun(name,title){ alert(name+' is a great '+title) } </script> </head> <body> <button type = 'button' onclick="fun('bill','leader')">click</button> </body> </html>
帶有返回值的函數
在使用 return 語句時,函數會中止執行,並返回指定的值。
<!DOCTYPE html> <html> <!--JavaScript 調用帶參數的函數--> <head> <title>html</title> <script type="text/javascript"> function re(){ var num = 4; return num; } // return 返回4 function fun(){ document.getElementById('demo').innerHTML=re() } </script> </head> <body> <p id="demo">Here is the content will be changed</p> <button type = 'button' onclick="fun()">click</button> </body> </html>
局部 JavaScript 變量
在 JavaScript 函數內部聲明的變量(使用 var)是局部變量,因此只能在函數內部訪問它。(該變量的做用域是局部的)。
能夠在不一樣的函數中使用名稱相同的局部變量,由於只有聲明過該變量的函數才能識別出該變量。
只要函數運行完畢,本地變量就會被刪除。
全局 JavaScript 變量
在函數外聲明的變量是全局變量,網頁上的全部腳本和函數都能訪問它。
向未聲明的 JavaScript 變量來分配值
若是把值賦給還沒有聲明的變量,該變量將被自動做爲全局變量聲明。
將聲明一個全局變量,即便它在函數內執行。
函數支持閉包
函數支持閉包,也便是說,函數可使用函數以外定義的變量。
<!DOCTYPE html> <html> <head> <title>html</title> </head> <body> <script type="text/javascript"> var say = 'hello world' function fun(){ alert(say) } fun() </script> <!-- 在上面這段代碼中,腳本被載入內存後,並無爲函數 fun() 計算變量 say 的值。該函數捕獲 say 的值只是爲了之後的使用,say 將在函數調用 fun() 時(最後一行)被賦值,顯示消息 "hello world"。--> </body> </html>
JavaScript 運算符
若是把數字與字符串相加,結果將成爲字符串。
逗號運算符
用逗號運算符能夠在一條語句中執行多個運算。經常使用在變量聲明中。
var iNum1 = 1, iNum = 2, iNum3 = 3;
JavaScript Switch 語句
<!DOCTYPE html> <html> <head> <title>html</title> </head> <body> <p id="demo"><p> <button type="button" onclick='fun()'>try it</button> <script type="text/javascript"> function fun(){ var str ='' var day = new Date().getDay(); switch(day)//注意day返回的是星期幾,也就是數字0-6 { case 1: str = 'today is mon' break case 2: str = 'today is Tus' break case 3: str = 'today is wens' break case 4: str = 'today is thus' break case 5: str = 'today is fri' break case 6: str = 'today is sat' break case 7: str = 'today is sun' break default: str='expecting weekends' } document.getElementById('demo').innerHTML=str; } </script> </body> </html>
for循環
<!DOCTYPE html> <html> <head> <title>html</title> <!-- javascript 遍歷對象屬性 --> </head> <body> <p id="demo"><p> <button type="button" onclick='fun()'>try it</button> <script type="text/javascript"> var i; var txt = '' function fun(){ var person = {'name':'bill','age':'23','cookie':'true','single':'true'} for(i in person){ txt+=i+'<br/>' } document.getElementById('demo').innerHTML=txt; } </script> </body> </html>
do/while
<!DOCTYPE html> <html> <head> <title>html</title> <!-- javascript do/while --> </head> <body> <p id="demo"><p> <button type="button" onclick='fun()'>try it</button> <script type="text/javascript"> var i = 0; var txt = ''; function fun(){ do { txt+= 'js running the '+i+'times'+'<br/>' i++ } while(i < 5) document.getElementById('demo').innerHTML = txt; } </script> </body> </html>
while 遍歷數組
<!DOCTYPE html> <html> <head> <title>html</title> <!-- javascript do/while 遍歷數組 --> </head> <body> <p id="demo"><p> <script type="text/javascript"> var i = 0; var cars = ['baoma','benchi','qq','aodi'] while(cars[i]){ document.write(cars[i]+'<br/>') i++ } </script> </body> </html>
try/catch
<!DOCTYPE html> <html> <head> <title>html</title> </head> <body> <script> function myFunc() { try { var x = document.getElementById('inputName').value; if (x == '') throw 'the input number should not be empty'; if (isNaN(x)) throw 'the input content should be number'; if (x < 5) throw 'the number was too small'; if (x > 10) throw 'the number was too large'; } catch (err) { var y = document.getElementById('miss'); y.innerHTML = 'error ' + err; } } </script> <input type="text" id='inputName'> <button type='button' onclick='myFunc()'>click</button> <p id='miss'></p> </body> </html>
經過標籤名查找 HTML 元素
getElementsByTagName
<!DOCTYPE html> <html> <head> <title>html</title> </head> <body> <div id = 'main'> <span>this is the first doc</span> <p>this is the second doc</p> <p>this is the third doc</p> </div> <script> var x = document.getElementById('main'); var y = x.getElementsByTagName('p'); document.write('The first doc is '+y[0].innerHTML) </script> </body> </html>
改變 HTML 內容
修改 HTML 內容的最簡單的方法時使用 innerHTML 屬性。
<!DOCTYPE html> <html> <head> <title>html</title> </head> <body> <p id='main'>this is the first doc</p> <script> document.getElementById('main').innerHTML='angularjs' </script> </body> </html>
改變 HTML 樣式
如需改變 HTML 元素的樣式,請使用這個語法:
<!DOCTYPE html> <html> <head> <title>html</title> </head> <body> <p id='main'>this is the first doc</p> <script> document.getElementById('main').style.color='red' </script> </body> </html>
點擊更改html
<!DOCTYPE html> <html> <head> <title>html</title> </head> <body> <p onclick="this.innerHTML='Thank you'">please click it</p> </body> </html> <!DOCTYPE html> <html> <head> <title>html</title> </head> <body> <script> function func(id){ id.innerHTML='Thank you!' } </script> <p onclick="func(this)">please click it</p> </body> </html>
打印系統時間
<!DOCTYPE html> <html> <head> <title>html</title> </head> <body> <p id='demo'></p> <script> function func(){ document.getElementById('demo').innerHTML= Date(); } </script> <button type='button' onclick="func()">please click it</p> </body> </html> button和點擊分離 <!DOCTYPE html> <html> <!-- 能夠將點擊按鈕分離 --> <head> <title>html</title> </head> <body> <button id='btm'>click here</button> <script> document.getElementById("btm").onclick = function() { displayDate() } function displayDate() { document.getElementById("demo").innerHTML = Date() } </script> <p id="demo"></p> </body> </html>
onload事件
<!DOCTYPE html> <html> <!-- onload 事件檢查cookie是否開啓 --> <head> <title>html</title> </head> <body onload="checkCookies()"> <script type="text/javascript"> function checkCookies(){ if(navigator.cookieEnabled==true){ alert('cook enabled') }else{ alert('cookie down') } } </script> </body> </html>
onchange事件,點擊離開,輸入內容大寫
<!DOCTYPE html> <html> <!-- onchange事件點擊離開,輸入的英文變大寫 --> <head> <title>html</title> </head> <body> <script type="text/javascript"> function func(){ var x = document.getElementById('demo'); return x.value = x.value.toUpperCase() } </script> <input type="text" id="demo" onchange="func()"> </body> </html>
mouseover/mouseout
<!DOCTYPE html> <html> <!-- onmouseout onmouseover事件點擊離開,更改樣式 --> <head> <title>html</title> </head> <body> <div onmouseover="mover(this)" onmouseout="mout(this)" style="background-color: green;height:100px;width:100px;text-align: center">what 's that</div> <script type="text/javascript"> function mover(obj){ obj.innerHTML='THANK YOU' } function mout(obj){ obj.innerHTML='LEAVE' } </script> </body> </html>
mouseup/mousedown
<!DOCTYPE html> <html> <!-- onmouseup onmousedown事件點擊離開,更改樣式 --> <head> <title>html</title> </head> <body> <div onmouseup="mover(this)" onmousedown="mout(this)" style="background-color: green;height:100px;width:100px;text-align: center"></div> <script type="text/javascript"> function mover(obj){ obj.innerHTML='please click mouse' obj.style.backgroundColor='red' } function mout(obj){ obj.innerHTML='please release your mouse' obj.style.backgroundColor='#ccc' } </script> </body> </html>
當輸入字段得到焦點時,會觸發改變背景顏色的函數。
<!DOCTYPE html> <html> <!-- onfocus 當輸入字段得到焦點時,會觸發改變背景顏色的函數。--> <head> <title>html</title> </head> <body> <script type="text/javascript"> function func(obj){ // return obj.style.backgroundColor = 'yellow' obj.style.background='red'//使用這兩種方式均可以 } </script> <input type="text" onfocus="func(this)"> </body> </html>
建立新的 HTML 元素
如需向 HTML DOM 添加新元素,你必須首先建立該元素(元素節點),而後向一個已存在的元素追加該元素。
<!DOCTYPE html> <html> <head> <title>html</title> </head> <body> <div id='main'> <p id='p1'>the second para</p> <p id='p2'>the second para</p> </div> <script type="text/javascript"> var p = document.createElement('p3') var node = document.createTextNode('This is something new') p.appendChild(node) var e2 = document.getElementById('main') e2.appendChild(p) </script> </body> </html>
刪除已有的 HTML 元素
如需刪除 HTML 元素,你必須首先得到該元素的父元素
<!DOCTYPE html> <html> <head> <title>html</title> </head> <body> <div id='main'> <p id='p1'>the first para</p> <p id='p2'>the second para</p> <p id='p3'>the third para</p> </div> <script type="text/javascript"> var a1 = document.getElementById('main'); var a2 = document.getElementById('p1') a1.removeChild(a2) </script> </body> </html>
javascript 面對對象
使用預約義對象只是面嚮對象語言的能力的一部分,它真正強大之處在於可以建立本身專用的類和對象。
工廠方式
原始方式
<!DOCTYPE html> <html> <head> <title>html</title> </head> <body> <script type="text/javascript"> var person = new Object(); person.color = 'yellow'; person.hight = 230; person.hands = 2; //最後一個屬性其實是指向函數的指針,意味着該屬性是個方法。執行這段代碼後,就可使用對象 car。 person.action = function(){ document.write(this.color); } person.action(); </script> </body> </html>
工廠模式
<!DOCTYPE html> <html> <head> <title>html</title> </head> <body> <script type="text/javascript"> function createPerson(){ var person = new Object(); person.color = 'yellow'; person.hight = 230; person.hands = 2; person.action = function(){ document.write(this.color); } return person; } var person1 = createPerson(); var person2 = createPerson(); person1.action(); document.write('<br>') person2.action(); </script> </body> </html> 返回 person 對象(person)做爲函數值。調用此函數,將建立新對象,並賦予它全部必要的屬性,複製出一個咱們在前面說明過的 person 對象。所以,經過這種方法,咱們能夠很容易地建立 person 對象的兩個版本(person1 和 person2),它們的屬性徹底同樣。
工廠模式傳遞參數
<!DOCTYPE html> <html> <!--給工廠模式傳遞參數--> <head> <title>html</title> </head> <body> <script type="text/javascript"> function createPerson(skinColor,phsiHight,hanNum){ var person = new Object(); person.color = skinColor; person.hight = phsiHight; person.hands = hanNum; person.action = function(){ document.write(this.color); } return person; } var person1 = createPerson('yellow',100,2); var person2 = createPerson('black',130,2); person1.action(); document.write('<br>') person2.action(); </script> </body> </html> 給 createPerson() 函數加上參數,便可爲要建立的 person 對象的 skinColor、phsiHight 和 hanNum 屬性賦值。這使兩個對象具備相同的屬性,卻有不一樣的屬性值
將函數方法定義在工廠函數外面
<!DOCTYPE html> <html> <!--在工廠函數外定義對象的方法--> <head> <title>html</title> </head> <body> <script type="text/javascript"> function action(){ document.write(this.color) } function createPerson(skinColor,phsiHight,hanNum){ var person = new Object(); person.color = skinColor; person.hight = phsiHight; person.hands = hanNum; person.action = this.action; return person; } var person1 = createPerson('yellow',100,2); var person2 = createPerson('black',130,2); person1.action(); document.write('<br>') person2.action(); </script> </body> </html> <!-- 每次調用函數 createPerson(),都要建立新函數 action(),意味着每一個對象都有本身的 action() 版本。而事實上,每一個對象都共享同一個函數。 -->
構造函數方法
<!DOCTYPE html> <html> <!--構造函數方法--> <head> <title>html</title> </head> <body> <script type="text/javascript"> function Person(skinColor, phsiHight, hanNum) { this.color = skinColor; this.hight = phsiHight; this.hands = hanNum; this.action = function() { document.write(this.color) } } var person1 = new Person('yellow', 100, 2); var person2 = new Person('black', 130, 2); person1.action(); document.write('<br>') person2.action(); </script> </body> </html>
構造函數方法與工廠方式的差異。
首先在構造函數內沒有建立對象,而是使用 this 關鍵字。使用 new 運算符構造函數時,在執行第一行代碼前先建立一個對象,只有用 this 才能訪問該對象。而後能夠直接賦予 this 屬性,默認狀況下是構造函數的返回值(沒必要明確使用 return 運算符)。
如今,用 new 運算符和類名 Person 建立對象,就更像 ECMAScript 中通常對象的建立方式了。
就像工廠函數,構造函數會重複生成函數,爲每一個對象都建立獨立的函數版本。不過,與工廠函數類似,也能夠用外部函數重寫構造函數,一樣地,這麼作語義上無任何意義。這正是下面要講的原型方式的優點所在。
原型方式
<!DOCTYPE html> <html> <!--原型方式--> <head> <title>html</title> </head> <body> <script type="text/javascript"> function Person(){//該方式利用了對象的 prototype 屬性,能夠把它當作建立新對象所依賴的原型。 //這裏,首先用空構造函數來設置類名。而後全部的屬性和方法都被直接賦予 prototype 屬性。 } //經過給 Car 的 prototype 屬性添加屬性去定義 Car 對象的屬性。 Person.prototype.color = 'yellow'; Person.prototype.hight = 100; Person.prototype.hands = 2; Person.prototype.action = function() { document.write(this.color) } //調用 new Person() 時,原型的全部屬性都被當即賦予要建立的對象,意味着全部 Person 實例存放的都是指向 action() 函數的指針。從語義上講,全部屬性看起來都屬於一個對象,所以解決了前面兩種方式存在的問題。 var person1 = new Person(); var person2 = new Person(); person1.action(); document.write('<br>') person2.action(); </script> </body> </html>
混合的構造函數
<!DOCTYPE html> <html> <!--混合的構造函數--> <head> <title>html</title> </head> <body> <script type="text/javascript"> function Person(sinkColor,job,gender){ this.color = sinkColor; this.title = job; this.sex = gender; this.numbers = new Array('bill','mike') } Person.prototype.show = function(){ document.write(this.title) } var person1 = new Person('yellow','ceo','man'); var person2 = new Person('red','dev','femal'); person1.numbers.push('iven'); document.write(person1.numbers) document.write('<br>') document.write(person2.numbers) </script> </body> </html>
字符串拼接,資源消耗問題
var str = "hello "; str += "world";
實際上,這段代碼在幕後執行的步驟以下:
建立存儲 "hello " 的字符串。 建立存儲 "world" 的字符串。 建立存儲鏈接結果的字符串。 把 str 的當前內容複製到結果中。 把 "world" 複製到結果中。 更新 str,使它指向結果。
每次完成字符串鏈接都會執行步驟 2 到 6,使得這種操做很是消耗資源。若是重複這一過程幾百次,甚至幾千次,就會形成性能問題。解決方法是用 Array 對象存儲字符串,而後用 join() 方法(參數是空字符串)建立最後的字符串。想象用下面的代碼代替前面的代碼:
<!DOCTYPE html> <html> <head> <title>html</title> </head> <body> <script type="text/javascript"> var arr = new Array(); arr[0] = 'hello' arr[1] = 'world' var str = arr.join(',') document.write(str) </script> </body> </html>
這樣,不管數組中引入多少字符串都不成問題,由於只在調用 join() 方法時纔會發生鏈接操做。此時,執行的步驟以下:
建立存儲結果的字符串 把每一個字符串複製到結果中的合適位置
雖然這種解決方案很好,但還有更好的方法。問題是,這段代碼不能確切反映出它的意圖。要使它更容易理解,能夠用 StringBuffer 類打包該功能:
<!DOCTYPE html> <html> <head> <title>html</title> </head> <body> <script type="text/javascript"> function StringBuffer(){ this._s_ = new Array(); } StringBuffer.prototype.append = function(str){ this._s_.push(str) } StringBuffer.prototype.toString = function(){ return this._s_.join(","); } var buffer = new StringBuffer(); buffer.append('hello') buffer.append('world') var strs = buffer.toString() document.write(strs) </script> </body> </html>
這段代碼首先要注意的是 s 屬性,本意是私有屬性。它只有兩個方法,即 append() 和 toString() 方法。append() 方法有一個參數,它把該參數附加到字符串數組中,toString() 方法調用數組的 join 方法,返回真正鏈接成的字符串。要用 StringBuffer 對象鏈接一組字符串
<!DOCTYPE html> <html> <head> <!-- 建立 Date 對象時,若是沒有參數,賦予對象的是當前的日期和時間。要計算鏈接操做歷經多少時間,把日期的毫秒錶示(用 getTime() 方法的返回值)相減便可。這是衡量 JavaScript 性能的常見方法 --> <title>html</title> </head> <body> <script type="text/javascript"> var d1 = new Date(); function StringBuffer(){ this._s_ = new Array(); } StringBuffer.prototype.append = function(str){ this._s_.push(str) } StringBuffer.prototype.toString = function(){ return this._s_.join(","); } var buffer = new StringBuffer(); for(var i = 0;i<10000000;i++){ buffer.append('txt') } var strs = buffer.toString() var d2 = new Date(); document.write('<h1>buffer time:</h1>') document.write(d2.getTime()- d1.getTime()) for(var i = 0;i<10000000;i++){ var txt = txt + "txt"; } var d3 = new Date(); document.write('<h1>str time:</h1>') document.write(d3.getTime()-d2.getTime()); </script> </body> </html>
重命名已有的方法
能夠給已有的方法名更更名稱,好比能夠給 Array 類添加兩個方法 enq() 和 inq(),只讓它們反覆調用已有的 push() 和 shift() 方法便可:
shift() 方法用於把數組的第一個元素從其中刪除,並返回第一個元素的值。
<!DOCTYPE html> <html> <head> <title>html</title> </head> <body> <script type="text/javascript"> Array.prototype.enq = function(v1){ return this.push(v1) } Array.prototype.inq = function(){ //shift() 方法用於把數組的第一個元素從其中刪除,並返回第一個元素的值。 return this.shift(); } var arr = new Array(3); arr[0] = 'm1'; arr[1] = 'm2'; arr[2] = 'm3'; arr.enq('mike'); document.write(arr); document.write('<br>') arr.inq(); document.write(arr) </script> </body> </html>
創造方法
indexOf() 方法可返回某個指定的字符串值在字符串中首次出現的位置.可是Array沒有indexof方法,這裏能夠給Array建立一個indexof方法
<!DOCTYPE html> <html> <head> <title>html</title> </head> <body> <script type="text/javascript"> Array.prototype.indeof = function(v){ for(var i = 0;i<this.length;i++){ if(v==this[i]){ return i } } return -1; } var arr = new Array('m1','m2','m3'); var str = arr.indeof('m2') document.write(str) </script> </body> </html>
重定義已有方法
就像能給已有的類定義新方法同樣,也可重定義已有的方法。如前面的章節所述,函數名只是指向函數的指針,所以能夠輕鬆地指向其餘函數。
<!DOCTYPE html> <html> <head> <title>html</title> <!-- 重定義已有方法 --> </head> <body> <script type="text/javascript"> Function.prototype.toString = function(){//重定義toString方法,返回指定字符串 return'strings' } function sayHi(){ document.write('something') } document.write(sayHi.toString()) </script> </body> </html>
從新定義toString方法,可是保留它的原始指針
<!DOCTYPE html> <html> <head> <title>html</title> <!-- 重定義已有方法 Function 的 toString() 方法一般輸出的是函數的源代碼。覆蓋該方法,能夠返回另外一個字符串 不過,toString() 指向的原始函數怎麼了呢?它將被無用存儲單元回收程序回收,由於它被徹底廢棄了。沒有可以恢復原始函數的方法,因此在覆蓋原始方法前,比較安全的作法是存儲它的指針,以便之後的使用。有時你甚至可能在新方法中調用原始方法:--> </head> <body> <script type="text/javascript"> Function.prototype.originalToString = Function.prototype.toString;//這個表達式的意思是存儲它的指針 Function.prototype.toString = function(){ if(this.originalToString().length > 100){ return 'too long to display' }else{ return this.originalToString(); } } function sayHi(){ alert('something') } document.write(sayHi.toString()) </script> </body> </html>
javascript的繼承機制的實現
選定基類後,就能夠建立它的子類了。基類只是用於給子類提供通用的函數。在這種狀況下,基類被看做抽象類。
儘管 ECMAScript 並無像其餘語言那樣嚴格地定義抽象類,但有時它的確會建立一些不容許使用的類。一般,咱們稱這種類爲抽象類。
建立的子類將繼承超類的全部屬性和方法,包括構造函數及方法的實現。記住,全部屬性和方法都是公用的,所以子類可直接訪問這些方法。子類還可添加超類中沒有的新屬性和方法,也能夠覆蓋超類的屬性和方法。
繼承的方式
和其餘功能同樣,ECMAScript 實現繼承的方式不止一種。這是由於 JavaScript 中的繼承機制並非明確規定的,而是經過模仿實現的。這意味着全部的繼承細節並不是徹底由解釋程序處理。做爲開發者,你有權決定最適用的繼承方式。
1,對象冒充
它是在開發者開始理解函數的工做方式,尤爲是如何在函數環境中使用 this 關鍵字後才發展出來。
<html> <head> <title>Example</title> </head> <!-- 構造函數使用 this 關鍵字給全部屬性和方法賦值(即採用類聲明的構造函數方式)。由於構造函數只是一個函數,因此可以使 ClassA 構造函數成爲 ClassB 的方法,而後調用它。ClassB 就會收到 ClassA 的構造函數中定義的屬性和方法。例如,用下面的方式定義 ClassA 和 ClassB: --> <body> <script type="text/javascript"> function ClassA(sColor) { this.color = sColor; this.sayColor = function() { document.write(this.color) }; } function ClassB(Lor, sName) { this.newMethod = ClassA;//由於構造函數只是一個函數,因此可以使 一個構造函數成爲 另外一個函數的方法 this.newMethod(Lor); delete this.newMethod;//最後一行代碼刪除了對 ClassA 的引用,這樣之後就不能再調用它。 this.name = sName; this.sayName = function() { document.write(this.name) }; } var objA = new ClassA("blue"); var objB = new ClassB("red", "John"); objA.sayColor(); document.write('<br>') objB.sayColor(); document.write('<br>') objB.sayName(); </script> </body> </html>
對象冒充可實現多重繼承
UML
這裏存在一個弊端,若是存在兩個類 ClassX 和 ClassY 具備同名的屬性或方法,ClassY 具備高優先級。由於它從後面的類繼承。除這點小問題以外,用對象冒充實現多重繼承機制垂手可得。
因爲這種繼承方法的流行,ECMAScript 的第三版爲 Function 對象加入了兩個方法,即 call() 和 apply()。
Call() 方法
<html> <head> <title>Example</title> </head> <!-- 構造函數使用 this 關鍵字給全部屬性和方法賦值(即採用類聲明的構造函數方式)。由於構造函數只是一個函數,因此可以使 ClassA 構造函數成爲 ClassB 的方法,而後調用它。ClassB 就會收到 ClassA 的構造函數中定義的屬性和方法。例如,用下面的方式定義 ClassA 和 ClassB: --> <body> <script type="text/javascript"> function ClassA(sColor) { this.color = sColor; this.sayColor = function() { document.write(this.color) }; } function ClassB(Lor, sName) { //this.newMethod = ClassA; //this.newMethod(Lor); //delete this.newMethod; ClassA.call(this,Lor)//call() 方法是與經典的對象冒充方法最類似的方法。它的第一個參數用做 this 的對象。其餘參數都直接傳遞給函數自身。這裏的this等於建立了新的ClassB對象,Lor對於兩個類來講都是惟一的參數 this.name = sName; this.sayName = function() { document.write(this.name) }; } var objA = new ClassA("blue"); var objB = new ClassB("red", "John"); objA.sayColor(); document.write('<br>') objB.sayColor(); document.write('<br>') objB.sayName(); </script> </body> </html>
var pet = { words:'...', speak: function(say){ console.log(say+''+this.words); } } // pet.speak('speak') //speak ... // this 指的是調用這個方法的對象 pet // 狗有本身的話,可是沒有speak的方法 var dog = { words:'wang' } // pet原本指向的是speak方法,可是call改變了執行上下文,pet 的speak就指向了dog //dog 如今有了一個pet的技能 speak pet.speak.call(dog,'speak ')//speak wang
call 實現繼承 function pet (words) { this.words = words; this.speak = function(){ console.log(this.words) } } function dog(words){ pet.call(this,words)//dog 沒有speak方法,經過call(this) 繼承了pet的speak方法 //pet.apply(this,arry) apply和call的區別在於apply傳遞的是一個參數列表 } var dog = new dog('wang'); dog.speak();//wang
apply方法
<html> <head> <title>Example</title> </head> <body> <script type="text/javascript"> function ClassA(sColor) { this.color = sColor; this.sayColor = function() { document.write(this.color) }; } function ClassB(Lor, sName) { //this.newMethod = ClassA; //this.newMethod(Lor); //delete this.newMethod; ClassA.apply(this,arguments)//第一個參數還是 this,第二個參數是隻有一個值 Lor 的數組。能夠把 ClassB 的整個 arguments 對象做爲第二個參數傳遞給 apply() 方法: this.name = sName; this.sayName = function() { document.write(this.name) }; } var objA = new ClassA("blue"); var objB = new ClassB("red", "John"); objA.sayColor(); document.write('<br>') objB.sayColor(); document.write('<br>') objB.sayName(); </script> </body> </html> //固然,只有超類中的參數順序與子類中的參數順序徹底一致時才能夠傳遞參數對象。若是不是,就必須建立一個單獨的數組,按照正確的順序放置參數。
call(),apply(),bind()的區別
<!DOCTYPE html> <html> <!-- 改變執行上下文,call, apply,bind, call 方法可將一個函數的對象上下文從初始的(初始值)上下文改變爲由 thisObj 指定的新對象。 若是沒有提供 thisObj 參數,那麼 Global 對象被用做 thisObj。同apply相似,惟一區別是: apply()把參數打包成Array再傳入; call()把參數按順序傳入。--> <body> <script type="text/javascript"> var obj = { log: function() { alert(this.foo); }, foo: 'foo' }; var temp = { foo:'bar' }; obj.log.bind(temp)();//bar obj.log.apply(temp);//bar obj.log.call(temp);//bar </script> </body> </html>
好比,在舉一個例子: <!DOCTYPE html> <html> <!-- 在JS中,這三者都是用來改變函數的this對象的指向的,他們有什麼樣的區別呢。 在說區別以前仍是先總結一下三者的類似之處: 一、都是用來改變函數的this對象的指向的。 二、第一個參數都是this要指向的對象。 三、均可以利用後續參數傳參。 --> <head> <title>比較apply,call,bind的區別</title> </head> <body> <script type="text/javascript"> var o ={ name:'mike', age:'20', say: function(){ alert(this.name+' this year '+this.age+' years old') } } var b = { name:'mk', age:'21' } o.say() </script> </body> </html> 這段代碼打印出來的確定是mike this year 20 years old
<!DOCTYPE html> <html> <!-- 那麼如何用 o 的say方法來顯示 b 的數據呢。這是就須要調用call,apply,bind --> <head> <title>比較apply,call,bind的區別</title> </head> <body> <script type="text/javascript"> var o ={ name:'o data', age:'20', say: function(){ alert(this.name+' this year '+this.age+' years old') } } var b = { name:'b data', age:'21' } // o.say() alert('will display call b data') o.say.call(b) alert('will dispaly apply b data') o.say.apply(b) alert('will display bind b data') o.say.bind(b)() </script> </body> </html>
<!DOCTYPE html> <html> <!-- call,apply直接調用,bind方法返回的仍然是一個函數,所以後面還須要()來進行調用才能夠。 call後面的參數與say方法中是一一對應的,而apply的第二個參數是一個數組,數組中的元素是和say方法中一一對應的,這就是二者最大的區別。 可是因爲bind返回的仍然是一個函數,因此咱們還能夠在調用的時候再進行傳參。--> <head> <title>比較apply,call,bind的區別</title> </head> <body> <script type="text/javascript"> var object1 ={ name:"object1 data", age:"20", say: function(gender,job){ alert(this.name+" this year " + this.age +" years old "+ gender+ " in microsoft, as a/an "+ job) } } var object2 = { name:"object2 data", age:"21" } // o.say() alert('will display call object2 data'); object1.say.call(object2,"female","developer"); alert('will dispaly apply object2 data'); object1.say.apply(object2,["male","Technical Leader"]); alert('will display bind object2 data'); object1.say.bind(object2)("female","CEO"); </script> </body> </html>
原型鏈繼承
<html> <head> <title>Example</title> <!-- prototype 對象是個模板,要實例化的對象都以這個模板爲基礎。總而言之,prototype 對象的任何屬性和方法都被傳遞給那個類的全部實例。原型鏈利用這種功能來實現繼承機制。 --> </head> <body> <script type="text/javascript"> function ClassA() { } ClassA.prototype.color = 'red'; ClassA.prototype.sayColor = function() { document.write(this.color) } function ClassB() { } ClassB.prototype = new ClassA();//把 ClassB 的 prototype 屬性設置成 ClassA 的實例。 //調用 ClassA 的構造函數,沒有給它傳遞參數。這在原型鏈中是標準作法。要確保構造函數沒有任何參數。 ClassB.prototype.name = 'mike' ClassB.prototype.sayName = function() { document.write(this.name) } var objA = new ClassA(); var objB = new ClassB(); objA.color = 'red' objB.name = 'john' objB.color = 'green' objA.sayColor() objB.sayColor() objB.sayName() </script> </body> </html>
混合繼承機制
<html> <head> <title>Example</title> </head> <body> <script type="text/javascript"> function ClassA(sColor) { this.color = sColor; } ClassA.prototype.sayColor = function() { alert(this.color); }; function ClassB(sColor, sName) { ClassA.call(this, sColor);//call()繼承機制 this.name = sName; } ClassB.prototype = new ClassA();//原型鏈繼承機制 ClassB.prototype.sayName = function() { alert(this.name); }; var objA = new ClassA("blue"); var objB = new ClassB("red", "John"); objA.sayColor(); objB.sayColor(); objB.sayName(); </script> </body> </html>
javasript中須要注意的一些問題
var obj = {name:'michael',age:'23',gender:'male'} var txt = '' for(var i in obj){//這裏能夠不加 var,直接寫‘i’可是會把i 作爲全局的變量 window.i txt +=obj[i]//obj是一個對象,可是能夠這樣寫 obj[i],由於集合也是對象。 } console.log(txt)//michael23male
javascript頁面加載刷新就會自動執行部分腳本,請看下面demo
<ul> <li>click me</li> <li>click me</li> <li>click me</li> <li>click me</li> </ul> var eles = document.getElementsByTagName('li') var len = eles.length; for(var i = 0;i<len;i++){ eles[i].onclick = function(){ console.log(i)// 4 4 4 4 } } 頁面加載後會自動把腳本部分執行,執行完腳本,i=4. 當點擊li觸發onclick事件 此時的i早已經是4
javascript 2種截取字符串的方法 substr 和 slice
var date = '2016-01-05' date.slice(0,7) date.substr(0,7)