js知識體系梳理-2

JS中的數組類型轉換匯總

[基本數據類型]javascript

  • number 數字
  • string 字符串
  • boolean 布爾
  • null 空
  • undefined 未定義

[引用數據類型]java

  • object類型
    • 普通對象
    • 數組對象 (Array)
    • 正則對象 (RegExp)
    • 數學對象 (Math)
    • 日期函數 (Date)
  • function 函數

把其它數據類型轉換爲number類型

一、發生的狀況node

  • isNaN檢測的時候:當檢測的值不是數字類型,瀏覽器會本身調用Number方法把它先轉換爲數字,而後再檢測是否爲非有效數字
isNaN('3')=>false
Number('3')->3
isNaN(3)->false
複製代碼
  • 基於parseInt/parseFloat/Number去手動轉換爲數字類型
  • 數學運算:+ - * / %,可是"+"不只僅是數學運算,還多是字符串拼接
'3'-1 =>2
Number('3')->3
3-1=2

'3px'-1 =>NaN

'3px'+1 =>'3px1' 字符串拼接

var i='3';
i=i+1; =>'31'
i+=1;  =>'31'
i++;    =>4   i++就是單純的數學運算,已經摒棄掉字符串拼接的規則
複製代碼
  • 在基於"=="比較的時候,有時候也會把其它值轉換爲數字類型

二、轉換規律數組

//=>轉換爲數字類型的時候瀏覽器默認都是用Number()方法
【把字符串轉換爲數字】
只要遇到一個非有效數字字符,結果就是NaN
''->0
' '->0(空字符串裏面是空格)
'\n' ->0 換行符(Enter)
'\t' ->0 製表符(Tab)

【把布爾轉換爲數字】
true ->1
false ->0

【把沒有轉換爲數字】
null ->0
undefined ->NaN

【把引用類型值轉換爲數字】
首先都先轉換爲字符串(toString),而後再轉換爲數字(Number)
複製代碼

把其餘類型值轉換爲字符串

一、發生的狀況瀏覽器

  • 基於alert/confirm/prompt/document.write等方法輸出內容的時候,會把輸出的值轉換爲字符串,而後再輸出
alert(1) =>'1'
複製代碼
  • 基於"+"進行字符串拼接的時候
  • 把引用類型值轉換爲數字的時候,首先會轉換爲字符串,而後再轉換爲數字
  • 給對象設置屬性名,若是不是字符串,首先轉換爲字符串,而後再當作屬性存儲到對象中(對象的屬性只能是數字或者字符串)
  • 手動調用toString/toFixed/join/String等方法的時候,也是爲了轉換爲字符串
var a=Math.PI;
Math.PI.toFixed(2) ->'3.14'

var ary=[1,45,2,34,34];
ary.join("+")
'1+45+2+34+34';//返回值,原有數組不變

複製代碼

二、轉化規律閉包

//=>調用toString方法
【除了對象,都是你理解的轉換結果】
1 ->'1'
NaN ->'NaN'
null ->null
[] ->''
[12] ->'12'
[12,23] ->'12,23'

【對象】
{name:"zhufneg",age:9}  ->'[object Object]'
{} ->'[object Object]'

複製代碼

把其它值轉換爲布爾類型

一、發生的狀況app

  • 基於!/!!/Boolean等方法轉換
  • 條件判斷中的條件最後都會轉換爲布爾類型
  • ...
if(n){
	//=>把n的值轉換爲布爾驗證條件真假
}

if('3px'+3){
	//=>先計算表達式的結果'3px3',把結果轉換爲布爾true,條件成立
}
複製代碼

二、轉換的規律 只有0/NaN/""/null/undefined五個值轉換爲布爾的false,其他都是轉換爲truedom

特殊狀況:數學運算和字符串拼接

//=>當表達式中出現字符串,就是字符串拼接,不然就是數學運算

1+true //=>2 數學運算
'1'+true  //=>'1true' 字符串拼接

[12]+10  //=>'1210' 雖然如今沒看見字符串,可是引用類型轉換爲數字,首先會轉換爲字符串,因此變爲了字符串拼接

({})+10 //=>'[object Object]10'
[]+10  //=>'10'

{}+10 =>10

{} 表明一個代碼塊(塊級做用域)
+10 纔是咱們的操做
嚴格寫法:
{};
+10;(+10就至關於0+10)

複製代碼

思考題函數

12+true+false+null+undefined+[]+'wy'+null+undefined+[]+true //=>'NaNwynullundefinedtrue'
複製代碼

特殊狀況:"=="在進行比較的時候,若是左右兩邊的數據類型不同,則先轉換爲相同的類型,再進行比較

對象==對象:不必定相等,由於對象操做的是引用地址,地址不相同,則不相等性能

{name:"xxx"}=={name:"xxx"}
[]==[] =>false

var obj1={};
var obj2=obj1;
obj1=obj2 =>true
複製代碼

對象==數字:把對象轉換爲數字,而後再比較

對象==布爾:把對象轉換爲數字,把布爾也轉換爲數字

對象==字符串:把對象轉換爲字符串

[]=='' //->true
[12,23]=='12,23' -//>true,若是按照下面的規律對象和字符串進行比較的時候轉換爲數字,兩邊都爲NaN,那麼返回的結果應該是false
複製代碼

字符串==數字:字符串轉換爲數字 字符串==布爾:都轉換爲數字 布爾==數字:把布爾轉換爲數字

規律:

一、不一樣狀況的比較,都是把其它值轉換爲數字,而後再進行比較的

二、對象和對象比較的時候,比較的是地址

三、null==undefined //->true

四、null === undefined ->false

五、null、undefined和其它值都不相等

六、null==null

七、undefined==undefined

八、null===null

九、undefined===undefined

1==true =>true
1==false =>false
2==true =>false

[]==true:false  都轉換爲數字  0==1
![]==true:false  

[]==false: true 都轉換爲數字 0==0
![]==false: true ![]把數組轉換爲布爾類型再取反  false==false  
複製代碼

關於JS數組經常使用方法的剖析

數組也是對象數據類型的,也是由鍵值對組成的

var ary = [12,23,34];
 /* *結構: * 0:12 * 1:23 * 2:34 * length:3 */
1.以數字做爲索引(屬性名),索引從零開始增長
2.有一個length屬性存儲的是數組長度

ary[0] 獲取第一項
ary[ary.length-1] 獲取最後一項
複製代碼

數組中每一項的值能夠是任何數據類型的

//=>多維數組
var ary=[
	{
		name:'xxx',
		age:20
	}
	{
		name:'xxx',
		age:20
	}
]
複製代碼

數組的經常使用方法

按照四個維度記憶:

  • 方法的做用
  • 方法的參數
  • 方法的返回值
  • 原有數組是否改變

push

  • 語法:ary.push()
  • 做用:向數組末尾追加新的內容
  • 參數:追加的內容,能夠是一個或多個,能夠是各類數據類型
  • 返回值:新增後數組的長度
  • 原有數組改變

pop

  • 語法:ary.pop()
  • 做用:刪除數組末尾的最後一項
  • 參數:無
  • 返回值:被刪除的那一項內容
  • 原有數組發生改變

shift

  • 語法:ary.shift()
  • 語法:刪除數組中的第一項
  • 參數:無
  • 返回值:被刪除的那一項內容
  • 原有數組發生改變

unshift

  • 語法:ary.unshift()
  • 做用:向數組開始位置追加新的內容
  • 參數:追加的內容,能夠是一個或多個,能夠是各類數據類型
  • 返回值:新增後數組的長度
  • 原有數組改變

splice

刪除

  • 語法:ary.splice(n,m)
  • 做用:從索引n開始,刪除m個內容
  • 參數:索引 刪除項數
  • 返回值:刪除的部分用新數組返回
  • 原有數組發生改變

增長

  • 語法:ary.splice(n,0,x)
  • 做用:從索引n開始刪除零項(沒刪除),把x或者更多須要插入的內容放到數組中索引N的"前面"
  • 參數:索引 刪除項數 插入內容
  • 返回值:刪除的部分用新數組返回
  • 原有數組發生改變

修改

  • 語法:ary.splice(n,m,x)
  • 做用:把原有內容刪除掉,而後用新的內容替換這部分信息便可
  • 參數:索引 刪除項數 插入內容
  • 返回值:刪除的部分用新數組返回
  • 原有數組發生改變

以上全部方法總結

一、在最前面追加內容的方法

  • ary.unshift(參數)
  • ary.splice(0,0,參數)

二、在末尾追加內容的方法

  • ary.push(參數)
  • ary.splice(ary.length,0,參數)
  • ary[ary.length]=參數

三、刪除數組中第一項的方法

  • ary.shift()
  • ary.splice(0,1)

四、刪除數組中最後一項的方法

  • ary.pop()
  • ary.splice(ary.length-1)
  • ary.length--

slice

  • 語法:ary.slice(n,m)
  • 做用:從索引n截取到索引m處(不包含m)
  • 返回值:以新數組存儲截取的內容
  • 原有數組不會發生改變

concat

  • 語法:ary.concat()
  • 做用:實現多個數組(或者值)的拼接
  • 參數:數組或者值
  • 返回:拼接後的新數組
  • 原有數組不變

toString

  • 語法:ary.toString()
  • 做用:把數組轉換爲字符串
  • 參數:無
  • 返回:數組中的每一項用逗號分隔的字符串
  • 原有數組不變

join

  • 語法:ary.join()
  • 做用:和toString相似,也是把數組轉換爲字符串,可是咱們能夠設置變爲字符串後,每一項之間的鏈接符
  • 參數:指定的連接符返回
  • 原有數組不變

reverse

  • 語法:ary.reverse()
  • 做用:把數組倒過來排列
  • 參數:無
  • 返回:排列後的新數組
  • 原有數組改變

sort

  • 語法:ary.sort()
  • 做用:給數組排序
  • 參數:無或者回調函數
  • 返回:排序後的新數組
  • 原有數組改變

不傳遞參數的狀況下:能夠給10之內的數字進行升序排列,可是超過10的就沒法處理了(多位數只識別第一位,按照第一位的大小進行排列)

升序:ary.sort(function(a,b){return a-b;}) 降序:ary.sort(function(a,b){return b-a;})

驗證數組中是否包含某一項

indexOf && lastIndex0f

這兩個方法不兼容IE6-8

  • 語法:ary.indexof(要檢測的值)
  • 做用:獲取當前項在數組中第一次或者最後一次出現位置的索引
  • 參數:要檢測的值
  • 返回值:被檢測項的索引
  • 原有數組不變

基於indexOf檢測,若是數組中有這一項,返回一個大於等於零的索引 若是沒有這一項,返回的索引爲-1

//=>驗證數組中是否包含某一項

if(ary.indexOf(100)>-1){
   //=>ARY中包含100這一項
}
複製代碼

案例:數組去重 方案一 indexOf方法

Array.prototype.myUnique=function(){
	for(let i=0;i<this.length-1;i++){
		let item=this[i],
			curary=this.slice(i+1);
		if(curary.indexOf(item)>-1){
			this[i]=this[this.length-1];
			this.length--;
			i--;
		}
	}
}

複製代碼

方案二 利用對象屬性名的惟一性

Array.prototype.myUnique=function(){
	let obj={};
        for(var i=0;i<this.length;i++){
	if(typeof obj[this[i]]!=='undefined'){
    		this[i]=this[this.length-1];
    		this.length--;
    		i--;
    		continues;
    	}
	obj[this[i]]=this[i];
    }
    obj=null;
}
複製代碼

方案三 利用雙循環

Array.prototype.myUnique=function(){
	for(var i=0;i<this.length-1;i++;){
	var item=this[i];
	for(var j=i+1;j<this.length;j++){
		if(item===this[j]){
			this[i]=this[this.length-1];
			this.length--;
			j--;
		}
	}
}
}

複製代碼

方案四 排序後相鄰去除法

Array.prototype.myUnique=function(){
	let ary=[];
	let _this=[...this];
	for(let i=0;i<_this.length;i++){
		let item=_this[i],
			nextItem=_this[i+1];
		if(item!==nextItem[i+1]){
			ary.push(item);
		}
	}
	return ary;
}
複製代碼

map

  • 語法: ary.map(function(item,index){})
  • 參數:函數
  • 做用: 遍歷數組中的每一項,每遍歷一次執行一次函數,並把當前項替換成函數執行的返回值,若是函數沒有返回值,或者return後面沒有值,那麼返回的是undefined,統一放在一個新數組中返回
  • 返回值:替換後的新數組
  • 原有數組不變
let ary=[12,23,34,25,36,47];
let curary=ary.map(function(item,index){
	return item+1;
});
console.log(curary);//=>[13,24,35,26,37,48]
console.log(ary);//=>[12,23,34,25,36,47]

----------------
let ary=[12,23,34,25,36,47];
let curary=ary.map(function(item,index){
});
console.log(curary);//=>[undefined,undefined,undefined,undefined,undefined,undefined]
複製代碼

重寫map方法

Array.prototype.myMap = function myMap(callback, context) {
        var ary = [];
        if([].map){
            return this.map(callback,context);
        }
        for(var i=0;i<this.length;i++){
            var res = callback.call(context,this[i],i);
            ary.push(res);
        }
        return ary;

    }
複製代碼

filter

  • 語法:ary.filter(function(item,index){})
  • 參數:函數
  • 做用:過濾數組,把符合條件的當前項放到新的數組中
  • 返回值:符合條件的新數組
  • 原有數組不變
let ary=[12,23,34,25,36,47];
let curary=ary.filter((item,index)=>{
	return item>20&&item<40;
})
console.log(curary);//=>[23,34,25,36]
複製代碼

find

  • 語法:ary.find(function(item,index){})
  • 參數:回調函數
  • 做用:過濾數組,把第一次符合條件的當前項返回
  • 返回值:第一次符合條件的那一項
  • 原有數組不變
let ary=[1,2,3,4,5];
let a=ary.find((item)=>{
    return item>1;
});
console.log(a);//=>2
console.log(ary);//=>[1,2,3,4,5]
複製代碼

findIndex

  • 語法:ary.findIndex(function(item,index){})
  • 參數:回調函數
  • 做用:過濾數組,返回第一次符合條件的當前項對應的索引
  • 返回值:第一次符合條件的當前項的索引
  • 原有數組不變
let ary=[1,2,3,4,5];
let a=ary.find((item)=>{
    return item>1;
});
console.log(a);//=>1
console.log(ary);//=>[1,2,3,4,5]
複製代碼

some

  • 語法:ary.some(function(item,index){});
  • 參數:回調函數
  • 做用:數組中有幾項,回調函數執行幾回,直到回調函數中return結果爲true時,中止遍歷
  • 返回值:true 或者false,看return後面的值是什麼(最終會被轉換爲布爾類型)
  • 原有數組不變
let ary=[1,2,"string",NaN,3,4];
let a=ary.some((item)=>{
    console.log(item);//=>1,2,string
    return typeof item ==="string";
});
console.log(a);//=>true

---------------
let ary=[1,2,"string",NaN,3,4];
let a=ary.some((item)=>{
    console.log(item);//=>1,2,string,NaN,3,4
    return 0;
});
console.log(a);//=>false,由於Boolean(0)=>false
複製代碼

every

  • 語法:ary.every((item,index)=>{});
  • 參數:回調函數
  • 做用:遍歷數組中的每一項,每遍歷一次,就執行一次回調函數,只要遇到回調函數返回值的結果爲false立馬中止遍歷
  • 返回值:true 或者false
  • 原有數組不變
let ary=[1,2,NaN,3,4];
let a=ary.every((item)=>{
    console.log(item);//=>1,2,NaN,3,4
    return typeof item==="number";
});
console.log(a);//=>true
------------
let ary=[1,2,"string",NaN,3,4];
let a=ary.every((item)=>{
    console.log(item);//=>1,2,string
    return typeof item==="number";
});
console.log(a);//=>false
複製代碼

reduce

  • 語法:ary.reduce((prev,item)=>{},init);
  • 參數:回調函數(第一個參數是前一次回調函數的返回結構,第二項是當前項),init表明了傳遞給函數的初始值
  • 做用:做爲累加器,數組中的每一個值(從左到右開始縮減),最終計算爲一個值
  • 返回值:最終獲得的結果
  • 原有數組不變
let ary=[1,1,1,1,1,,1,1,1,1,1];
let a=ary.reduce((prev,item)=>{
    console.log(prev, item);
    return prev-item;
},10);
console.log(a);//=>0,遇到空位直接跳過
console.log(ary);//=>[1,1,1,1,1,,1,1,1,1,1];
複製代碼

reduceRight

  • 語法:ary.reduceRight((prev,item)=>{},init)
  • 參數:回調函數(第一個參數是前一次回調函數的返回結構,第二項是當前項),init表明了傳遞給函數的初始值
  • 做用:做爲累加器,數組中的每一個值(從右到左開始縮減),最終計算爲一個值
  • 返回值:最終獲得的結果
  • 原有數組不變
let ary=[-1,1,-1,1];
let b=ary.reduceRight((prev,item)=>{
    console.log(prev, item);
    return prev*item;//=>10*1*-1*1*-1
},10);
console.log(b);//=>10
複製代碼

JS中關於字符串的一些細節知識

在JS中全部用單引號或者雙引號包起來的都是字符串,每個字符串是由零到多個字符組成

var str = 'zhufengpeixun';
str.length ->字符串長度
str[0] ->'z'
str[str.length-1] ->'n'
str[100] ->undefined

//=>字符串中的每個字符,都有一個本身對應的索引,也有相似於數組同樣的length表明本身的長度

//=>循環遍歷字符串,輸出每一項字符 
for(var i=0;i<str.length;i++){
	console.log(str[i]);
}
複製代碼

字符串的經常使用方法

字符串是基本數據類型,字符串的每一次操做都是值直接的進行操做,不像數組同樣是基於空間地址來操做的,因此不存在原有字符串是否改變這一說,確定都是不變的

charAt && charCodeAt

  • 語法:str.charAt(索引)
  • 做用:charAt根據索引獲取指定位置的字符,charCodeAt不只僅獲取字符,它獲取的是字符對應的Unicode編碼值(ASCII)
  • 參數:索引
  • 返回值:字符或者對應的編碼

indexOf && lastIndexOf

基於這兩個方法,能夠獲取字符在字符串中第一次或者最後一次出現位置的索引,有這個字符,返回大於等於零的索引,不包含這個字符,返回的結果是-1,因此能夠基於這兩個方法,驗證當前字符串中是否包含某個字符

var str = 'zhufengpeixun';
if(str.indexof('@')>-1){
	//=>條件成立說明包含@符號
}
複製代碼

slice

  • 語法:str.slice(n,m)
  • 做用:str.slice(n,m)從索引n開始找到索引爲m處(不包含m),把找到的字符當作新字符串返回
  • 返回值:截取的字符串

substring

  • 語法:str.substring(n,m)
  • 做用:str.substring(n,m)從索引n開始找到索引爲m處(不包含m),把找到的字符當作新字符串返回,不支持負數做爲索引
  • 返回值:截取的字符串

substr

  • 語法:str.substr(n,m)
  • 做用:從索引n開始截取m個字符

toUpperCase && toLowerCase

  • 語法:str.toUpperCase()/str.toLowerCase()
  • 做用:實現字母的大小寫轉換
    • toUpperCase 小寫轉化爲大寫
    • toLowerCase 大寫轉換爲小寫
  • 參數:無

split

  • 語法:str.split()
  • 做用:和數組中的join相對應,數組中的join是把數組每一項按照指定的鏈接符變爲字符串,而split是把字符串按照指定的分隔符,拆分紅數組中每一項

replace

  • 語法:str.replace(原有字符,要替換的新字符)
  • 做用:替換字符串中的原有字符
  • 返回:替換後的字符串

真實項目中的需求

1.時間字符串格式化

需求:有一個時間字符串"2018-4-4 16:26:8".咱們想基於這個字符串獲取到"04月04日 16時26分"

var str="2018-4-4 16:26:8",
    ary=str.split(' '),
	aryLeft=ary[0],
	aryRight=ary[1];
	month=aryLeft.split('-')[1],
	day=aryLeft.split('-')[2],
	hour=aryRight.split(':')[0],
	minute=aryRight.split(':')[1];

function fn(n){
	return n<10?"0"+n:n;
}
var date=fn(month)+'月'+fn(day)+'日 '+fn(hour)+'時'+fn(minute)+'分'

console.log(date);
	
--------------正則
let reg=/^(\d{4})[-/](0?[1-9]|1[0-2])[-/](0?[1-9]|[12]\d|3[01])\s+(0?[1-9]|1\d|2[0-3]):(0?\d|[1-5]\d):(0[1-9]|[1-5]\d)$/;
console.log(reg.exec(str));
複製代碼

2.URL地址問號傳參解析

有一個URL地址"www.zhufengpeixun.cn/stu/?1x=1&a…"地址問號後面的內容是咱們須要解析出來的參數信息 { 1x:1, name:'AA', sex:'man' }

var str="http://www.zhufengpeixun.cn/stu/?1x=1&name=AA&sex=man#teacher";
var indexASK=str.indexOf("?");
var indexWell=str.indexOf('#');

if(indexWell>-1){
	str=str.substring(indexASK+1,indexWell);
}else{
	str=str.substr(indexASK+1);
	
}
var ary=str.split('&');
var obj={};
for(var i=0;i<ary.length;i++){
	var curary=ary[i].split('=');
	obj[curary[0]]=curary[1];
}

複製代碼

案例:獲取URL問號後傳參值--函數封裝

function queryParameter(URL){
    var indexASK=URL.indexOf("?"),
        indexWell=URL.indexOf('#');
    indexWell>-1?URL=URL.substring(indexASK+1,indexWell):URL=URL.substring(indexASk+1);
    var ary=URL.split('&'),
	    obj={};
    for(var i=0;i<ary.length;i++){
		var item=ary[i],
		    curary=item.split("=");
		    obj[curary[0]]=curary[1];
    }
    return obj;
}
複製代碼

JS中的數學函數

Math稱爲數學函數,可是屬於對象類型的

typeof Math//=>'object'
複製代碼

之因此叫作數學函數,是由於Math這個對象中提供了不少操做數字的方法

Math中提供的經常使用方法

abs

  • 語法:Math.abs()
  • 做用:取絕對值

ceil && floor

  • 語法:Math.ceil()
  • 做用:向上/向下取整

round

  • 語法:Math.round()
  • 做用:四捨五入

sqrt

  • 語法:Math.sqrt()
  • 做用:開平方

pow

  • 語法:Math.pow(n,m)
  • 做用:n的m次方

max && min

  • 語法:Math.max()
  • 做用:獲取最大值或最小值

PI

  • 語法:Math.PI()
  • 做用:獲取圓周率

random

  • 語法:Math.random()
  • 做用:獲取[0,1)的隨機小數

獲取[n,m]之間的隨機整數 Math.round(Math.random()*(m-n)+n)

獲取四位隨機驗證碼--封裝函數

function queryCode(str){
    var result="";
    while(result.length<4){
        var mathIndex=Math.round(Math.random()*(str.length-1));
        result.indexOf(str.charAt(mathIndex))===-1?result+=str.charAt(mathIndex):null;
    }
    return result;
}
queryCode();
複製代碼

函數

function fn(n,m){//=>形參:入口
	//=>函數體
	var total = 0;
	total=n+m;
	console.log(total)
}
fn(10,20);//=>實參:給形參傳遞的具體值
/* * var a =12; * fn(a,1===1?10:0);//=>實參必定是值,即便咱們寫的是變量或者表達式,也是把變量或者表達式計算的結果做爲值傳遞給形參變量 */
複製代碼

函數執行的時候,都會造成一個全新的私有做用域(私有的棧內存),目的是:

  • 1.把原有堆內存中存儲的字符串變爲JS表達式執行
  • 2.保護裏面的私有變量不受外界的干擾(和外界是隔離的) 咱們把函數執行的這種保護機制,稱之爲**"閉包"**

function fn(n,m){
	var total=0; //=>total:私有變量
	total=n+m;
}
fn(10,20);
console.log(total);//=>Uncaught ReferenceError: total is not defined TOTAL是私有變量,咱們沒法在函數的外面直接獲取這個值(閉包)
複製代碼

函數中的return

  • 函數的入口:形參
  • 函數的出口:返回值 return
  • 把函數運行的結果(或者函數體中的部分信息)拿到函數外面去使用
function fn(n,m){
	var total = 0;
	total = n+m;
	return total;//=>並非把total變量返回,返回的是變量存儲的值,return返回的永遠是一個值
}
fn //=>表明的是函數自己(函數自己也是個值,自己表明的是堆內存中的代碼字符串)
fn(10,20);//=>表明的是函數執行(不只如此,它表明的是函數執行後,返回的結果[return返回的值])
複製代碼
function fn(n,m){
	var total = 0;
	total = n+m;
}
var res = fn(10,20);//=>若是當前函數沒有return結果出來(或者return;啥也沒返回),函數執行在外面拿到的結果都是 undefined
複製代碼
function fn(n,m){
	//=>若是n/m有一個沒有傳遞值,咱們返回零
	if(n===undefined || m===undefined){
		return 0;//=>return還有一個做用:相似於循環中的break,可以強制結果函數體中代碼的執行(return後面的代碼不在執行)
}
	var total=0;
	total=n+m;
	return total;
}
fn(10);//=>此時n=10,m爲undefined,至關於10+undefined,Number(undefined)=>NaN,10+NaN=>NaN



===知識點1===
1、n===undefined 常常這樣判斷n的值是否爲undefined,這種方式能夠
2、n==undefined 這種模式很差,由於null==undefined也是相等的(===比較纔不相等)
3typeof n=='undefined' 項目中開發者更喜歡這種判斷模式



===知識點2===
1、total=0; 0是有值的,值時0,從內存方面來講,會在棧內存中佔一個位置
2、total=null; 開發者更喜歡用null來做爲初始值,null是空對象指針,是不佔內存的;

複製代碼

函數中的arguments

形參是有侷限性的:咱們須要具體的知道用戶和執行的時候傳遞實參數量、順序等,纔可使用形參變量定義對應的入口

arguments:函數內置的實參集合(內置:函數天生就存在的機制,無論你是否設置了形參,也無論你是否傳遞了實參,arguments都有,始終存在的)

function sum(){
	console.log(arguments);
}

複製代碼

argument是一個類數組,不是數組,不能直接使用數組中的方法

即便設置形參變量,形參該是什麼值仍是什麼值,可是arguments使用存儲的是全部傳遞進來的實參,因此它被稱爲實參集合

function sum(){
	console.log(arguments.callee===sum);//=>true
}
複製代碼

案例:任意數求和

//=>思路:先將實參中的每一項都轉換爲數字類型,若是是有效數字則累加,不然,不累加

function sum(){
	var total=null;
	for(var i=0;i<arguments.length;i++){
		var item=arguments[i];
		if(!isNaN(Number(item))){ 
			total+=Number(item);
}
}
return total;
}
複製代碼

實名函數和匿名函數

  • 實名函數:有函數名的
  • 匿名函數:沒有函數名的
    • 函數表達式:把函數當作值賦值給變量或者元素的事件
    • 自執行函數:建立和執行一塊兒完成的,自執行函數正常寫法是"(function(){...})();"可是,JS中會將以」function「 開頭的語句認定爲函數聲明語句,而自執行函數獲得的是一個值,因此不能夠直接這樣寫。因此要以運算符或者括號開頭~func...或者以變量接收var a=function(){...}();
===函數表達式===

var fn=function (){

}

oBox.onclick=function (){

}


===自執行函數
(function (){})();

//=>由於自執行函數不能以function作開頭,因此function前加上運算符。

~function(){
		console.log(this)    //=>Window
	}();
	//return 值爲~undefined=>-1
	//二進制否運算符(~)將每一個二進制位都變爲相反值(0變爲1,1變爲0)。
		
!function(){
		console.log(this)    //=>Window
	}();
	//return 值爲!undefined=>true
	
-function(){
		console.log(this)    //=>Window
	}();
	//return 值爲-undefined=>NaN

+function(){
			console.log(this)    //=>Window
	}();
	//return 值爲+undefined=>NaN
	

複製代碼

DOM

DOM樹

dom tree 當瀏覽器加載HTML頁面的時候,首先就是DOM結構的計算,計算出來的DOM結構就是DOM樹(把頁面中的HTML標籤像樹狀結構同樣,分析出之間的層級關係)

DOM樹描述了標籤和標籤之間的關係(節點間的關係),咱們只要知道任何一個標籤,均可以依據DOM中提供的屬性和方法,獲取到頁面中任意一個標籤或者節點

獲取DOM元素的方法

getElementById

經過元素的ID獲取指定的元素對象,使用的時候都是document.getELementById("")此處的document是限定了獲取元素的範圍,把它稱之爲"上下文(context)"

一、getElementById的上下文只能是document 由於嚴格意義上一個頁面的id是不能重複的,瀏覽器規定在整個文檔中既能夠獲取這個惟一的ID

二、 若是頁面中的ID重複了,咱們基於這個方法只能獲取到第一個元素,後面相同ID元素沒法獲取

三、在IE6-7瀏覽器中,會把表單元素(input)的name屬性值當作ID來使用(建議:之後使用表單元素的時候,不要讓name和id的值有衝突)

getElementsByTagName

[context].getElementsByTagName在指定的上下文中,根據標籤名獲取到一組元素集合(HTMLCollection)

一、 獲取的元素集合是一個類數組(不能直接使用數組的方法) 二、它會把當前上下文中,子子孫孫(後代)層級內的標籤都獲取到(獲取的不只僅是兒子級的) 三、基於這個方法得到的結果永遠都是一個集合(無論裏面是否有內容,也無論有幾項,它是一個容器或者集合),若是想操做集合中具體的某一項,須要基於索引獲取到才能夠

案例:尋找全部id爲HAHA的元素

思路:先得到id爲box的div下的全部元素,獲得一個類數組,建立一個新數組,再遍歷類數組中的每一項,若是id等於HAHA則存儲到數組中

第一種方案

<div class="box" id="box">
    <ul>
        <li class="item1 item2">新聞</li>
        <li class="item1">電影</li>
        <li class="item2">音樂</li>
    </ul>
    <div id="HAHA" name="hobby">最新新聞</div>
    <div>最新電影</div>
    <div id="HAHA">最新音樂</div>
</div>

var oBox=document.getElementById('box'),
    nodeList=oBox.getElementsByTagName('*'),
    ary=[];
function queryAllById(id){
	for(var i=0;i<nodeList;i++){
		var item=nodeList[i];
		item.id===id?ary.push(item):null;
	}
	return ary;
}
複製代碼

第二種方案

console.log(HAHA);
//=>HAHA爲id名
複製代碼

在JS中,默認會把元素的ID設置爲變量(不須要再獲取設置),並且ID重複,獲取的結果就是一個集合,包含全部ID項,不重複就是一個元素對象(相似於ById獲取的結果)

getELementsByClassName

[context].getELementsByClassName()在指定的上下文中,基於元素的樣式類名(class="xxx")獲取到一組元素集合

一、真實項目中,咱們常常是基於樣式類來給元素設置樣式,因此在JS中,咱們也會常常基於樣式類來獲取元素,可是此方法在IE6-8下不兼容

兼容處理方案

Node.prototype.queryElementsByClassName = function queryElementsByClassName() {
    if (arguments.length === 0) return [];
    var strClass = arguments[0],
        nodeList = utils.toArray(this.getElementsByTagName('*'));
    strClass = strClass.replace(/^ +| +$/g, '').split(/ +/);
    for (var i = 0; i < strClass.length; i++) {
        var reg = new RegExp('(^| +)' + strClass[i] + '( +|$)');
        for (var k = 0; k < nodeList.length; k++) {
            if (!reg.test(nodeList[k].className)) {
                nodeList.splice(k, 1);
                k--;
            }
        }
    }
    return nodeList;
};
複製代碼

getElementsByName

document.getElementsByName()它的上下文也只能是document,在整個文檔中,基於元素的name屬性值獲取一組節點集合(也是一個類數組)

一、在IE9及如下版本瀏覽器當中,只對表單元素的name屬性起做用(正常來講,咱們項目中只會給表單元素設置name,給非表單元素設置name,實際上是一個不太符合規範的操做)

querySelector

[context].querySelector()在指定的上下文中基於選擇器(相似於CSS選擇器)獲取到指定的元素對象(獲取到的是一個元素,哪怕選擇器匹配了多個,咱們只獲取第一個)

querySelectorAll >在querySelector的基礎上,咱們獲取到選擇器匹配到的全部元素,結果是一個節點集合(NodeList)

querySelector/querySelectorAll都是不兼容IE6-8瀏覽器的,不考慮兼容的狀況下,咱們能用byid或者其它方式獲取的,也儘可能不要用這兩個方法,這兩個方法性能消耗較大

<div id="div1" class="fon mark" name="div1">01</div>
<div id="div2" class="mark">02</div>
<div id="div1" class="fon">03</div>

<script>
    console.log(document.querySelectorAll("#div1"));/*ID選擇器*/
    console.log(document.querySelectorAll('.mark'));/*類選擇器*/
    console.log(document.querySelectorAll('body>div'));/*子級選擇器*/
    console.log(document.querySelectorAll('div'));/*標籤選擇器*/
    console.log(document.querySelectorAll("body div"));/*後代選擇器*/
    console.log(document.querySelectorAll("div[name='div1']"));/*標籤屬性選擇器*/
    console.log(document.querySelectorAll("*"));/*通配符選擇器*/
</script>
複製代碼

document.head

獲取head元素對象 直接調取document這個實例上的head屬性

document.body

獲取body元素對象 直接調取document這個實例上的body屬性

document.documentElement

獲取HTML元素對象 直接調取document這個實例上的documentElement屬性

//=>需求:獲取瀏覽器一屏幕的寬度和高度(兼容全部的瀏覽器)

document.documentELement.clientWidth ||
document.body.clientWidth

document.documentELment.clien
tHeight ||
document.body.clientHeight
複製代碼

節點(node)

在一個HTML文檔中出現的全部東西都是節點

  • 元素節點(HTML標籤)
  • 文本節點(文字內容、空格、換行)
  • 註釋節點(註釋內容)
  • 文檔節點(document)
  • ...

每一種類型的節點都會有一些屬性區分本身的特性和特徵

  • nodeType:節點類型
  • nodeName:節點名稱
  • nodeValue:節點值

元素節點

  • nodeType:1
  • nodeName:大寫標籤名
  • nodeValue:null

文本節點

  • nodeType:3
  • nodeName:"#text"
  • nodeValue:文本內容

註釋節點

  • nodeType:8
  • nodeName:"#comment"
  • nodeValue:註釋內容

文檔節點

  • nodeType:9
  • nodeName:"#document"
  • nodeValue:null

描述節點之間關係的屬性

parentNode

獲取當前節點惟一的父親節點

childNodes

獲取當前節點的全部子節點

  • 子節點:只得到兒子級別的
  • 全部:包含元素節點、文本節點等

children

獲取當前節點全部的元素子節點 在IE6-8中會把註釋節點也當作元素節點獲取到,因此兼容性很差

firstChild

獲取當前節點的第一個子節點(多是元素或者文本)

firsrElementChild

獲取當前節點的第一個元素子節點 在IE6-8中不兼容

lastChild

獲取當前節點的最後一個子節點(多是元素或者文本)

lastElementChild

獲取當前節點的最後一個元素子節點 在IE6-8中不兼容

previousSibling

獲取當前節點的上一個哥哥節點(獲取的哥哥多是元素也多是文本等)

previousElementSibling

獲取上一個哥哥元素節點(不兼容IE6-8)

nextSibling

獲取當前節點的下一個弟弟節點(獲取的哥哥多是元素也多是文本等)

nextElemnentSibling

獲取下一個弟弟元素節點(不兼容IE6-8)

兼容處理1--獲取當前元素的全部元素子節點

基於children不兼容IE低版本瀏覽器(會把註釋當作元素節點)

//=>思路:首先獲取當前元素下全部的子節點,而後遍歷這些節點,篩選出元素的(nodeType===1),把篩選出來的結果單獨存儲起來便可

/* *children:get all the element nodes of the current element *@parameter * curEle:[object] current element *@return * [Array] all the element nodes *by team on 2018/04/07 12:36 */
function children(curEle){
	var childEle=curEle.childNodes;
	var aryEle=[];
	for(var i=0;i<childEle.length;i++){
		var item=childEle[i];
		if(item.nodeType===1){
			aryEle.push(item);
		}
	}
	return aryEle;
}

複製代碼

兼容處理2--獲取當前元素的上一個哥哥元素節點

基於previousElementSibling不兼容IE低版本瀏覽器

//=>先找當前元素的哥哥節點,看是否爲元素節點,不是的話,基於哥哥,找哥哥的上一個哥哥節點...一直到找到元素節點或者已經沒有哥哥了(說明我就是老大)則結束查找
/* *prev:get the last elder brother element node of the current element *@parameter * curEle:[object] current element *@return * [object] last elder brother element *by team on 2018/04/07 12:48 */
function prev(curEle){
   var item=curEle.previousSibling;
	   while(item && item.nodeType!==1){//=>item是爲了驗證當前這個元素是否還設有,若是沒有item會爲null,Boolean(item)=>false
		   item=item.previousSibling;
	   }
	   return item;
}
複製代碼

兼容處理3---得到當前項下一個弟弟元素節點

思路:先找到當前項的弟弟節點,判斷該弟弟節點的nodeType===1,若是不等於就繼續往前找 一直找到末尾

/* * next:get the next element of the current element * @parameter:[object] the current element * return:the next element * by Fay on 17:58 */
function next(curEle){
	var item=curEle.nextSibling;
	while(item && item.nodeType!==1){
		item=item.nextSibling;
	}
	return item;
}
複製代碼

兼容處理4--獲取當前項全部的弟弟元素節點

思路:先獲取當前元素的弟弟節點,建立一個空數組,若是當前元素的弟弟節點的nodeType===1則存起來,一直往下找找到末尾

/* * nextAll:get all of the next elements by the current element * @parameter:[object] the current element * return: all of the next elements * by Fay on 18:06 */
function nexAll(curEle){
	var item=curEle.nextSibling,
		ary=[];
	while(item){
		item.nodeType===1?ary.push(item):null;
		item=item.nextSibling;
	}
	return ary;
}
複製代碼

兼容處理5--獲取當前項全部的哥哥元素節點

/* * preAll:get all of the previous elements by the current element; * @parameter:[object] the current element * return:[object] all of the previous elements * by Fay on 18:11 */
function preAll(curEle){
	var item=curEle.previousSibling,
		ary=[];
	while(item){
		item.nodeType===1?ary.push(item):null;
		item=item.previousSibling;
	}
	return ary;
}
複製代碼

兼容處理6--得到當前項的全部兄弟元素節點

思路:將全部的哥哥元素節點與全部的弟弟元素節點相加

/* * siblings:get all siblings elements by the current element * @parameter:[object] the current element * return:all siblings elements * by Fay on 18:25 */
function siblings(curEle){
	var preItem=curEle.previousSibling,
		nextItem=curEle.nextSibling,
		ary=[];
	while(preItem){
		preItem.nodeType===1?ary.push(preItem):null;
		preItem=preItem.previousSibling;
	}
	while(nextItem){
		nextItem.nodeType===1?ary.push(nextItem):null;
		nextItem=nextItem.nextSibling;
	}
	return ary;
}
複製代碼

兼容處理7--得到當前項的索引

思路:當前元素有多少個哥哥節點,索引就是多少,即獲取當前項哥哥節點的個數

/* * index:get the index of the current element * @parameter:[object] the current element * return:[number] the index of the current element * by Fay on 18:17 */
function index(curEle){
	var item=curEle.previousSibling,
		ary=[];
	while(item){
		ary.push(item);
		item=item.previousSibling;
	}
	return ary.length;
}
複製代碼

關於DOM的增刪改

createElement

建立一個元素標籤(元素對象) document.createELement([標籤名]) Document類原型上的屬性,屬性值是函數

案例:經過動態建立元素快速獲取queryURLParameter

a元素有一些內置屬性:

  • hash:存儲了哈希值 '#teacher'
  • search:問號傳遞參數值,沒有傳遞是空字符串 '?name=bd&age=10'
  • hostname:域名 'www.baidu.cn'
  • pathname:路徑 '/stu/'
function queryURLParameter(url){
var link=document.createElement('a');
link.href=url;
var search=link.search;
if(search.length===0) return;
   url=search.substr(1);
   var ary=url.split('&'),
    obj={};
for(var i=0;i<ary.length;i++){
	var curary=ary[i].split('=');
	obj[curary[0]]=curary[1];
}
	link=null
	return obj;
}
複製代碼

appendChild

把一個元素對象插入到指定容器的末尾

[container].appendChild([newELe])

Node類原型上的屬性,屬性值是函數

var newP = document.createElement('p');
document.body.appendChild(newP);
newP.innerHTML = '我是P!!';
newP.style.backgroundColor = 'red';
複製代碼

insertBefore

把一個元素對象插入到指定容器中某一個元素標籤以前

[container].insertBefore([newEle],[oldEle])

Node類原型上的屬性,屬性值是函數

<div id="box2" class="box">2</div>
//=>建立
    var oDiv = document.createElement('div');
     oDiv.id='div1';
    oDiv.className='box';
    oDiv.innerText='1';

document.body.insertBefore(oDiv,document.getElementById('box2'));

//也能夠這樣寫,直接用id名

document.body.insertBefore(oDiv,box2);
複製代碼

cloneNode

把某一個節點進行克隆 [curELe].cloneNode():淺克隆,只克隆當前的標籤 [curELe].cloneNode(true):深克隆,當前標籤及其裏面的內容都一塊兒克隆了

Node類原型上的屬性,屬性值是函數

<div class="box" id="box1">1</div>
<div class="box" id="box2">2</div>

<script>
    var box1=document.getElementById('box1'),
        box2=document.getElementById('box2');
    var box3=box2.cloneNode();
    document.body.appendChild(box3);
    var box4=box2.cloneNode(true);
    document.body.appendChild(box4);
</script>
複製代碼

removeChild

在指定容器中刪除某一個元素 [container].removeChild([curEle]) Node類原型上的屬性,屬性值是函數

set/get/removeAttribute

設置/獲取/刪除 當前元素的某一個自定義屬性 設置的自定義屬性值最終都會以字符串的形式展示 [container].setAttribute([key],[value]) Element類原型上的屬性,屬性值是函數

使用xxx.index=0和xxx.setAttribute('index',0)這兩種設置自定義屬性的區別?

xxx.index:是把當前操做的元素當作一個普通對象,爲其設置一個屬性名(和頁面中的HTML標籤不要緊)

xxx.setAttribute:把元素當作特殊的元素對象來處理,設置的自定義屬性和頁面結構中的DOM元素映射在一塊兒的

使用DOM方法設置的自定義屬性與對象設置自定義屬性沒法互相獲取,兩種方法是獨立的

  • 第一種是基於對象鍵值對操做方式,修改當前元素對象的堆內存空間來完成
  • 第二種是直接修改頁面中的HTML標籤的結構來完成(此種方法設置的自定義屬性能夠在結構上呈現出來)

相關文章
相關標籤/搜索