初識 javascript 1、JS組成:ECMA BOM DOM (1)是一種基於 對象模型 和 事件 的腳本語言 (2)組成: ECMAScript由ECMA-262定義,提供核心語言功能; 文檔對象模型(DOM),提供訪問和操作網頁內容的方法和介面; 瀏覽器對象模型(BOM),提供與瀏覽器交互 ...
初識 javascript
1、JS組成:ECMA BOM DOM
(1)是一種基於 對象模型 和 事件 的腳本語言
(2)組成:
- ECMAScript由ECMA-262定義,提供核心語言功能;
- 文檔對象模型(DOM),提供訪問和操作網頁內容的方法和介面;
- 瀏覽器對象模型(BOM),提供與瀏覽器交互的方法和介面;
2、html 中使用 javascript
- html是從上往下瀑布式載入,<script>包裹的 js 代碼也是從上往下依次載入的;
- 一般應該把<script>元素放在頁面最後,越晚載入越好,有利於提升網頁的載入速度;
基本概念
1、js 的基本特點
- 區分大小寫;
- 標識符字母、數字、下劃線和美元符組成,數字不能開頭;
- 單行和多行註和 java 一樣;
- 語句的分號不是必須的,但是最好寫一下;
2、變數
(1)變數的基本特點:弱類型;可連續聲明和賦值;
(2)數據類型:undefined、null、string、number、boolean、object
(3)typeof 運算符(單目運算符):不是函數;可以用來判斷 function;function 是一個特殊的對象;
3、基本數據類型
(1)Undefined:
- undefined 的引入是為了區分空對象(null)和未初始化的變數的(undefined);
- undefined 不需要顯示聲明;
- 未聲明變數用 typeof 判斷結果也是 undefined;
(2)Null:可以理解為一個特殊的空對象;null==undefined 判斷結果為 true;
(3)Boolean:
- true 和 false 並不等同於 0 和 1;
- 其他的數據類型通過Boolean()函數可以轉換為 boolean 值:空串、0、NAN、null、undefined 都為 false;
- if 判斷中的變數會自動轉換為 boolean;
(4)Number:
1、進位:070(八進位)、0xAF(16進位);
2、浮點數:浮點數值計算會產生舍入誤差的問題(很多語言中都存在)
var a=0.1; var b=0.2; console.log(a+b)//0.30000000000000004
3、數值範圍:最小值(Number.MIN_VALUE) 、最大值(Number.MAX_VALUE)
4、關於NAN:nan不等於nan;可以用 isNaN()函數判斷(這個函數會試圖將其中的參數轉換為number,不能轉換則結果為 true);
5、轉換為數值:
(1)Number():支持十六進位;
(2)parseInt(str,rule):rule 參數可以指定進位;預設支持八進位和十六進位的解析;
(3)parseFloat():解析都是按十進位來的;
(4)空串、null 和 undefined:Number函數的結果是(0、0、nan);parseFloat 和 parseInt 都是 nan;
(5)String:
1、基本特點
(1)字元串實質是字元序列;
(2)字元串一旦創建,它們的值就不能改變,要改變某個變數保存的字元串,首先要銷毀原來的字元串,然後再用另一個包含新值的字元串填充該變數;
2、轉為String:
(1)tar + "";
(2)tar.toString(2):可以實現進位的轉換;null 和 undefined 不能用;
(3)String(tar):null 和 undefined 也可以;
(6)Object:
- 概念就像Java中的java.lang.Object對象一樣;
- BOM和DOM中的對象由宿主實現提供,不一定會繼承 js 中的 Object;
- object 使用字面量表示法(json),不會調用構造函數;
(7)其他說明:
- 閉包的概念:子函數可以使用父函數的局部變數;
4、變數補充
(1)基本類型
- 保存在棧中;複製值的副本;
- 可以用 typeof 區分類型;函數傳參是按值傳遞;
(2)引用類型
- 值為對象保存在堆中;複製的時候複製的是指針;
- 用 instanceof 區分具體類型;函數傳參是按值傳遞(傳遞的是引用的副本);
- 對象可以動態添加屬性;
(3)作用域(執行環境)
- 全局變數(全局執行環境)
- 局部變數(函數執行環境)
- 作用域鏈:搜索變數和函數就近原則,從里往外找,找到就停止;裡面的能訪問外面的,外面的不能訪問裡面的;
(4)記憶體問題(垃圾回收)
- js 自動垃圾回收機制基於標記清除法(基於變數的作用域);
- 另外一種回收機制是引用計數法,用的少,因為相互引用會導致無法垃圾回收引發記憶體泄漏;
- 解除變數的引用有利於垃圾回收:全局變數、全局變數屬性和迴圈引用在不用的時候最好及時解除引用(null);
(5)關於 try---catch 和 with 語句
- catch塊中會匹配錯誤對象的屬性;
- with:裡面的href 會首先去匹配 location 的屬性
(6)關於 if 和 for:js沒有塊級作用域
4、運算符 | 流程式控制制 | JSON
(1)運算符
- 由於相等(==)和不相等(!=)操作符存在類型轉換問題,而為了保持代碼中數據類型的完整性,我們推薦使用全等(===)和不全等(!==)操作符;
- 三目運算符:(condition?value1:value2)
(3)流程式控制制:
- if、switch、
- for、for-in、
- while、do-while(break和continue)
- 說明:
- 1、基本和java一樣的用法;
- 2、迴圈也支持 label:statement 方式的命名,以便在break等中使用;
- 3、switch語句在比較值時使用的是全等操作符,因此不會發生類型轉換;
- 4、for(var i in json)來進行遍歷對象的屬性(json 可以理解為 js 對象的簡化表示);
引用類型
1、Object
2、數組(Array)
(1)特點:
- 1、Array 的length 屬性既可以獲取也可以設置;
- 2、可以保存不同類型的值,大小也可以動態調整;
- 3、包含 index 和 length,index的最大值是length-1;偽數組也有;
var arr = [1,2];
arr[arr.length] = 3;
arr[arr.length] = 4;
arr[10] = 10;
console.log(arr.length);
console.log(arr[8]);
(2)數組檢測:
- value instanceof Array:包含多個框架(多個全局環境的時候會有問題)
- Array.isArray(value):忽略執行環境,但是一些瀏覽器不支持?
(3)常用方法:
- 轉換方法:
- 1、數組繼承的toLocaleString()、toString()和valueOf()方法,在預設情況下都會以逗號分隔的字元串的形式返回數組項;
- 2、join():元素連接成字元串,指定分隔符;
- 棧方法:
- 1、push()和 pop()方法;
- 2、註意 push 方法會返回操作後的數組的長度;
- 隊列方法:
- 1、push 和 shift 方法一對,pop 和 unshift 一對可以實現隊列;
- 2、其中 unshift 也是返回數組的長度;
- 重排序方法:
- 1、reverse 和 sort 方法;
- 2、sort 方法預設是比較字元串,想要比較數值和其他數據類型的大小,要用到比較函數(傳參);
- 3、比較函數如下:上為通用的比較函數,下為數值類型的比較函數
- 操作方法:
- 1、concat:數組的連接;
- 2、slice(begin,end):切片;
- 3、splice:可以插入、刪除和替換:splice(起點,刪除長度,添加的數據);此方法返回被刪除的數組;
- 位置方法:
- 1、indexOf() 和 lastIndexOf();
- 2、沒找到返回 -1;使用全等(===);
- 3、兩個參數的情況:第二個參數是指定查找的起始 index
var numbers = [1,2,3,4,5,4,3,2,1];
console.log(numbers.indexOf(4, 6));
console.log(numbers.lastIndexOf(4, 6));
- 迭代方法:
- 1、every 和 some:返回值是 true 和 false;every 全部元素滿足條件則返回true,some一個滿足就返回 true;
- 2、filter:返會一個數組由滿足條件的元素組成;
- 3、map 和 forEach:map 返回一個數組;forEach沒有返回值;
- 4、每個方法都接收兩個參數:要在每一項上運行的函數和運行該函數的作用域對象(可選的);其中函數參數都包含item、index、array 這三個參數;
- 歸併方法:每一次迭代可以從參數里取到上一次返回的值
- 1、reduce() 和 reduceRight()
- 2、可以執行數組求和:
var values = [1,2,3,4,5];
var sum = values.reduce(function(prev, cur, index, array){
return prev + cur;
},10);
console.log(sum); //15 + 10 = 25
3、時間(Date)
(1)構造函數和三個方法
var now = new Date(); //裡面不傳參數獲取當前時間,也可以參一個毫秒值
var someDate1 = new Date(Date.parse("May 25, 2004"));
var someDate2 = new Date("May 25, 2004");
var allFives1 = new Date(Date.UTC(2005, 4, 5, 17, 55, 55));
var allFives2 = new Date(2005, 4, 5, 17, 55, 55);
var start = Date.now(); //獲取當前時間的毫秒值
(2)繼承方法
- toLocaleString()、toString()、valueOf()
- 兩個 String 方法因瀏覽器不同輸出不同;valueOf 返回日期的毫秒錶示(getTime方法也是);
(3)格式化方法
(4)組件方法
- 獲取時分秒:getHours()、getMinutes()、getSeconds()
- 獲取年月日:getFullYear()、getMonth()+1、getDate()、getDay()---星期
4、正則(RegExp)
(1)字面量和構造函數
var pattern1 = /at/g;
var pattern2 = new RegExp("[bc]at", "i");
- 後面的匹配模式:g(全局匹配)、i(忽略大小寫)、m(多行模式);
- 二者的差異:
- 1、字面量的元字元轉義只要一個 \ 而構造函數要 \\
- 2、下麵的例子中字面量只有一個對象,構造函數生成多個對象(實際測試大部分瀏覽器字面量也是每次創建新實例)
var re = null, i;
for (i=0; i < 10; i++){
re = /cat/g;
console.log(re.test("catastrophe")+Math.random());
}
for (i=0; i < 10; i++){
re = new RegExp("cat", "g");
console.log(re.test("catastrophe"));;
}
(2)實例屬性
var pattern1 = /\[bc\]at/i;
alert(pattern1.global); //false
alert(pattern1.ignoreCase); //true
alert(pattern1.multiline); //false
alert(pattern1.lastIndex); //0
alert(pattern1.source); //"\[bc\]at"
- source屬性保存的是字面量形式所用的字元串;
(3)實例方法
var text = "mom and dad and baby";
var pattern = /mom( and dad( and baby)?)?/gi;
var matches = pattern.exec(text);
alert(matches.index); // 0
alert(matches.input); // "mom and dad and baby"
alert(matches[0]); // "mom and dad and baby"
alert(matches[1]); // " and dad and baby"
alert(matches[2]); // " and baby"
- exec 方法返回的是數組,其中含兩個額外屬性,index 表示匹配項在字元串中的位置,input表示測試的字元串;
- 模式中設置了全局標誌(g),每次也只會返回一個匹配項;
- 沒有(g),在同一個字元串上多次調用exec()將始終返回第一個匹配項的信息;
- 有(g),每次調用exec()則都會在字元串中繼續查找新匹配項;
- 在全局匹配模式下,lastIndex的值在每次調用exec()後都會增加,而在非全局模式下則始終保持不變;
- 另外一個 test()方法返回 true 或 false;
(4)構造函數屬性
var text = "this has been a short summer";
var pattern = /(.)hort/g;
if (pattern.test(text)){
alert(RegExp.input); // this has been a short summer
alert(RegExp.leftContext); // this has been a
alert(RegExp.rightContext); // summer
alert(RegExp.lastMatch); // short
alert(RegExp.lastParen); // s
alert(RegExp.multiline); // false IE不支持
}
- RegExp.$1、RegExp.$2...RegExp.$9,分別用於存儲第一、第二......第九個匹配的捕獲組;
(5)模式局限性
補充:正則表達式
(1)基礎
- 常用字元串操作:search、substring、charAt、split
- 練習:找出字元串中的數字(兩種方法)
- 概念:正則是一種規則,用來匹配字元串
- RegExp對象:new RegExp(re,'i'); /re/ ;
(2)正則和字元串配合
- search:返回位置
- match:返回匹配的
- replace:返回替換後的
- re.test:
(3)正則分解
- 全局規則:i(忽略大小寫)g(全部匹配);
- 方括弧:[abc] [a-z] [a-z0-9] [^a]
- 轉義字元:點(.)表示匹配所有字元;\d、\w、\s、\D、\W、\S
- 量詞:{n,m} {n,} {n} + *(儘量不用) ?
- 頭尾匹配:^ $
(4)常用正則練習
- 郵箱電話匹配
5、函數(funtion)
(1)函數參數(聲明、調用和返回略)
- arguments(可變參):偽數組(有 index 和 length),存的傳入的參數,可以用for 遍歷;
- 函數的參數在聲明的時候寫不寫都可以,寫多少個也沒有規定,底層是用數組實現的,函數聲明的括弧里寫上形參只是為了函數內部使用的方便;函數在調用的時候要傳幾個實參都是可以的,反正是傳幾個接受幾個;
- 由於 js 函數參數的以上特點,所以 js 的函數沒有真正意義上的重載;
- 函數的參數最好的做法是對那些必需值使用命名參數,而使用對象字面量(json)來封裝多個可選參數;
(2)function 類型
function sum (num1, num2) {
return num1 + num2;
} //函數聲明
var sum = function(num1, num2){
return num1 + num2;
}; //函數表達式
- 函數是對象,函數名是指針;
- 由於 js 函數參數的特殊性,js 是沒有方法重載的,同名函數是覆蓋的效果;
- 函數聲明隨意寫在什麼位置都不影響函數的調用,但是函數表達式必須寫在調用之前才不會出錯;
DOM應用
1、dom基礎
(1)dom 節點:
- 父節點的獲取:parentNode、offsetParent(獲取有定位的父節點);
- 子節點的獲取:childNodes和nodeType(也可以用children);
- 首尾子節點:firstChild(firstElementChild 不會獲取到文本節點,IE9以下不可用)、lastChild(lastElementChild);
- 兄弟子節點:nextSibling(nextElementSibling)、previousSibling(previousElementSibling);
(2) 元素的屬性操作:
- obj.value(不可以傳參) 和 obj["value"](可以傳參)
- setAttribute | getAttribute | removeAttribute
- 屬性相關:
- 1、屬性基本 html 怎麼寫 js 就怎麼寫,除了 class 外:div.className=" ";
- 2、style 屬性無論是增加還是獲取都是取行間,行間沒有的話,取值的時候取不到;
- 3、style 的優先順序高於 className;
- 4、獲取非行間樣式的相容性寫法:
function getStyle(obj, attr) {
if(obj.currentStyle){
return obj.currentStyle[attr];
}else{
return getComputedStyle(obj,null)[attr];
}
}
(3)dom元素靈活查找:
- 用 className 來獲取元素,封裝函數 getByClass(oParent,sClass)
(4)創建、插入和刪除元素
- createElement | appendChild(加在末尾,也是先刪後加)| insertBefore(節點,指定節點)--加在前面;
- removeChild()
(5)文檔碎片(*):createDocumentFragment----幾乎不用
2、dom高級
(1)表格應用
- 表格的便捷操作:tHead、tFoot、tBodies、rows、cells;
- 表格的隔行變色;
- 添加和刪除一行;
- 搜索和排序;
(2)表單應用
- 事件:onsubmit、onreset;
- 表單的驗證;
JS運動技術
1、運動基礎
(1)offsetWidth 和 offsetHeight:只和自身相關,與周圍的元素無關
- offsetWidth = border-left + border-right + padding-left+padding-right+元素本身的寬度;
- offsetHeight = border-top + border-bottom + padding-top+padding-bottom+元素本身的高度;
(2)offsetLeft和offsetTop
- offsetTop = 上級定位元素的padding + 元素本身的margin;
- 如果二者中間還有其他元素,還要加上該元素的 margin padding 和 border;
- offsetLeft同理;
(3)scrollTop和scrollLeft:與滾動條相關的屬性
- scrollTop:滾動條當前位置顯示的最上面和真正的最上面的距離,scrollLeft同理;
(4)clientHeight和clientWidth
- clientHeight包括padding但不包括border、水平滾動條、margin的元素的高度,clientWidth同理;
(5)定時器
- 開啟:setInterval(函數,時間)---迴圈執行;setTimeout()---只執行一次;
- 關閉:clearInterval;clearTimeOut;
- 應用:數位時鐘,延時提示框、無縫滾動;
2、運動框架
(1)開始運動前先關閉已有的定時器;
(2)將運動和停止的狀態用 if else 隔開;
(3)練習:側邊欄、圖片的淡入淡出;
3、緩衝運動
(1)速度越來越慢,最後停止;
(2)速度=(目標值-當前值)/縮放繫數;
(3)緩衝菜單:速度取整(向上和向下取整);目標值取整;
4、勻速運動的停止條件
(1)距離小於速度就停止;
(2)再手動將元素移到目標點;
(3)勻速和緩衝運動代碼的差異:速度表達式不同,最後的停止條件和處理方法也不同
5、多物體運動框架
(1)多物體運動框架很多東西都不能公用,定時器和透明度的變數等,解決方法就是給每個元素設置自定義屬性;
6、任意值的運動框架
(1)offset 屬性 bug 和 opacity 的小數問題;
(2)練習:圖片輪換的播放器;
7、運動中級
(1)鏈式運動
- 在原有框架的基礎上加一個回調函數,在運動結束關閉定時器之後加
(2)完美運動框架
- 多個屬性同時變化;
- 等所有的條件都滿足再停止;
JS事件應用
1、基礎
(1)event對象
- 用來獲取事件的詳細信息:滑鼠位置,鍵盤鍵位
- 滑鼠的位置:clientX 和 clientY
- document的本質:可以看作一個最高級的節點,包含html 的所有內容,全局事件加在 document 上
- 事件對象的相容性寫法:var oEvent = ev || event
(2)事件冒泡
- 父級和子級的元素假如都有 onclick 事件,子級元素的被點擊,則會觸發父級元素的點擊事件
- 阻止事件的冒泡:event.cancelBubble = true;
(3)滑鼠事件
- onmousemove事件
- clientX 和 clientY 實際是可視區域的坐標,如果要獲取相對與 document 的絕對坐標,需要和 scrolltop 等配合使用,封裝相應的方法;
- 應用:div 跟隨滑鼠的移動
(4)鍵盤事件
- keycode :可以用來判斷鍵盤的按鍵;應用:鍵盤控制 div 的移動;
- ctrlkey、altkey、shiftkey:應用提交留言;
2、中級
(1)預設行為
- 預設行為就是瀏覽器自發產生的行為,不用人為寫代碼觸發;
- document.onContextMenu(右鍵菜單彈出);
- 阻止預設行為,直接在事件的方法里 return false;
- 練習:阻止右鍵預設菜單,彈出自定義菜單;只能輸入數字的文本框(keycode 和 onKeydown);
(2)拖拽
1、基本原理:
- 元素位置的確定依靠滑鼠位置和滑鼠距離元素左上邊界的長度來確定;
- onmousedown計算滑鼠和元素邊界的距離,onmousemove重新定位元素,onmouseup停止事件;
2、拖拽的改進:
- 快速拖動滑鼠會移出 div :直接給 document 加事件;
- 火狐瀏覽器下空 div 的拖拽 bug:阻止預設行為;
- 防止 div 脫出頁面:進行位置的修正;
3、應用
(1)事件綁定
- 老方法給同一個元素相同事件綁定不同的函數,會出現後面的把前面的覆蓋了的問題;
- 解決以上問題需要用到新的事件的綁定方法
function myAddEvent(obj, ev, fn)
{
if(obj.attachEvent)
{
obj.attachEvent('on'+ev, fn);
}
else
{
obj.addEventListener(ev, fn, false);
}
}
- 事件的解綁:IE(detachEvent);CHROME(removeEventListener);
(2)高級拖拽
- 練習:不能脫出指定的元素;
- 練習:磁性吸附功能(靠近邊界的時候把距離設置為0即可);
- 練習:帶框的拖拽;
- 事件捕獲:將所有元素的事件集中到某一個元素上,解決IE下拖拽引起的其他元素的選中問題(setCapture()、releaseCapture());
(3)自定義滾動條
- 原理:橫向拖拽;限制範圍;計算比例;
- 應用:控制元素大小;控制透明度;控制文字的滾動;
AJAX技術
1、概念
- Ajax 即 Asynchronous Javascript And XML(非同步 JavaScript 和 XML);
- 無刷新數據讀取技術;
2、應用
- 讀取靜態數據,如txt文件等;
- 讀取動態數據,如json;
- 用於網頁的局部刷新;
其他:
- eval(str)可以將 str 解析為 js 執行;
- 瀏覽器緩存是根據 url 進行緩存的,變更 url 可以阻止瀏覽器的緩存;
3、原理
(1)AJAX 原理
/**
* ajax 的封裝
*/
function myAjax(method,url,data,async,sucFn,faiFn){
//get ajax obj
if(window.XMLHttpRequest)
{
var oAjax=new XMLHttpRequest();
}
else
{
var oAjax=new ActiveXObject("Microsoft.XMLHTTP");
}
//connection check method
if(method.toUpperCase() == "GET"){
oAjax.open(method, url+(data ? '?'+data : ''), async);
oAjax.send(data);
}else if(method.toUpperCase() == "POST"){
oAjax.open(method, url, async);
oAjax.setRequestHeader("Content-type","application/x-www-form-urlencoded");
oAjax.send(data);
}
//state listener
oAjax.onreadystatechange=function ()
{
if(oAjax.readyState==4)
{
if(oAjax.status==200)
{
if(sucFn){
sucFn(oAjax);
}
}
else
{
if(faiFn){
faiFn(oAjax);
}
}
}
};
};
(2)說明:
- ajax 數據類型:xml 和 json;
- 字元集問題:統一字元集就不會出現亂碼;
- js 的變數與屬性:使用未定義的變數會報錯;使用未定義的屬性僅僅是 undefine,不會報錯;
(3)AJAX請求的幾種狀態
- 0:未初始化,還未調用 open 方法;
- 1:載入,已調用 send 方法,正在發送去請求;
- 2:載入完成,send 方法完成,收到所有的響應內容;
- 3:解析,解析響應內容;
- 4:完成,解析完成,可以在客戶端使用了;
面向對象
1、概述
(1)js 中的面向對象:隱藏實現的細節,對外發佈功能;
(2)面向對象的特點:
- 抽象:抓住核心問題;
- 封裝:隱藏實現的細節,對外發佈功能;
- 繼承:已有對象派生出新的對象(多態和多重繼承);
(3)對象的組成:
- 屬性(變數)
- 方法(函數)
2、為對象添加方法和屬性
(1)this 的本質:函數屬於誰,全局函數屬於 window 對象;
(2)Object 對象:
- 不能隨意給系統的對象添加屬性和方法,可能會造成方法和屬性的覆蓋;
- Object 是一個空的對象,可以用來改造;
3、類的構建方法
(1)工廠方式
- 原理:用構造函數創建一個類
- 存在問題:不能 new;通用的方法存在很多,浪費資源;
- 構造函數也可以加上 new ,加上 new 後會自動做兩件事:創建空白對象和返回對象,new 創建的對象名即為 this;
(2)原型(prototype)
- 概念:類似於 css 中的 class 的概念,修改他可以影響一類的元素;
- 給對象加方法類似於行間樣式;給原型加方法類似於 class;
- 原型的缺陷:無法限制屬性和方法的覆蓋;
(3)混合方法(推薦)
- 構造函數加屬性;
- 原型加方法;
function CreatePerson(name, qq) //構造函數
{
this.name=name;
this.qq=qq;
}
CreatePerson.prototype.showName=function () //原型
{
alert('我的名字叫:'+this.name);
};
CreatePerson.prototype.showQQ=function ()
{
alert('我的QQ號:'+this.qq);
};
var obj=new CreatePerson('blue', '258248832');
var obj2=new CreatePerson('張三', '45648979879');
4、面向對象的選項卡(練習)
(1)面向過程改面向對象原則
- 不能有函數套函數、但可以有全局變數
(2)過程
- onload → 構造函數
- 全局變數 → 屬性
- 函數 → 方法
(3)註意 this 在面向對象的用法
window.onload=function(){
new Tar('div1');
};
function Tar(id) {
var _this = this;
this.oDiv = document.getElementById(id);
this.aInput = this.oDiv.getElementsByTagName('input');
this.aDiv = this.oDiv.getElementsByTagName('div');
for(var i = 0;i < this.aInput.length;i ++){
this.aInput[i].index = i;
this.aInput[i].onclick=function () {
_this.fnClick(this);
};
}
}
Tar.prototype.fnClick =