JS基礎
- 頁面由三部分組成:
- html:超文本標記語言,負責頁面結構
- css:層疊樣式表,負責頁面樣式
- js:輕量級的腳本語言,負責頁面的動效和數據交互
小總結:結構,樣式和行為,三者相分離 - 在html頁面中寫結構
- 通過 link標簽的href屬性,引入css樣式
- 通過script標簽的src屬性,引入js腳本
- css引入頁面的方式有三種
- 行內
<div style="width:200px;height:300px;"></div>
- 內嵌:在header里面寫一個
<style>選擇器{key:value}</style>
- 外鏈:在header里面寫一個
<link rel="stylesheet" href="css/index.css"/>
- 行內
- JS引入頁面的方式,同CSS相似
- 內嵌:在開發過程中,建議把script放在body底部;如果非要把script標簽對,放在head里面的話;需要加window.onload
window.onload=function(){ document.body.innerHTML='XXXXXX'; }
- 行內:
<div onclick="xxxx" onmouseover="xxxx"></div>
- 外鏈:
<script src="01.js"></script>
注意:如果script作為JS的外鏈,一定不要在兩個script標簽中寫代碼,寫了也沒用
- 屬性和方法的區別:屬性沒括號,方法有括號
- 字符串和變量的區別:字符串有引號,變量沒引號
- 字符串一般用單引號;為了元素身跟上的屬性值區分開來;屬性值一般是""
- 變量,就是別名;var str; 告訴瀏覽器,定義了str這么一個變量
- 如果沒有定義變量,xxx is not defined
- JS常見的輸出方式7種
- alert('') ; 顯示帶有一條指定消息和一個 OK 按鈕的警告框
- confirm('確定要刪除?'); 他有兩個返回值:true 真, false假
- console.log(''); 可以在控制臺打印出我們想要打印的內容
- console.dir(); 打印出對象身上的屬性和方法
- document.write() 向文檔寫入 HTML 表達式或 JavaScript 代碼
如果遇到window.onload會清空頁面 - 元素.innerHTML=xxxx 設置或返回表格行的開始和結束標簽之間的 HTML
- console.table(); 可以把數組和對象,以表格的形式打印出來
var ary2=[ { name:'a', age:1, sex:'gril' }, { name:'王b', age:2, sex:'boy' } ]; console.table(ary2);
- chrome控制臺
- Elements:用來調試html+css的
- console:用來調試JS的
- sources:可以拿到該網站相關的資源:images ,html ,css, js
體驗JS編程思想
需求:鼠標移入div1的時候,div2顯示;鼠標移出div1的時候,div2隱藏
-
實現思路:
- 高度:div2的高度為0; 移入div1后高度為100;移出div1時div2高度0;
- display:block顯示,none,隱藏;
- 透明度:rgba(); opacity();
- 定位:left和top;
- margin:margin-left和 margin-top;
- overflow:hidden和visible;
-
JS獲取元素的方式:
- document.getElementById('id名字');
因為id是唯一的,所以拿到的是一個元素 - document.getElementsByTagName('標簽名');
標簽名拿到的是一個元素集合;即使只有一個元素,也是個集合
想要取到其中的一個:aDiv[0] aDiv[2]
- document.getElementById('id名字');
-
JS中的數據類型
- 基本數據類型:
- 字符串string
- 數字 number
- 布爾值 boolean
- undefined 現在沒有,以后也沒有
- null 空對象,現在沒有,以后會有
- 引用數據類型
- 對象數據類型
- 數組
- 正則
- 對象{}
- 函數數據類型
function 函數名(){};
- 對象數據類型
- 基本數據類型:
-
數據類型檢測的方式
- typeof 可以檢測基本數據類型(所有經過typeof的都是字符串),但是對于對象數據類型,檢測出來的都是object,無法知道具體屬于哪種對象
- 對象 instanceof 類; 比如
ary instanceof Array
判斷這個實例是否屬于某個類 - 對象.constructor: 比如
ary.constructor
可以打印出對象所屬的類 - Object.prototype.toString.call(ary); 出來的結果 '[object Array]'
-
基本數據類型和引用數據類型的區別:
- 基本數據類型:是對值的操作
- 引用數據類型:是對地址的操作
操作屬性用的是"." oDiv.style.display='block'
-
其他數據類型轉為number數據類型
- 強制轉換
- Number()
- parseInt()
- parseFloat()
- 一個嚴格轉換
- Number()
- 兩個非嚴格轉化
- parseInt() 只能轉化為整數
- parseFloat() 可以保留小數
如果轉換失敗的話,返回的結果是NaN:not a number 不是數字;但是NaN是number數據類型
- 強制轉換
-
關于NaN:
- NaN是number數據類型
- isNaN() 判斷是否為非有效數字; 非有效數字:true; 有效數字:false
-
循環由4部分組成:
- 1)定義 2)條件 3)語句 4)自增
-
常見的循環方式:
- for() :類數組arguments,htmlCollection,數組[],字符串
- for in():普通對象{}
- while(){}和for循環的區別和聯系
- 用while()循環也可以實現for循環的四步
- for循環一般用在循環次數固定; while()循環次數不固定
- do...while() 不管條件是否成立,都會先執行一次
-
函數由兩部分組成:
- 函數定義3階段
- 開辟一個內存空間
- 把函數體內所有的JS代碼,作為字符串存在這個空間中
- 把空間地址賦值給函數名
- 函數調用2階段
- 當函數被調用的時候,會形成一個私有作用域
- 把內存中的字符串作為JS代碼來執行
只定義不調用,函數不會執行
- 函數定義3階段
-
閉包
- 定義:
- 當函數被調用的時候會形成一個私有作用域,保護里面的變量不受外界的干擾,函數的這種保護機制叫做閉包
- 閉包就是在提供了一個在外部訪問另一個函數內部局部變量的方式
- 定義:
var add = (function(){
var count = 0;//外部訪問的計數器,局部變量.
var fun = function(){
return ++count;
}
return fun;
})();
//還可以這樣寫
var add2 = (function(){
var count = 0;//外部訪問的計數器,局部變量.
function plus(){
return ++count;
}
return plus;
})();
//還可以這樣寫
var add3 = (function(){
var count = 0;//外部訪問的計數器,局部變量.
return function(){
return ++count;
}
})();
- 作用:
- 避免全局變量名沖突
- 在閉包中通過“window.xx”去修改全局變量;如果閉包中沒有定義此變量,也可以直接修改變量去影響全局
- 封裝(閉包中封裝的方法在全局不能使用,只能通過“window.xx=封裝的函數名”把方法導出)
- 保存正確的i值
- 特性:
- 函數嵌套函數
- 函數內部可以引用外部的參數和變量
- 參數和變量不會被收回
- 函數自帶的參數機制叫做arguments;
- arguments:能拿到實參,并且以類數組的形式展現; 類數組也是對象,是對象都有屬性和方法
- arguments.callee 拿到的是當前函數本身
- arguments.length 拿到實參的長度/個數
- 數字常用的方法:
- toFixed(要保存的位數)四舍五入的保存小數位數的
- 屬性和方法的區別:
- 屬性沒括號,方法有括號;方法本質就是對函數的調用
- 對象的屬性不會報錯,如果沒有,undefined; 方法不存在的話,會報錯
- 屬性操作:. 和 []
- 如果遇到變量,屬性名[變量名] 注:千萬不要給變量加引號
- 如果遇到屬性名為數字,屬性名[1]
- 參數有兩種
- 形參
- 形參是私有變量
- 如果定義了形參,但沒有賦值,拿到是undefined
- 形參個數不確定的話,用arguments來獲取參數
- 函數自帶的參數機制arguments
- arguments可以打印出實參,以類數組的形式打印出來
- 0,1,2可以找到對應的屬性值
- arguments.callee;代表當前函數本身
- arguments.length;打印出實參的個數
- 形參
- 函數返回值:
- 函數返回值通過return;來返回
- 獲取值的時候,需要返回值;設置值的時候,不需要返回值
- undefined出現的幾種情況:
- 屬性:當對象的屬性名不存在的話,拿到的是undefined
- 參數:如果定義了形參,但是沒有傳實參,拿到的是undefined
- 沒有設置函數返回值,即沒有寫return,拿到的函數返回值為undefined
- 寫了return但沒有賦值,拿到的函數返回值也是undefined
- NaN出現的幾種情況:
- 轉化失敗時
- 無效運算時:null+undefined、undefined+undefined
- 運算符:
- 算術運算符:+ - * / %
- %(取余):技巧-有幾種情況就%幾
- 比較運算符:
> , >= , < , <= , == ,!= ,===, !== - 邏輯運算符:
! && ||- &&:兩邊都成立才能成立;但是也可以用它做條件判斷; 9%3==0 && alert('能整除')
- ||:一般成立就算成立;也可以用它做條件判斷;9%3!=0 || alert('能整除')
- 賦值運算符
=; += ; -= ; *= ; /= ; %= - 運算符的優先級:算術》比較》邏輯》賦值
- 算術運算符:+ - * / %
- 條件判斷:
- if(條件1){....}else if(條件2){...}else{...}
- 條件?語句1:語句2;
- switch:用于多條件判斷
每一種case情況其實都是相當于在用“===”進行比較switch(判斷的是可變的值){ case a: 語句1; break; case b: 語句2; break; default: 語句3; break; }
- 如果只有一種條件,有三種寫法:
- if(條件){語句1}
- 條件?語句1:null;
- if(條件) 語句1;
- 9%3==0 && alert('能整除');
- 9%3!=0 || alert('能整除');
數組常用的方法
第一組:增加,刪除和替換
- push()
- 作用:給數組末尾增加一項
- 需要實參
- 返回值:新數組的長度
- 原數組發生改變
- pop()
- 作用:刪除數組最后一項
- 不需要參數
- 返回值:被刪除的內容
- 原數組發生改變
- unshift()
- 作用:給數組開頭增加一項
- 需要實參
- 返回值:新數組的長度
- 原數組發生改變
- shift()
- 作用:刪除數組第一項
- 不需要參數
- 返回值:被刪除的內容
- 原數組發生改變
- splice()
- 插入/增加 splice(index,0,要添加的內容)
- 作用:在指定的索引前面,插入我們要添加的內容
- 參數:3個
- 返回值:[]空數組,里面沒有內容
- 原數組發生改變
- 刪除 splice(index,m)
- 作用:從指定的索引地方開始,刪除m個;如果第二個參數不寫,就從索引一直刪除到結尾
- 參數:2個
- 返回值:被刪除的內容,以一個新數組的形式返回
- 原數組發生改變
- 替換 splice(index,m,n)
- 作用:從指定的索引開始,刪除m個,并替換為n的新內容
- 參數:3個
- 返回值:被刪除的內容,以一個新數組的形式返回
- 原數組發生改變
- 插入/增加 splice(index,0,要添加的內容)
第二組:克隆和截?。檎?/h5>
- slice(n,m)
- 作用:從索引n開始,查找到索引m,包前不包后
- 參數2個
- 返回值:查找的內容
- 原數組沒有發生改變
- 克隆的功能:slice(0)/slice()
面試題:請找到數組中[n,m]項(答案:ary.slice(n-1,m))
- concat()
- 作用:數組拼接 / 克隆ary.concat()
- 參數:不確定,想拼接幾個數組,里面參數就寫幾個數組名,也可以寫成數組的形式
- 返回值:拼接成的新數組
- 原數組沒有發生改變
第三組:數組轉字符串
- toString()
- 作用:數組轉字符串
- 參數:無
- 返回值:以逗號分割的新字符串
- 原數組沒有發生改變
- join(拼接形式) 拼接形式可以為任何運算符號
- 作用:數組轉字符串
- 參數:拼接形式可以為任何運算符號
- 返回值:以指定的拼接形式分割的新字符串
- 原數組沒有發生改變
- 如果拼接形式為+之類的,想實現運算,可以用eval()
- eval():把字符串作為JS代碼來執行
第四組:數組的翻轉和排序
- 數組翻轉 ary.reverse()
- 功能:數組翻轉
- 參數:沒有
- 返回值:被翻轉后的數組
- 原數組發生改變
- 數組排序
ary.sort(function(a,b){
return a-b;//從小到大排; return b-a 從大到小排
})
第五組:數組常用但不兼容的方法
- indexOf()
- 功能:查找內容
- 參數:要查找的內容
- 返回值:如果找到,返回內容對應的索引/位置; 如果沒找到,返回-1
- 原數組不變
- forEach():遍歷數組的
- 作用:遍歷數組的
- 參數有兩個:1)callback 2)context:改變this指向的
- callback中有三個參數:item,index,input
- 返回值:undefined; 沒有返回值
- 原數組不變
- map():也是遍歷數組,跟forEach()功能一樣,只是forEach()沒有返回值;map有返回值
Math常用的方法
- Math.round() 四舍五入
- Math.floor() 向下取整
- Math.ceil() 向上取整
- Math.abs() 絕對值
- Math.sqrt() 開平發
- Math.pow() 冪次方
- Math.max() 最大值
- Math.min() 最小值
求n-m之間的隨機整數:Math.round(Math.random()(m-n)+n);
字符串常用的方法:
- 通過下標找對應的字符
- charAt() 返回指定位置的字符
- charCodeAt() 返回在指定的位置的字符的 Unicode 編碼
- 通過字符找下標
- 從前往后找:indexOf()
- 從后往前找:lastIndexOf()
- 字符串截取
- slice(n,m) 從索引n截取到索引m;不包含m;包前不包后;但是,slice可以取負值
- substr(n,m) 從索引n開始,截取m個
- substring(n,m) 從索引n截取到索引m;不包含m
- 字符串轉數組
- split(切割形式:字符串或正則表達式) 把字符串分割為字符串數組,返回一個字符串數組
- 轉大小寫
- toUpperCase() 把字符串轉換為大寫
- toLowerCase() 把字符串轉換為小寫
- 跟正則配合的字符串方法
- split() 把一個字符串分割成字符串數組
- match() 檢查一個字符串是否匹配一個正則表達式
- replace('a','b') 把a替換為b;替換與正則表達式匹配的子串
- search() 檢索與正則表達式相匹配的值;找到的情況下,返回對應內容的索引;找不到的返回-1
- 其他數據類型轉為number數據類型
- 一個嚴格轉換Number(),兩個非嚴格轉換parseInt() parseFloat()
- 轉換失敗是NaN
- [] 默認通過 toString() 轉成空字符串; Number("")===0
- null默認轉為0;null+10=10; undefined+10=NaN
- false===0; true===1
- 其他數據類型轉為布爾數據類型
- Boolean()
- 假:"",0,NaN,null,undefined,false
- 真:除了假都是真
- if(一個值) 會轉成布爾
- if(表達式/比較) 會默認轉成布爾
- !
- 其他數據類型轉成字符串數據類型
- 對象轉字符串:toString()
- 數字轉字符串:""+數字
- 數據類型的比較:
- 對象==對象 比較的是地址 []==[] false
- 字符串==對象 轉成字符串 ""==[] true
- 字符串==數字 轉成數字 ""==0 true
- 字符串==布爾值 轉成數字 ""==![] true
- 數字==對象 轉成數字 0==[]
- 布爾值==對象 轉成數字 false==[] ![]==[]
- 數字==布爾值 轉成數字 false==![]
- null==undefined true
- null===undefined false
- NaN==NaN false ;NaN跟任何值都不相等,包括自己也不相等
- 給數組末尾增加一項
- push()
- ary[ary.length]=xxx;
- ary.splice(ary.length,0,xxxx);
- 刪除數組最后一項
- pop()
- ary.length--; ary.length-=1; ary.length=ary.length-1;
- ary.splice(ary.length-1,1);
- 如何實現克隆
- ary.slice();/ary.slice(0)
- ary.concat();
- ary.splice(0) 注意:如果用splice()進行克隆,0不能省略
- for循環也可以實現;但for循環是循環,不是方法
- 定時器
- 隔一段時間爆發一次:
- setInterval(callback,毫秒數);
- 關閉定時器 clearInterval(定時器的名字)
- 只爆發一次:
- setTimeout(callback,毫秒數);
- 關閉定時器 clearTimeout(定時器的名字)
- n++ 和 ++n的區別
- ++n 先++,再運算;累加后的結果參與了運算
- n++ 先運算,再++; 累加后的結果不參與運算
- 創建數組的兩種方式
- var ary=[1,2,3]; 字面量方式創建
- var ary2=new Array(1,2,3); 實例創建
- DOM樹:由一大堆的元素和標簽組成;所以DOM就是用來操作頁面中的標簽的
- DOM中的獲取方式有以下幾種:
- id
- className
- tagName
- name
- 可視區的寬度:document.documentElement.clientWidth||document.body.clientWidth;
- 可視區的高度:document.documentElement.clientHeight||document.body.clientHeight;
- querySelector() #id .class div 拿到的是一個元素
- querySelectorAll() #id .class div 拿到的是一組元素
- 節點:
- 作用:從索引n開始,查找到索引m,包前不包后
- 參數2個
- 返回值:查找的內容
- 原數組沒有發生改變
- 克隆的功能:slice(0)/slice()
面試題:請找到數組中[n,m]項(答案:ary.slice(n-1,m))
- 作用:數組拼接 / 克隆ary.concat()
- 參數:不確定,想拼接幾個數組,里面參數就寫幾個數組名,也可以寫成數組的形式
- 返回值:拼接成的新數組
- 原數組沒有發生改變
- 作用:數組轉字符串
- 參數:無
- 返回值:以逗號分割的新字符串
- 原數組沒有發生改變
- 作用:數組轉字符串
- 參數:拼接形式可以為任何運算符號
- 返回值:以指定的拼接形式分割的新字符串
- 原數組沒有發生改變
- 如果拼接形式為+之類的,想實現運算,可以用eval()
- eval():把字符串作為JS代碼來執行
- 功能:數組翻轉
- 參數:沒有
- 返回值:被翻轉后的數組
- 原數組發生改變
ary.sort(function(a,b){
return a-b;//從小到大排; return b-a 從大到小排
})
- 功能:查找內容
- 參數:要查找的內容
- 返回值:如果找到,返回內容對應的索引/位置; 如果沒找到,返回-1
- 原數組不變
- 作用:遍歷數組的
- 參數有兩個:1)callback 2)context:改變this指向的
- callback中有三個參數:item,index,input
- 返回值:undefined; 沒有返回值
- 原數組不變
求n-m之間的隨機整數:Math.round(Math.random()(m-n)+n);
- charAt() 返回指定位置的字符
- charCodeAt() 返回在指定的位置的字符的 Unicode 編碼
- 從前往后找:indexOf()
- 從后往前找:lastIndexOf()
- slice(n,m) 從索引n截取到索引m;不包含m;包前不包后;但是,slice可以取負值
- substr(n,m) 從索引n開始,截取m個
- substring(n,m) 從索引n截取到索引m;不包含m
- split(切割形式:字符串或正則表達式) 把字符串分割為字符串數組,返回一個字符串數組
- toUpperCase() 把字符串轉換為大寫
- toLowerCase() 把字符串轉換為小寫
- split() 把一個字符串分割成字符串數組
- match() 檢查一個字符串是否匹配一個正則表達式
- replace('a','b') 把a替換為b;替換與正則表達式匹配的子串
- search() 檢索與正則表達式相匹配的值;找到的情況下,返回對應內容的索引;找不到的返回-1
- 一個嚴格轉換Number(),兩個非嚴格轉換parseInt() parseFloat()
- 轉換失敗是NaN
- [] 默認通過 toString() 轉成空字符串; Number("")===0
- null默認轉為0;null+10=10; undefined+10=NaN
- false===0; true===1
- Boolean()
- 假:"",0,NaN,null,undefined,false
- 真:除了假都是真
- if(一個值) 會轉成布爾
- if(表達式/比較) 會默認轉成布爾
- !
- 對象轉字符串:toString()
- 數字轉字符串:""+數字
- 對象==對象 比較的是地址 []==[] false
- 字符串==對象 轉成字符串 ""==[] true
- 字符串==數字 轉成數字 ""==0 true
- 字符串==布爾值 轉成數字 ""==![] true
- 數字==對象 轉成數字 0==[]
- 布爾值==對象 轉成數字 false==[] ![]==[]
- 數字==布爾值 轉成數字 false==![]
- null==undefined true
- null===undefined false
- NaN==NaN false ;NaN跟任何值都不相等,包括自己也不相等
- push()
- ary[ary.length]=xxx;
- ary.splice(ary.length,0,xxxx);
- pop()
- ary.length--; ary.length-=1; ary.length=ary.length-1;
- ary.splice(ary.length-1,1);
- ary.slice();/ary.slice(0)
- ary.concat();
- ary.splice(0) 注意:如果用splice()進行克隆,0不能省略
- for循環也可以實現;但for循環是循環,不是方法
- 隔一段時間爆發一次:
- setInterval(callback,毫秒數);
- 關閉定時器 clearInterval(定時器的名字)
- 只爆發一次:
- setTimeout(callback,毫秒數);
- 關閉定時器 clearTimeout(定時器的名字)
- ++n 先++,再運算;累加后的結果參與了運算
- n++ 先運算,再++; 累加后的結果不參與運算
- var ary=[1,2,3]; 字面量方式創建
- var ary2=new Array(1,2,3); 實例創建
- id
- className
- tagName
- name
- 可視區的寬度:document.documentElement.clientWidth||document.body.clientWidth;
- 可視區的高度:document.documentElement.clientHeight||document.body.clientHeight;
- querySelector() #id .class div 拿到的是一個元素
- querySelectorAll() #id .class div 拿到的是一組元素
節點類型 | 說明 | 值 |
---|---|---|
元素節點 | 每一個HTML標簽都是一個元素節點(例如:<div>、<input>等) | 1 |
屬性節點 | 元素節點(HTML標簽)的屬性(例如:id 、class 、name 等) | 2 |
文本節點 | 元素節點或屬性節點中的文本內容 | 3 |
注釋節點 | 表示文檔注釋,形式為 | 8 |
文檔節點 | 表示整個文檔(DOM 樹的根節點,即 document ) | 9 |
-
DOM動態操作
- 創建新標簽
- document.createElement(標簽名) 創建
- 克隆 obj.cloneNode(false/true);//false:只克隆表面; true:深度克隆
- 動態插入
- 父級.appendChild(新元素) 插入到父容器的末尾
- 父級.insertBefore(newEle,oldEle) 插入到指定元素的前面
- 刪除標簽
- 父級.removeChild(獲取到的元素名)
- 創建新標簽
-
屬性操作
- . 和 []
- attribute
- setAttribute(屬性名,屬性值) 設置屬性
- getAttribute(屬性名) 獲取屬性
- removeAttribute(屬性名) 移除屬性
- 1)通過點來設置自定義屬性,看不到;但是通過setAttribute()可以看到;
2)通過點獲取元素身上已經定義好的的自定義屬性,獲取不到;但是通過getAttribute()可以拿到;
注意:用"."都用點,用attribute,都用attribute;千萬不要混搭!
-
判斷屬性是否存在的方法
- in: "屬性名" in 對象 如果支持,返回true;不支持返回false
- ".": 對象.屬性名 如果不支持,返回undefined
預解釋:當前作用域下,在JS代碼執行之前瀏覽器會對帶var和帶function的進行提前聲明或定義
-
帶var和帶function的聲明和定義不同:
- 帶var的,只聲明不定義
- 帶function,聲明+定義
-
函數定義三步驟:
- 開辟一個空間地址
- 把函數體內所有JS代碼作為字符串放在這個空間中
- 把空間地址賦值給函數名=
-
函數調用四步驟:
- 形成一個私有作用域
- 形參賦值
- 預解釋
- 代碼從上到下的執行
上級作用域
上級作用域跟函數在哪里調用無關,只跟函數對應的堆內存在哪里開辟有關-
作用域鏈
- 當函數被調用的時候,會形成一個私有作用域;在這個作用域中查找是否有私有變量a
- 如果有私有變量a:那么整個函數體內的所有a都是私有變量,跟外界沒有任何關系
- 如果沒有私有變量a:去上級作用域找,找不到,繼續往上級找,如果找到window還沒有的話,報錯!
-
私有變量主要有兩種
- 函數體內帶var的
- 形參
- 內存包含:堆內存和棧內存
- 堆內存:用來存放數據
- 對象數據類型的
- 存的是鍵值對 key=value
- 函數數據類型的
- 代碼字符串
- 對象數據類型的
- 堆內存的釋放:
var a=[1,2,3,4]
釋放:a=null - 棧內存:本身提供了一個供JS代碼執行的環境
- 包含:全局作用域 和 私有作用域
- 全局作用域的形成和銷毀:
- 形成:當一個頁面被瀏覽器加載完成的時候,全局作用域就形成了
- 銷毀:1)關閉頁面 2)關閉瀏覽器
- 私有作用域的形成和銷毀:
- 形成:當函數被調用的時候,會形成私有作用域
- 銷毀:一般情況下,當函數執行完成的時候,默認就被銷毀了;但是兩種情況下不銷毀:
- 不銷毀:當函數體內的東西被外面的變量或者其他占用的話,就不銷毀
- 不立即銷毀:當函數執行完成的時候,會返回一個函數,被返回的函數還需要再執行一次;只有所有的調用都完成的時候,這個函數才能銷毀
- 預解釋無節操
- 只對等號左邊帶var的,聲明但不定義
- 自執行函數不會進行預解釋,只有,執行到他的時候,聲明+定義+調用同步完成
- 已經聲明過的不會進行重復聲明,但會重新賦值
- return下面的語句雖然不會執行,但會進行預解釋
- 函數的聲明早于變量的聲明
- (在IE10及10以下瀏覽器下)在條件判斷語句中,無論條件是否成立,都會進行預解釋
不要在條件判斷語句中寫函數的定義階段;否則,各大瀏覽器對其的兼容性不同
全局變量,都是window的全局屬性;
全局函數,都是window的全局方法。
比如:
setInterval()
setTimeout()
alert()
confirm()
- 關于this
- 當一個元素身上的事件被觸發的時候,會執行一個函數,函數中的this指向當前這個元素
- 自執行函數中的this,永遠都是window
- 回調函數中的this,一般都是window
setInterval(函數名,1000) ; ary.sort(function(){}) ; - 當函數被調用的時候,看前面是否有".","."前面是誰,this就是誰
- 當遇到call、apply、bind時,以上規律失效;因為他們可以改變this指向
- 箭頭函數中的this指向父函數中的this
- 改變this指向的函數:
- call(arg1,arg2,arg3,arg4......)
- call的一個參數用來改變call前面的函數中的this關鍵字
- call從第二個參數開始,相當于給call前面的函數從左往右一個個的賦值;
- call當改完this指向,傳完參數后,立即執行了
- apply(arg1,arg2) arg2可傳可不傳
- arg1用來改變this指向,具體跟call一樣
- 區別:apply的第二個參數是個數組,存放所有需要給形參的值;
雖然apply的第二個參數是個數組,但是對于形參來說,也是從左往右一個個的賦值
- bind(預處理機制)
- bind的傳參形式跟call一樣
- 注:bind屬于預處理機制,當調用bind的時候,會返回一個已經改好this,傳好參數的函數,你只需要在需要的時候,調用即可
- call(arg1,arg2,arg3,arg4......)
- 帶var和不帶var的區別:
- 帶var:
1)會進行預解釋
2)如果在全局作用域下,他就是window的全局屬性 - 不帶var:
1)不會進行預解釋
2)不帶var在"賦值"的時候,相當于window添加全局屬性
- 帶var:
面向對象
對象兩大特征:屬性 和 方法
-
面向對象(oop,oo)思想的特點:
- 封裝:對于同一個功能,只需要封裝一次,以后再使用的時候,只需要調用即可,無需重寫;低耦合高內聚
- 繼承:子類可以繼承父類的屬性和方法
- 多態:重載 和 重寫
- 重載:JS上沒有嚴格意義上的重載;但有類似重載的功能,就是傳不同的參數,有不同的返回值
- 重寫:子類可以重寫父類的屬性和方法
-
面向對象的四種常見設計模式:
- 單例模式
- 把同一個對象上的屬性和方法,都放在同一個命名空間
- 單例模式的本質:普通對象
- 模塊化開發:對于一個復雜的大項目,可以分配給不同的工程師同步進行開發;等項目完成的時候,合并即可
- 各個模塊之間的相互調用:對象名.屬性名
- 本模塊之間的相互調用:this.屬性名
** 缺點:造成大量冗余代碼**
- 工廠模式
- 工廠模式有3步:
- 引進原材料 創建一個空對象{}
- 加工原材料 加工對象:給對象添加屬性和方法
- 輸出產品成 輸出對象: return
- 工廠模式,為了讓他長的像系統的類 new Array()
- 工廠模式和構造函數模式的區別:
- 在調用的時候:
工廠模式 person()
構造函數模式 new Person() - 在函數體內
工廠模式三步:1)創建對象 2)給對象添加屬性和方法 3)返回對象
構造函數模式只有一步:2)給對象添加屬性和方法 ; 第一步和第三步系統幫做了,系統提供了一個對象叫this
- 在調用的時候:
- 工廠模式有3步:
- 構造函數模式
1.構造函數首字母一定大寫
2.構造函數中放的都是私有的屬性和方法
3.原型上放的都是公有的屬性和方法
4.系統默認會創建一個對象,this
5.系統默認會返回一個對象 this
6.構造函數中的this,指向當前這個實例(構造函數new給誰,this就指向誰) - 原型模式
- 原型模式基礎:
- 每個函數數據類型(普通函數,類),都有一個屬性,叫做prototye,prototype是個對象
- prototype這個對象上,天生自帶一個屬性,叫做constructor,指向當前所屬類
- 每個對象(普通對象,實例,prototype)身上,都有一個屬性,叫做
__proto__
,指向當前對象所屬類的原型
- 原型鏈:
__proto__
如果要查找 對象.屬性名 比如f1.showX- 先在自己的私有作用域中查找;如果找到,那么這個屬性是私有屬性
- 如果沒找到,到當前實例所屬類的原型上找(f1.
__proto__
),如果找到屬于公有的屬性或方法 - 如果沒找到,繼續通過
__proto__
往上找,一直找到Object.prototype上還沒有的話,undefined
- 要形成的幾個條件反射:
- 一看到構造函數:存的都是私有的屬性和方法
- 一看到prototype:存的都是公有的屬性和方法
-
__proto__
原型鏈
- 原型模式基礎:
- 單例模式
兩大boss:Object 和Function
1 Function 是 Object 的爹
2 Object 是 Function 的爹
3 Object 是 Function.prototype的爹
4 Object.prototype 是 Function.prototype的爹-
函數的三種角色:
- 普通函數:形成一個私有作用域,形參賦值,預解釋,代碼執行,內存和內存釋放,作用域鏈
- 類:實例,prototype,constructor,類,原型鏈
__proto__
- 普通對象:具有普通對象的特征:屬性和方法
如果給原型自定義了一個對象,那么自定義的這個對象上,沒有constructor
-
屬性判斷
- in:判斷某個屬性是否在元素上(包含了私有+公有)
- hasOwnProperty判斷某個屬性是否為元素身上的私有屬性
使用 obj.hasOwnProperty(屬性名) - 寫一個方法:判斷是否為公有屬性
- isPrototypeOf:判斷前一個對象是否在后一個對象的原型鏈上;返回的布爾值
- propertyIsEnumerable:他的作用跟hasOwnProperty類似;返回的布爾值
-
繼承:子類繼承父類的屬性和方法
- call繼承:子類只繼承父類私有的屬性和方法;父類私有的屬性和方法,都在父類的構造函數里
- 拷貝繼承:私有通過call來繼承,公有通過extend() 來繼承
- 原型繼承:
- 私有繼承:call繼承
- 公有繼承:父類原型上的屬性和方法,只有父類中的實例可以使用
- 子類原型可以使用父類原型上的屬性和方法;子類原型作為父類的實例
- 類數組轉數組
- 類數組有兩種:
- arguments
- htmlCollection 元素集合
- 瀏覽器異常捕獲
try....catch(e){}...finally{..}
平常用的,只有 try...catch...
使用場景:只要有報錯的情況,建議用try...catch.... - JSON: JOSN 是系統window的屬性
- JSON.parse() 把JSON格式的字符串,轉成JSON格式的對象
- JSON.stringify() 把JSON格式的對象,轉成JSON格式的字符串
注意JSON,屬性名一定是雙引號"";屬性值,如果是數字,可以沒有引號
- eval() 容易引起"注入攻擊"
- 類數組有兩種:
- sort排序
- DOM映射:html頁面中的DOM結構,跟通過JS獲取到的元素集合htmlCollection之間,存在一一對應的關系
- appendChild() 有類似剪切的功能
- sort排序三步驟:
1 類數組轉數組
2 sort排序
3 把排好序的內容,重新插入頁面 - 把數據插入頁面的幾種方式
- 字符串拼接; _插入頁面用innerHTML
- 動態創建和插入; document.createElement() 父級.appendChild(元素)
- 文檔碎片:
1)先把創建好的每個元素,放入文檔碎片
2)最后把文檔碎片放入父元素中
3)釋放文檔碎片
- DOM映射:html頁面中的DOM結構,跟通過JS獲取到的元素集合htmlCollection之間,存在一一對應的關系
- 前端往后臺的請求方式:
- GET 請求數據
- POST 發送數據
- DELETE 刪除數據
- PUT 提交數據
- 同步和異步:
- 同步:每次只能完成一個任務,必須等這個任務完成之后,才能開始下個任務
- 異步:當前的任務沒完成,不用等待,繼續開始下個任務,也就是,可以多個任務并行
- 回調異步
- 事件
- 定時器
- ajax
- http響應狀態碼
- 2xx 成功
- 3xx 重定向
- 4xx 請求錯誤
- 400 請求的參數錯誤
- 404 文件沒找到
- 5XX 服務器錯誤
-
正則(手冊:http://tool.oschina.net/uploads/apidocs/jquery/regexp.html)
- 作用:玩字符串的
- 定義:通過制定一系列的規則來操作(校驗/匹配、捕獲)字符串
- 校驗: reg.test() ;/^2\d{2}/.test(xml.status);
- 捕獲:1)str.match(reg) 2)reg.exec(str); 3)str.replace(reg);
正則的方法: reg.test() reg.exec()
字符串的方法:str.match() str.replace() str.split() str.search();
-
創建正則的方式:
- var reg=/^2\d{2}/; 字面量的創建方式
- var reg=new RegExp(); 實例創建
-
字面量創建和實例創建的區別:
- 字面量創建無法拼接變量,實例創建可以拼接變量
- 字面量創建不需要轉義,實例創建需要轉義
-
正則由元字符和修飾符兩部分構成: var reg=/^2\d{2}/g;
- 元字符:就是包含在兩個斜杠之間,陌生的字符
- 修飾符:就是斜杠外面的
-
元子符包含:特殊含義的元字符和量詞元字符
- 特殊含義的元字符:
\ 轉義
| 或
() 分組
. 除了\n以外的其他字符
\n 換行
\b 開頭結尾和空格
^ 開頭
$ 結尾
\s 空格 \d 數字 \w 數字,字母,下劃線
\S 非空格 \D 非數字 \W 非數字,非字母,非下劃線
[a-z] 任意一個小寫字母
[^a-z] 除了字母以外的任何一個字符
[abc] “a,b,c”中的任意一個字母
[^abc] 除了“a,b,c”以外的任意一個字母 - 量詞元字符
-
*
重復0次或多次 -
+
重復1次或多次 -
?
0 或1,可有可無 - {n} 正好n次
- {n,} 最少n次;n次到多次
- {n,m} n次到m次
-
- 特殊含義的元字符:
-
修飾符:
- g 全局
- m 換行
- i 忽略大小寫;ignore
-
()小括號的用法:
- 提高優先級 /^(18|19)$/
- 分組的作用
-
[]中括號的用法:
- 中括號中不會出現兩位數
- 像類似于.-之類的,在中括號中都沒有特殊函數
-
?問號的作用:
- 可有可無
- 解決正則捕獲的貪婪性
-
捕獲
- 正則中的捕獲,主要講三點:
- exec: reg.exec(str);
- match: str.exec(reg);
- replace:str.replace(reg,xxxxxx)
- 正則捕獲有兩大特點:
- 懶惰性:
- 解決措施:添加全局g
- 加了全局g,會影響lastIndex(從你找到內容 的 下一項內容的 索引 開始查找)
- 貪婪性:
- 解決措施:在量詞元字符后面加上?
- 懶惰性:
- exec,是正則的方法,每次只能拿到一個值;返回的結果是個數組,默認情況下,數組有3項:
- 符合大正則的內容
- index:找到的內容所對應的索引;(位置)
- input:原始字符串;
如果有小分組的情況下,小分組從數組的第二項開始;數組的長度也會因為小分組而增加
- match:是字符串的方法,每次能到所有符合正則的內容,并且以一個新數組的形式返回
- exec和match的區別:
- exec每次只能拿到一個值;match能拿到所有值,并以新數組的形式返回
- exec能拿到小分組; match只能拿到大正則,無法拿到小分組
- 正則中的捕獲,主要講三點:
-
replace
- replace中的回調函數,默認接收三個參數,如果有小分組,arguments的長度會擴充
- replace回調函數中第一個參數的運用:敏感詞過濾
- replace回調函數中第2個參數的運用:把數字作為數組的索引,找到對應的值
統計出現次數最多的單詞
思路1:
1) 利用對象不重名的特性
2) 假設法
3) 字符串拼接
思路2:
1)字符串排序:字符串轉數組-數組排序-數組轉字符串
2)假設法+重復子項 /(\w)\1+/gi;解析URL地址: /([&?=]+)=([&?=]+)/g;
日期格式化:
重點,字符串轉成數組,三種思路:
1)嚴格匹配;
var reg=/^(\d{4})[/-](\d{2})[/-](\d{2}) (\d{2}):(\d{2}):(\d{2})$/;
var ary=null;
str.replace(reg,function(){
ary=Array.prototype.slice.call(arguments,1,arguments.length-2)
});
- split 切
var ary=str.split(/[^\d]+/g); - match 捕獲
var ary=str.match(/\d+/g);
- ?的用法
1) 0或1
2) 解決正則捕獲的貪婪性 +?
3) 只匹配不捕獲 (?:\d+) - 小括號的用法:
1)分組
2)提高優先級
3)只匹配不捕獲 (?:\d+) - var reg=new RegExp();
- 在有全局g的情況下,能影響lastIndex的值的屬性有兩個:
1)reg.test()- reg.exec()
- 回調函數需要注意的幾點:
- 回調函數被調用的次數;比如,map中回調函數被調用的次數,取決于數組的長度
- 回調函數是否需要傳參;比如,map中回調函數接收三個參數
- item
- index
- input
- 回調函數中this默認指向window,可以通過call來改變this指向
- 回調函數是否有返回值;比如 forEach()沒有返回值; map()有返回值,他是把每個回調函數的返回值保存在一個數組中,最后返回出map
- CSS盒子模型
- 構成:手動設置的寬高+padding+border+margin
- JS盒子模型
- 主要通過元素身上提供的屬性和方法,來獲取元素身上的樣式值
- JS中盒子模型所設計的屬性和方法,主要包含以下幾類:
- client系列:clientWidth clientHeight clientLeft clientTop
- clientWidth/clientHeight: 手動設定的寬度/高度+左右/上下padding
- clientLeft/clientTop: 左邊框的寬度 / 上邊框的寬度
- offset系列:offsetWidth offsetHeight offsetLeft offsetTop offsetParent
- offsetWidth/offsetHeight:手動設定的寬度/高度+左右/上下padding+左右/上下的border寬度
(clientWidth+左右border clientHeight+上下border) - offsetLeft/offsetTop:當前元素的外邊框距離他定位父級的內邊框之間的距離
- offsetParent: 定位上的父級
- scroll系列:scrollWidth scrollHeight scrollLeft scrollTop
- scrollWidth/scrollHeight:
- 在內容沒有溢出的情況下,
scrollWidth/scrollHeight等于clientWidth/clientHeight; - 如果內容溢出的情況下,
scrollHeight約等于上padding+真實內容的高度
為什么是約等于:
1)當內容溢出的情況下,不同瀏覽器拿到的值不同
2)同一瀏覽器下,內容是否溢出拿到的值也不同
- 在內容沒有溢出的情況下,
- scrollTop:指當前頁面被瀏覽器卷去高度
- JS盒子模型遇到的問題
- JS盒子模型中求出來的都是四舍五入的整數,無法拿到小數 --不解決
- JS盒子模型中拿到的值都是復合值,無法拿到單獨的寬或高; --解決:封裝getCss
- 關于盒子模型的偏移量,我們只能求出當前容器的外邊框到定位父級的那邊框之間的距離,無法求出當前定位元素到body的距離;--解決:封裝offset
- 求可視區的寬高或被瀏覽器卷去的高度和寬度,太麻煩了;-- 封裝win
- 箭頭函數
- 表達式
- var fn=p=>p;
- var fn=()=>'我沒有參數';
- var fn=(n,m)=>n+m;
- 函數體
- var fn=p=>{return p};
- var fn=()=>{return '我沒有參數'};
- var fn=(n,m)=>{return n+m}
注:箭頭函數中的this,指向父函數的this
- 表達式
- 類的創建和繼承
- 類的創建
class 類名{
constructor(){//寫私有的屬性和方法
}
getName(){//公有的屬性和方法
}
static getAge(){//類的靜態方法;也是類的私有方法,實例不能使用
}
}
類.xxxx=xxxx;//類的私有屬性
- 類的繼承
class S extends F{
constructor(name,age,color){
super(name,age);
this.color=color;
}
//下面正常寫子類公有的
}
- 解構賦值:{屬性名}=persion;//實際拿到的是對象身上該屬性名對應的值
- let 和 const
- 他兩都不能進行預解釋
- let會形成塊級作用域
- const 是個常量,不能進行更改
- $(document).ready() 和 window.onload的區別:
- window.onload 是等頁面所有的內容(圖片,音頻,視頻,DOM結構.....)都加載完成的時候,才執行JS代碼
- $(document).ready(function(){...代碼}) 只要DOM結構加載完成,就開始執行JS 代碼
- jQuery選擇器
- 基本選擇器:
('#div')('.div') ('div')('.div1,.div2');
- 基本選擇器:
- JS和jquery只能共存,不能混淆
- JS 轉成jquery:只需要被包裹即可;(this) $(oDiv)
- jquery轉JS: [index] get(index)
- jquery中DOM常用方法
- append 和 appendTo
聯系:功能相同,但是針對的主體不同 - 創建元素 ('')('<div></div>')
- append 和 appendTo
-
運動
- show() 顯示隱藏的元素
hide() 隱藏顯示的元素 - slideDown() 通過使用滑動效果,顯示隱藏的被選元素
slideUp() 通過使用滑動效果,隱藏被選元素,如果元素已顯示出來的話 - fadeIn() 使用淡入效果來顯示一個隱藏的元素
fadeOut() 使用淡出效果來隱藏一個元素 - animate(target,time,effect,callback) 執行 CSS 屬性集的自定義動畫
stop() 停止當前正在運行的動畫
- show() 顯示隱藏的元素
ajax前后端數據交互
ajax({
type:'get/post',
url:'xxxx?'+Math.random()*1000000+new Date().getTime(),
async:true/false,
dataType:'json',//解決了jsonParse()
data:$('form').serialize()//表單序列化:就是把前端要傳后臺的數據,以k=v&k=v拼成字符串
success:function(){//成功之后的回調
},
error:function(){//失敗之后的回調
}
})
- 事件和事件綁定
- 事件綁定:2個
on(type,fn) //可以執行多次
one(type,fn) //只能執行一次 - 解除綁定
off(type,fn);//注意:只能解除有名字的函數
- 事件綁定:2個
- each和map
-
().each() 和.each()的區別:
- $().each() 只能遍歷jquery獲取到的元素
- $.each() 既可以遍歷jquery元素也可以遍歷原生數組和原生對象
-
().map() 和.map() 他們 與 each的區別
- map的回調函數接收的參數,跟each的順序正好相反
- map可以返回一個新的數組;而each拿到的還是原來的數組
-
().each() 和.each()的區別:
- 事件
- 鼠標事件:
onclick ondbclick onmouseover onmouseout onmouseenter onmouseleave - 系統事件:
onload resize onscroll - 鍵盤事件:
onkeydown onkeyup onkeypress - 表單事件:
onfocus onblur autofocus=true/false;
- 鼠標事件:
- 事件分類:DOM0級事件 和 DOM2級事件
- DOM0級事件 和 DOM2級事件的區別:
- DOM0級事件:
1)在元素的私有屬性上
2)同一個元素,同一個行為,只能綁定同一個方法;如果多次綁定,后面的方法會覆蓋前面的方法
3)只能發生在事件流的冒泡階段 - DOM2級事件:
1)在元素所屬的EventTarget這個類的原型上
2)同一個元素,同一個行為,可以綁定多個不同的方法
3)可以人為的控制發生事件流的哪個階段(捕獲,冒泡)
- DOM0級事件:
- DOM0級事件 和 DOM2級事件的區別:
-
標準瀏覽器下:
addEventListener(type,fn,useCapture);- 解綁:
removeEventListener(type,fn,useCapture);
注意:所有的行為,都不加on
- 解綁:
-
IE6-8下:
attachEvent('on'+type,fn)- 解綁:
detachEvent('on'+type,fn);
attachEvent只能發生在冒泡階段
- 解綁:
- 事件流
- 由三部分構成:捕獲,target事件源,冒泡
- 由兩部分構成:捕獲,冒泡
注意順序:先捕獲,后冒泡
- 一個元素的層級嵌套:
元素自己->HTMLDivElement ->HTMLElement->Element->Node->EventTarget->Object - 事件對象
- 事件對象的兼容處理:e=e||window.event
- 事件源:e.target=e.target||e.srcElement;
- 坐標:距離當前可視區左上角的坐標-兼容:e.clientX; e.clientY;
- 坐標:距離第一屏左上角的坐標:e.pageX;e.pageY;
不兼容:
e.pageY=(document.documentElement.scrollTop||document.body.scrollTop)+ e.clientY;
e.pageX=(document.documentElement.scrollLeft||document.body.scrollLeft)+ e.clientX; - 事件類型:e.type
- 鍵碼:e.keyCode
- 阻止默認事件: e.preventDefault?e.preventDefault():e.returnValue=false;
- 阻止冒泡 e.stopPropagation? e.stopPropagation():e.cancelBubble=true;
- 熟悉標準瀏覽器中的DOM2級事件綁定
- addEventListener特點:(標準瀏覽器)
- 按"綁定的"先后循序執行的
- this指向當前被綁定事件的這個"元素"
- 如果給同一個元素,同一個行為綁定多次同一個方法,實際上只執行一次
- attachEvent的問題:
- 順序不對
- this不對,attachEvent中的this,默認指向window
- 如果給同一個元素,同一個行為綁定多次同一個方法,執行的是多次;也不對
- addEventListener特點:(標準瀏覽器)
補充
-
null和undefined區別:
- 定義變量時:null現在沒有,以后會有;undefined:現在沒有,以后也沒有
- null轉為數值為0,undefined轉為數值為NaN
- 報錯時:undefined表示“缺少值”,即 此處應該有一個值,但沒定義;null表示“沒有對象”,即 此處不該有值
-
性能優化
- 網頁內容
- 減少 http請求次數
- 減少 DNS查詢次數
- 避免頁面跳轉
- 緩存 Ajax
- 延遲加載
- 提前加載
- 減少 DOM元素數量
- 避免 404
- 服務器
- 使用CDN(內容分發網絡)
- 添加Expires或Cache-Control報文頭
- Gzip壓縮傳輸文件
- CSS
- 將樣式表置頂
- 用代替@import
- JavaScript
- 把腳本置于頁面底部
- 使用外部JavaScript和CSS
- 精簡JavaScript和CSS
- 去除重復腳本
- 減少DOM訪問
- 圖片
- 優化圖像
- 優化CSS Spirite
- 不要在HTML中縮放圖片
- favicon.ico要小而且可緩存
- 網頁內容
如何解決跨域問題
jsonp 原理:動態插入script標簽JavaScript同源策略
這里的同源策略指的是:協議,域名,端口相同。同源策略是一種安全協議,指一段腳本只能讀取來自同一來源的窗口和文檔的屬性。哪些操作會造成內存泄漏?
1、內存泄漏指任何對象在您不再擁有或需要它之后仍然存在
2、垃圾回收器定期掃描對象,并計算引用了每個對象的其他對象的數量。如果一個對象的引用數量為 0(沒有其他對象引用過該對象),那么該對象的內存即可回收
3、setTimeout 的第一個參數使用字符串而非函數的話,會引發內存泄漏。閉包、控制臺日志、循環(在兩個對象彼此引用且彼此保留時,就會產生一個循環)事件代理(Event Delegation) 即 事件委托
定義:把原本需要綁定的事件委托給父元素,讓父元素擔當事件監聽的職務
原理:DOM元素的事件冒泡
優點:提高性能