JS高级语法与JS选择器
元素(element)和節點(node)
childNode屬性和children屬性的區別
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="parentDiv">
<!--注釋-->
<div></div>
</div>
<script>
console.log(document.getElementById('parentDiv').childNodes); //NodeList[5]
console.log(document.getElementById('parentDiv').children) ; //HTMLCollection[1]
</script>
</body>
</html>
childNodes屬性返回的是NodeList數組,是屬于節點(也包括元素)的屬性,而children屬性返回的是子元素,是屬于元素的屬性
而在Nodelist數組里面也有元素存在,證明了元素也是節點的一種,即元素節點。
W3C中的解釋是:
在 HTML DOM (文檔對象模型)中,每個部分都是節點 文檔本身是文檔節點 所有 HTML 元素是元素節點 所有 HTML 屬性是屬性節點 HTML 元素內的文本是文本節點 (包括回車符,空格,空白字符也是屬于文本節點) 注釋是注釋節點
Element 對象可以擁有類型為元素節點、文本節點、注釋節點的子節點。
NodeList 對象表示節點列表,比如 HTML 元素的子節點集合。
元素也可以擁有屬性。屬性是屬性節點。
總結:元素是元素節點,是節點中的一種,但元素節點中可以包含很多的節點
nodeName(純大寫) 屬性含有某個節點的名稱
元素節點的nodeName 是標簽名稱 屬性節點的nodeName 是屬性名稱 文本節點的nodeName 永遠是 #text 文檔節點的nodeName 永遠是 #document
nodeValue 對于文本節點,nodeValue 屬性包含文本。 對于屬性節點,nodeValue 屬性包含屬性值
nodeValue 屬性對于文檔節點和元素節點是不可用的
nodeType 屬性可返回節點的類型
Element 元素 1 Attribute 屬性 2 Text 文本 3 CDATA Section CDATA斷 4 Entity Reference 實體參數 5 Entity 實體 6 Processing Instrucion 處理指令 7 Comment 注釋 8 Document 文檔 9 Document Type 文檔類型 10 Document Fragment 文檔片斷 11
添加和刪除節點(HTML 元素)
創建新的 HTML 元素
如需向 HTML DOM 添加新元素,您必須首先創建該元素(元素節點),然后向一個已存在的元素追加該元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="div1">
<p id="p1">這是一個段落</p>
<p id="p2">這是另一個段落</p>
</div>
</body>
<script>
var para=document.createElement("p");
var node=document.createTextNode("這是新段落。");
para.appendChild(node);
var element=document.getElementById("div1");
element.appendChild(para);
</script>
</html>
<!-- 為這段代碼創建新的 <p> 元素:
var para=document.createElement("p");
此時檢查頁面可以看到div里面已經生成了<p>元素
如需向 <p> 元素添加文本,您必須首先創建文本節點。
這段代碼創建了一個文本節點:
var node=document.createTextNode("這是新段落。");
然后您必須向 <p> 元素追加這個文本節點:
para.appendChild(node);
最后您必須向一個已有的元素追加這個新元素。
這段代碼找到一個已有的元素:
var element=document.getElementById("div1");
這段代碼向這個已有的元素追加新元素:
element.appendChild(para); -->
刪除已有的 HTML 元素
如需刪除 HTML 元素,您必須首先獲得該元素的父元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="div1">
<p id="p1">這是一個段落。</p>
<p id="p2">這是另一個段落。</p>
</div>
</body>
<script>
var parent=document.getElementById("div1");
var child=document.getElementById("p1");
parent.removeChild(child);
</script>
</html>
<!-- 例子解釋:
這個 HTML 文檔含有擁有兩個子節點(兩個 <p> 元素)的 <div> 元素:
<div id="div1">
<p id="p1">這是一個段落。</p>
<p id="p2">這是另一個段落。</p>
</div>
找到 id="div1" 的元素:
var parent=document.getElementById("div1");
找到 id="p1" 的 <p> 元素:
var child=document.getElementById("p1");
從父元素中刪除子元素:
parent.removeChild(child);
提示:如果能夠在不引用父元素的情況下刪除某個元素,就太好了。
不過很遺憾。DOM 需要清楚您需要刪除的元素,以及它的父元素。
這是常用的解決方案:
找到您希望刪除的子元素,然后使用其 parentNode 屬性來找到父元素:
var child=document.getElementById("p1");
child.parentNode.removeChild(child); -->
常用節點操作
1.節點查找
document.getElementById,document.getElementByTagName,document.getElementByName ,document.getElementByClassName
document.querySelector() 參數為選擇器
document.forms 選取頁面中的所有表單元素
2.增加節點
增加節點前必須先使用document.createElement()創建元素節點,參數為標簽名
m.appendChild(n) 為m元素在末尾添加n節點
m.insertBefore(k,n) 在m元素的k節點前添加n節點
3.刪除節點
m.removeChild(n)刪除m元素中的n節點
m.replaceChild(k,n)用n節點取代m元素中的k節點
4.復制節點
m.cloneChild() 復制m節點,并將復制出來的節點作為返回值
參數為true時,則將m元素的后代元素也一并復制。否則,僅復制m元素本身
節點屬性操作
節點(自身)屬性:
attributes - 節點(元素)的 屬性節點
nodeType – 節點類型
nodeValue – 節點值
nodeName – 節點名稱
innerHTML - 節點(元素)的文本值
1.節點屬性值選取
m.屬性名 (:駝峰形式 ) m.className
m[“屬性名”] m.['className']
m.getAttribute(“屬性名”) :加引號,html的形式 m.getAttribute("class")
2.節點屬性修改
前兩種選取方法時,直接賦值即可
m.setAttribute("屬性名",“值”)
3.創建屬性節點并設置屬性值
var info_node=document.createAttribute("info");//創建
info_node.value='123';//設置
sup1.setAttributeNode(info_node);//添加
4.復制節點
var body = document.querySelector('body');
true深拷貝,拷貝自身與內容, false淺拷貝,只拷貝自身標簽
var cl_body = body.cloneNode(true);
console.log(cl_body);
JS DOM節點(當前標簽和同級、父級、子級..之間的關系)
1. 通過頂層document節點獲取
1) document.getElementById(elementId) //根據id獲得
2) document.getElementsByName(elementName) //根據name獲得
3) document.getElementsByTagName(tagName) //根據標簽名獲得
2、通過父節點獲取
1) parentObj.firstChild //獲得第一個子節點
2) parentObj.lastChild //獲得第二個子節點
3) parentObj.childNodes //獲取作為指定對象直接后代的HTML元素和TextNode對象的集合
4) parentObj.children //非標準dom集合,建議使用childNodes
5) parentObj.getElementsByTagName(tagName) //獲得該標簽下標簽名為tagName的所有標簽
3、通過臨近節點獲取
1) neighbourNode.previousSibling //獲得同級前一個標簽
2) neighbourNode.nextSibling //獲得同級后一個標簽
4、通過子節點獲取
1) childNode.parentNode //獲得父標簽
事件
onload:頁面加載完畢事件,只附屬于window對象 onclick:鼠標點擊時間 onmouseover:鼠標懸浮事件 onmouseout:鼠標移開事件
on事件綁定方式
document.onclick = function() {
console.log("文檔點擊");
}
on事件只能綁定一個方法,重復綁定保留最后一次綁定的方法
document.onclick = function() {
console.log("文檔點擊");
}
事件的移除
document.onclick = null;
非on事件綁定方式
document.addEventListener('click', function() {
console.log("點擊1");
})
document.addEventListener('click', function() {
console.log("點擊2");
})
非on事件可以同時綁定多個方法,被綁定的方法依次被執行
addEventListener第三個參數(true|false)決定冒泡的方式
function fn () {}
document.addEventListener('click', fn);
事件的移除
document.removeEventListener('click', fn,false);
事件的三種綁定方式的思考
方法一:嵌入dom
把onclick綁定在標簽上
HTML元素行間事件(也可以叫HTMl事件處理程序),直接在html標簽里添加事件。
缺點:html和js代碼緊密耦合
<input id="btn1" type="button" onclick="test();" />
方法二:直接綁定
onclick的js綁定辦法
//把一個函數賦值給一個事件處理程序屬性。(這種方式也叫做Dom0級事件處理程序)
var btn1 = document.getElementById('btn1');
function abc() {
alert('abc');
}
btn1.onclick = abc; //當點擊的時候執行abc這個函數,等價于 btn1.onclick=function abc(){alert('abc');}
//btn1.onclick = null; //去掉綁定的事件
方法三:事件監聽
click的js綁定辦法(js的話推薦這種)
//通過“事件監聽”的方式來綁定事件(也叫Dom2級事件處理程序)
var btn2 = document.getElementById('btn2');
btn2.addEventListener('click', showMsg, false); //鼠標單擊的時候調用showMes這個函數
function showMsg() {
alert("事件監聽");
}
//btn2.removeEventListener('click', showMsg, false); //去除綁定
方法一
最原始的寫法:和html混合在一起寫,缺點是代碼高冗余,且無法添加多個事件處理函數如上文對事件的舉例則為典型的**html事件處理程序*寫法
方法二
dom0級:將html代碼和js代碼分離,且支持匿名函數,可以看到完美的改進了1的冗余缺憾,所有的事件相關操作都在js中完成
方法三
dom2級:ie使用attachEventListener其他非ie使用addEventListener,可以支持綁定多個事件,瞧吧,又一個缺憾被完美解決了~,而且dom2級還可以自定義事件流,下一篇會分析事件流模型
dom3級:對事件進行了更廣而全的分類,請自行查閱
實例運用一
</head>
<body>
<div class="div"></div>
<div class="div"></div>
</body>
<script>
// js事件: 頁面標簽在滿足某種條件下可以完成指定功能的這種過程, 成之為事件
// 某種條件: 如鼠標點擊標簽: 點擊事件 | 鼠標雙擊標簽: 雙擊事件 | 鍵盤按下: 鍵盤按下事件
// 指定功能: 就是開發者根據實際需求完整相應的功能實現
// 鉤子函數: 就是滿足某種條件被系統回調的函數(完成指定功能)
// 點擊事件: 明確激活鉤子的條件 = 激活鉤子后改處理什么邏輯, 完成指定功能(函數)
var div = document.querySelector(".div"); // 找到的是第一個.div
div.onclick = function () {
// alert(123)
this.style.backgroundColor = "pink";
}
// 明確第一個及第二個
var divs = document.querySelectorAll('.div');
divs[1].ondblclick = function () {
divs[0].style.backgroundColor = "yellow";
}
</script>
</html>
實例運用二
復習并延伸
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>復習預習</title>
<style>
[key='value'] {
color: #0f8209;
}
</style>
</head>
<body>
<div class="ele" alert="OK">div div div</div>
</body>
<script>
// 1.面向對象js
// ES5
// 普通的單一對象
var obj = {
// 普通對象的屬性
key: "value",
fn: function () {
console.log("普通對象的方法")
}
};
console.log(obj.key);
console.log(obj["key"]);
// 1.key的類型為字符串類型
// 結論:
// js支持的標識符可以省略引號, 反之不可以省略
// 不支持的標識符訪問方式: 不可以采用.語法,需要采用[]語法,eg:obj["background-color"]
var obj1 = {
"name": "obj1",
// key有時候會出現js不能直接支持的標識符書寫方式
// 需求: obj1用來描述頁面標簽的各種顏色
color: "red",
// "color": "red",
"background-color": "yellow"
}
console.log(obj1.name);
console.log(obj1["name"]);
console.log(obj1.color);
// obj1.background = 12;
// color = 10;
console.log(obj1["background-color"]);
// 2. 對象可以任意添加或刪除屬性
var obj2 = {
name: "obj2"
};
console.log(obj2);
// 刪除屬性
delete obj2.name;
console.log(obj2);
// 添加屬性
obj2.age = 8;
console.log(obj2);
// 拓展: 獲取的頁面元素就是標簽對象, 可以對其添加任意屬性
var ele = document.querySelector('.ele');
console.log(ele.info); // 直接使用無值, 原因ele并沒有添加該屬性
ele.info = "添加的屬性信息"; // 添加屬性
console.log(ele.info); // 添加屬性后就可以正常方式添加的屬性值
delete ele.info; // 刪除操作
console.log(ele.info); // 刪除后屬性又會消失
// 構造函數
function Perple(name, age) {
this.name = name;
this.age = age;
this.fn = function () {
console.log("fn")
}
}
// 實例化對象
var p = new Perple("張三", 18);
p.fn();
// ES6
class Student {
constructor (name, age) {
this.name = name;
this.age = age;
}
fn () {
console.log("fn")
}
}
var s = new Student("張三", 18);
s.fn();
</script>
<script>
// getElementById只能由document調用
var ele = document.getElementsByClassName("ele")[0];
console.log(ele);
ele = document.querySelector(".ele");
console.log(ele);
ele = document.querySelectorAll(".ele")[0];
console.log(ele);
// 該添加屬性的方式只映射到js代碼中
ele.index = 123;
console.log(ele.index);
// js如何操作元素(頁面標簽)的全局屬性, 映射到html代碼中
ele = document.querySelector('[alert]'); // 通過全局屬性獲取元素
console.log(ele);
// 獲取全局屬性值
var info = ele.getAttribute('alert');
console.log(info);
// 修改全局屬性值
ele.setAttribute('alert', 'no ok');
// 添加全局屬性值(映射到html代碼中) => 結合CSS來控制頁面標簽的樣式
ele.setAttribute('key', 'value');
</script>
</html>
事件參數event
存放事件信息的回調參數
在觸發DOM上某個事件時,會產生一個事件對象event,這個對象包含著所有事件有關的信息(導致事件的元素、事件的類型、與特定事件相關的信息)
所有瀏覽器都支持Event對象,但支持方式不同
IE中的事件對象:window.event
阻止事件冒泡 DOM中提供stopPropagation()方法,但IE不支持,使用event對象在事件函數中調用就行 IE中提供的是,cancelBubble屬性,默認為false,當它設置為true時,就是阻止事件冒泡,也是用event對象在事件函數中調用 jQuery中提供了stopPropagation()方法來停止事件冒泡,當需要時,只需用用event對象來調用就行,即event.stopPropagation(); 默認行為 阻止默認行為 DOM中提供preventDefault()方法來取消事件默認行為,但是只有當cancelable屬性設置為true的事件,才可以使用preventDefault()來取消事件默認行為,使用event對象在事件函數中調用就行 IE中提供的是returnValue屬性,默認為true,當它設置為false時,就是取消事件默認行為,也是用event對象在事件函數中調用 jQuery中提供了preventDefault()方法來阻止元素的默認行為,只需要用event對象來調用就好,即event.preventDefault() 如果想同時對事件對象停止冒泡和默認行為,可以在事件處理函數中返回false。這是對事件對象同時調用stopPropagation()方法和preventDefault()方法的一種簡寫方式
事件注意點
1、event代表事件的狀態,例如觸發event對象的元素、鼠標的位置及狀態、按下的鍵等等; 2、event對象只在事件發生的過程中才有效。 firefox里的event跟IE里的不同,IE里的是全局變量,隨時可用; firefox里的要用參數引導才能用,是運行時的臨時變量 在IE/Opera中是window.event,在Firefox中是event; 而事件的對象,在IE中是window.event.srcElement,在Firefox中是event.target,Opera中兩者都可用
處理冒泡與默認事件
事件的冒泡:父子都具有點擊事件,不處理的話,點擊子級也會出發父級的點擊事件
如果提供了事件對象,則這是一個非IE瀏覽器 if ( e && e.stopPropagation ) 因此它支持W3C的stopPropagation()方法 e.stopPropagation(); else 否則,我們需要使用IE的方式來取消事件冒泡
window.event.cancelBubble = true;
return false;
處理冒泡實例
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件對象</title>
<style>
body {
margin: 0;
}
.box {
background-color: pink;
}
.sup {
200px;
height: 200px;
background-color: red;
}
.sub {
100px;
height: 100px;
background-color: orange;
}
</style>
</head>
<body>
<div class="box">12345</div>
<div class="sup">
<div class="sub"></div>
</div>
<a >只想相應點擊事件</a>
</body>
<script>
var box = document.querySelector('.box');
// 事件的鉤子函數, 系統回調時傳遞了一個值, 該值為事件對象
box.onclick = function (ev) { // 回調函數
console.log(ev)
// 特殊按鍵 altKey | shiftKey | ctrlKey
console.log(ev.altKey)
// 鼠標的點擊點
console.log(ev.clientX, ev.clientY)
}
</script>
<script>
var sup = document.querySelector('.sup');
var sub = document.querySelector('.sub');
// 事件默認有冒泡, 子級相應事件后,會將事件傳遞給父級,如果父級有相同事件,也會被激活, 最終傳遞給document
sub.onclick = function (ev) {
console.log(ev);
// 取消冒泡, 當自身處理事件后, 該事件就處理完畢, 結束, 不再向上傳遞
ev.cancelBubble = true;
console.log("子級被點擊了")
};
sup.onclick = function () {
console.log("父級被點擊了")
};
document.onclick = function () {
console.log("文檔被點擊了")
}
</script>
</html>
事件默認行為:當一個事件發生時瀏覽器自己會做的事情
如果提供了事件對象,則這是一個非IE瀏覽器 if ( e && e.preventDefault ) 阻止默認瀏覽器動作(W3C) e.preventDefault(); else IE中阻止函數器默認動作的方式 window.event.returnValue = false; return false; 既然return false 和 e.preventDefault()都是一樣的效果,那它們有區別嗎?當然有 僅僅是在HTML事件屬性 和 DOM0級事件處理方法中 才能通過返回 return false 的形式組織事件宿主的默認行為
處理默認事件實例
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件對象</title>
<style>
body {
margin: 0;
}
.box {
background-color: pink;
}
.sup {
200px;
height: 200px;
background-color: red;
}
.sub {
100px;
height: 100px;
background-color: orange;
}
</style>
</head>
<body>
<div class="box">12345</div>
<div class="sup">
<div class="sub"></div>
</div>
<a >只想相應點擊事件</a>
</body>
<script>
var box = document.querySelector('.box');
// 事件的鉤子函數, 系統回調時傳遞了一個值, 該值為事件對象
box.onclick = function (ev) { // 回調函數
console.log(ev)
// 特殊按鍵 altKey | shiftKey | ctrlKey
console.log(ev.altKey)
// 鼠標的點擊點
console.log(ev.clientX, ev.clientY)
}
</script>
<script>
// 默認事件
var aBtn = document.querySelector('a');
aBtn.onclick = function (ev) {
ev.cancelBubble = true;
console.log("a被點擊了");
// 手動轉跳頁面
open('https://www.oldboyedu.com', '_self');
// a標簽默認會完成轉跳, 如果取消默認事件
return false;
}
</script>
</html>
再補充一些
默認操作 具體指的是什么呢?
(1)把單擊事件處理程序注冊到一個錨元素,而不是一個外層的<div>上,那么就要面對另外一個問題:當用戶單擊鏈接時,瀏覽器會加載一個新頁面。
(2)當用戶在編輯完表單后按下回車鍵時,會觸發表單的submit事件,在此事件發生后,表單提交才會真正發生。
這種行為與我們討論的事件處理程序不是同一個概念,它是單擊標簽元素的默認操作。
如果我們不希望執行這種默認操作,那么在事件對象上調用.stopPropagation()方法也無濟于事,因為默認操作不是在正常的事件傳播流中發生的
在這種情況下,處理方法有:
1、w3c的方法是e.preventDefault(),IE則是使用e.returnValue = false;
preventDefault它是事件對象(Event)的一個方法,作用是取消一個目標元素的默認行為。既然是說默認行為,當然是元素必須有默認行為才能被取消,如果元素本身就沒有默認行為,調用當然就無效了。什么元素有默認行為呢?如鏈接<a>,提交按鈕<input type=”submit”>等。當Event 對象的 cancelable為false時,表示沒有默認行為,這時即使有默認行為,調用preventDefault也是不會起作用的。
1 <a id="testA" >caibaojian.com</a>
var a = document.getElementById("testA");
a.onclick =function(e){
if(e.preventDefault){
e.preventDefault();//
}else{
window.event.returnValue = false;//IE
//注意:這個地方是無法用return false代替的
//return false只能取消元素
}
}
2、return false;
javascript的return false只會阻止默認行為,而是用jQuery的話則既阻止默認行為又防止對象冒泡
常見事件
鼠標事件
var box = document.querySelector('.box');
1. 點擊事件
box.onclick = function () {
console.log("單擊");
};
2. 雙擊事件(應用場景不廣)
box.ondblclick = function () {
console.log("雙擊");
};
3. 鼠標右鍵
box.oncontextmenu = function () {
console.log("右鍵了");
return false;
};
4. 鼠標懸浮 | 移動 | 按下 | 抬起 | 離開
box.onmouseover = function () {
console.log("懸浮");
};
box.onmousemove = function () {
console.log("移動");
};
box.onmousedown = function () {
console.log("按下");
};
box.onmouseup = function () {
console.log("抬起");
};
box.onmouseout = function () {
console.log("離開");
}
事件參數ev
ev.clientX:點擊點X坐標
ev.clientY:點擊點Y坐標
over | out VS enter | leave
總結: 1. 將子級與父級分開考慮, 大家都有各自的懸浮離開事件, 采用 over | out 組合 2. 將子級納入父級考慮范圍, 也就是只有父級去相應懸浮離開事件, 采用 enter | leave 組合 3. 單獨考慮一個盒子的懸浮離開事件, 兩套均可以 特性 從父級移至子級, 會觸發out事件, 緊接著觸發子級的over事件, 并可以冒泡給父級 從父級移至子級, leave事件并不會觸發, 它認為子級是屬于父級的一部分, enter事件, 也不會再次觸發 懸浮子級: sub over => sup over 支持冒泡 sup enter => sub enter 不支持冒泡
鍵盤事件
鍵盤事件
onkeydown:鍵盤按下會觸發,長按持續觸發
onkeyup:鍵盤抬起
事件參數ev
ev.keyCode:按鍵編號
ev.altKey:alt特殊按鍵
ev.ctrlKey:ctrl特殊按鍵
ev.shiftKey:shift特殊按鍵
<head>
<meta charset="UTF-8">
<title>鍵盤事件</title>
<style>
.box {
100px;
height: 100px;
background: orange;
position: absolute;
top: 0;
left: 0;
}
</style>
</head>
<body>
<div class="box"></div>
</body>
<script>
// 鍵盤長按會一直觸發按下事件
document.onkeydown = function (ev) {
console.log(ev);
// 按下的鍵盤編號
console.log("按下", ev.keyCode);
// console.log(ev.which);
}
document.onkeyup = function (ev) {
console.log("抬起", ev.keyCode);
}
// 左上右下: 37-40
var box = document.querySelector('.box');
document.onkeydown = function (ev) {
switch (ev.keyCode) {
case 37:
box.style.left = box.offsetLeft - 10 + 'px';
break;
case 38:
box.style.top = box.offsetTop - 10 + 'px';
break;
case 39:
box.style.left = box.offsetLeft + 10 + 'px';
break;
case 40:
box.style.top = box.offsetTop + 10 + 'px';
break;
}
}
</script>
</html>
表單事件
onfocus:獲取焦點 onblur:失去焦點 onselect:文本被選中 oninput:值改變 onchange:值改變,且需要在失去焦點后才能觸發 onsubmit:表單默認提交事件
文檔事件
文檔事件由window調用 onload:頁面加載完畢觸發 onbeforeunload:頁面退出或刷新警告,需要設置回調函數返回值,返回值隨意
圖片事件
onerror:圖片加載失敗
頁面事件
onscroll:頁面滾動 onresize:頁面尺寸調整 window.scrollY:頁面下滾距離
文檔頁面事件運用實例
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>其他事件</title>
<script>
// 當頁面加載完畢之后再回調
window.onload = function () {
var box = document.querySelector('.box');
console.log(box);
}
// 頁面滾動可以設置給 window | document
var isShow = false;
window.onscroll = function () {
console.log(window.scrollY);
if (window.scrollY >= 1200) {
if (!isShow) {
console.log("將返回Top按鈕顯示");
isShow = true;
}
} else {
if (isShow) {
isShow = false;
}
}
}
</script>
</head>
<body>
<div class="box"></div>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</body>
</html>
JS選擇器
getElement系列
通過id名獲取唯一滿足條件的頁面元素
document.getElementById('id名');
該方法只能由document調用
任何HTML元素可以有一個id屬性,在文檔中該值必須唯一
若瀏覽器中出現多個id名的情況,CSS樣式對所有該id名的元素都生效,但javascript腳本僅對第一個出現該id名的元素生效。
getElementById()該方法接收一個參數:要取得元素的id,若找到則返回該元素,若不存在則返回null
注意:document.getElementById方法的內部實現需要用到this,這個this本來被期望指向document
跨瀏覽器兼容
1:在ie7中,使用getElementById()的時候,接收的參數id不區分大小寫。
2:在表單元素中,如果表單設置有name屬性,其name屬性會被當做id識別出來。
3:id是唯一的,但name屬性并不是唯一的。具有該名稱的隱式全局變量會引用一個類數組對象,包括所有該命名的元素
通過class名獲取所有滿足條件的頁面元素
document.getElementsByClassName('class名');
該方法可以由document及任意頁面元素對象調用
document.getElementsByClass("class1
class2")可以拿到同時擁有class1和class2的元素,中間用空格隔開,不區分class1和class2的順序。
兼容性:IE8及其以下版本的瀏覽器未實現getElementsByClassName方法
返回值為HTMLCollection (一個類數組結果的對象,使用方式同數組)
沒有匹配到任何結果返回空HTMLCollection對象 ([])
通過name屬性獲取元素
getElementsByName(返回值是一個nodeList集合(區別于Array),可作用于Dom元素)
getElementsByName()方法接收一個參數,即要取得元素的name值。
document.getElementsByName("Name");Name為要獲取元素的name屬性值,這個方法一般適用于提交表單數據,當
元素為form、img、iframe、applet、embed、object的時候設置name屬性時,會自動在Document對象中創建以該
name屬性值命名的屬性。
所以可以通過document.domName引用相應的dom對象。
在ie9中,getElementsByName()只對表單元素起作用。
IE9-瀏覽器中使用getElementsByName()方法也會返回id屬性匹配的元素。因此,不要將name和id屬性設置為相同的值。
通過tag名獲取所有滿足條件的頁面元素
document.getElementsByTagName('tag名');
該方法可以由document及任意頁面元素對象調用
返回值為HTMLCollection (一個類數組結果的對象,使用方式同數組)
沒有匹配到任何結果返回空HTMLCollection對象 ([])
可以使用方括號語法或item()方法來訪問類數組對象中的項,length屬性表示對象中元素的數量。
[注意]通過getElementsByTagName()方法取得的類數組對象有一個namedItem()方法,可以通過元素的name屬性取得集合中的第一個值。safari和IE不支持該方法。document.getElementsByTagName("*")表示匹配文檔的所有元素
querySelect系列
獲取第一個匹配到的頁面元素
document.querySelector('css語法選擇器');
該方法可以由document及任意頁面對象調用
獲取所有匹配到的頁面元素
document.querySelectorAll('css語法選擇器');
該方法可以由document及任意頁面對象調用
返回值為NodeList (一個類數組結果的對象,使用方式同數組)
沒有匹配到任何結果返回空NodeList對象 ([])
id名
可以通過id名直接獲取對應的頁面元素對象,但是不建議使用
js選擇器運用實例
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>js選擇器</title>
<style>
#d {
color: red;
}
</style>
</head>
<body id="bd">
<!--注釋-->
<div id="d" class="dd">我是ddd111</div>
<div id="d" class="dd">我是ddd222</div>
<div class="sup1">
<div id="div"></div>
</div>
<div class="sup2">
<div id="div"></div>
</div>
</body>
<script>
// 節點(了解): 在文檔(document)中出現的所有內容都是document中的節點
// 節點(node): 標簽節點(元素element) | 注釋節點 | 文本節點 | <!doctype>節點
console.log([bd]) // 文本 注釋 文本 標簽 文本 標簽 文本 標簽 文本 標簽 文本
</script>
<script>
// js選擇器: 將js與html建立起連接
// js中一般稱標簽為頁面元素
// 1.直接通過id名進行匹配
console.log(d); // 兩個都可以找到
// 2.getElement系列(最嚴謹)
// 所有顯示在頁面中的內容(展現給用戶看的), 都是屬于文檔(document)對象的內容, 存放在文檔中
// console.log(document)
// 獲取文檔中的標簽 => document對象通過.語法去獲取具體的目標標簽元素
// ① id
var div = document.getElementById('d'); // 檢索得到頁面中出現的第一個滿足條件的目標
console.log(">>>", div);
var body = document.getElementById("bd");
console.log(body);
// 注: getElementById該方法只能由document來調用
// 原因: 我們需要保證一個文檔中一個id只能出現一次, document檢索的就是文檔,
// 而某父級標簽只能檢索自身標簽內部區域, document可以保證文檔中只能一個id
// 只出現一次,某父級標簽只能保證自身內部區域id不重復,能不能保證與外界不重復?
// 不能, 所以從安全角度出發, 獲取唯一對象的getElementById方法只能由能確定唯一id的
// 對象來調用, 能被document調用, 不能被sup來調用
// ② 類名
var divs = document.getElementsByClassName('dd');
console.log(divs);
// 兩個div在body之中, 上方已經獲取了body, 那能否通過body來獲取body中的div
var divs1 = body.getElementsByClassName('dd');
console.log(divs1);
// ③ 標簽名
var divs = document.getElementsByTagName('div');
console.log(divs)
console.log('--------------------------------------------------');
// 3.querySelector系列(最方便)
// 參數: 就是css選擇器語法
// querySelector檢索第一個
var div = document.querySelector('body > .dd');
console.log(div);
// querySelectorAll檢索所有滿足結果
var divs = document.querySelectorAll('body > .dd');
console.log(divs);
var divs = body.querySelectorAll('.dd');
console.log(divs)
var divs = body.querySelectorAll('#d'); // 不嚴謹
console.log(divs)
</script>
</html>
選擇器分類
1. ID選擇器
使用ID選擇器時,需在前面添加“#”,區分大小寫,語法如下:document.querySelector('#id'); //等同于document.getElementById('id')
2. 元素選擇器
元素選擇器通過指定的標簽查詢元素,此時querySelectorAll等同于getElementsByTagName,語法如下:document.querySelectorAll('a'); //獲取頁面上的所有a元素并返回元素
3. 樣式類選擇器
使用元素的樣式類獲取一個或一類元素,樣式名字前使用“.”(英文句號)開頭,語法如下:document.querySelectorAll('.btn'); //獲取所有樣式類中包含btn類名的元素
4. 分組選擇器
使用querySelectorAll不僅可以獲取一個或一類元素,還可以同時獲取其他類別元素,兩種類型之間使用逗號隔開,語法如下:document.querySelectorAll('a,p');
//獲取頁面上所有a元素和p元素,并通過一個列表返回document.querySelectorAll('.btn,.txt'); //獲取頁面上所有包含btn和txt樣式類名的元素
5. 屬性選擇器
獲取頁面上包含指定屬性的元素,屬性名稱可以是元素原生屬性和用戶自定義屬性,語法如下:document.querySelectorAll('a[target="_blank"]');
//獲取頁面上所有target屬性為_blank的a元素document.querySelectorAll('img[data-id]'); //獲取頁面上所有帶有自定義屬性data-id的img元素
6. 后代選擇器
主要用于選擇作為某元素后代的元素,規則左邊的選擇器一端包含兩個或多個用空格分隔的選擇器,如div a可以理解為查找所有被div包圍的所有a元素,語法如下:document.querySelectorAll('div a');
//獲取頁面上所有被div包含的a元素document.querySelectorAll('div .btn'); //獲取頁面上所有被div包含的帶有btn樣式類名的元素
7. 子元素選擇器
后代選擇器會將元素底下的所有相關元素都搜索出來,如果想進一步縮小范圍,可以使用子元素選擇器,只會選擇某個元素的一級子元素,子元素用“>”(大于號)表示,代碼如下:
<html> <div id="first"> <div></div> <div></div> </div></html> <script> document.querySelectorAll('html>div'); //只返回一個id為first的div元素</script>
8. 相鄰兄弟選擇器(比較少用)
選擇緊接在另一個元素后的元素,而且兩者有相同的父元素,相鄰兄弟選擇器使用“+”(加號),代碼如下:
<div> <div></div> <div></div></div><p id="p1"></p><p id="p2"></p><script> document.querySelectorAll('div+p');
//只返回一個id為p1的p元素</script>
9. 偽類選擇器
“:first-child”表示選擇元素的第一個子元素,“:last-child”表示選擇元素的最后一個子元素,“:nth-child(n)”表示選擇元素的第n個子元素。“:first-child”的使用例子,代碼如下:
<div> <p id="p1"></p> <p id="p2"></p></div> <script> document.querySelectorAll('p:first-child'); //只返回一個id為p1的p元素</script>
閉包
function outer() {
var data = {}
function inner() {
return data;
}
return inner;
}
閉包目的:不允許提升變量作用域時,該函數的局部變量需要被其他函數使用
閉包本質:函數的嵌套,內層函數稱之為閉包
閉包的解決案例:①影響局部變量的生命周期,持久化局部變量;②解決變量污染
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>閉包</title>
</head>
<body>
閉包
</body>
<script>
// 了解知識點
// 閉包: 局部的函數(被一個函數包裹的函數)
// 為什么使用閉包:
// 1.一個函數要使用另一個函數的局部變量
// 2.閉包會持久化包裹自身的函數的局部變量
// 3.解決循環綁定
// 函數的嵌套定義
function outer() {
var num = 10;
function inner() {
// 1.在inner函數中,使用了outer的局部變量num
return num;
}
return inner;
}
var innerFn = outer();
// 2.借助閉包,將局部變量num的生命周期提升了
var num = innerFn();
console.log(num);
</script>
</html>
循環綁定
.html文件
<ul> <li>列表項</li> <li>列表項</li> <li>列表項</li> </ul>
.js文件
var lis = document.querySelector('li');
for (var i = 0; i < lis.length; i++) {
lis[i].onclick = function () {
// 打印列表項的索引
console.log(i);
}
}
會發生變量污染
解決方法
1 獲取局部作用域解決 2 閉包解決 3 對象屬性解決
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>循環綁定</title>
</head>
<body>
<div class="box">0000000000000000001</div>
<div class="box">0000000000000000002</div>
<div class="box">0000000000000000003</div>
</body>
<script>
var divs = document.querySelectorAll(".box");
/* 存在污染
for (var i = 0; i < divs.length; i++) {
// i = 0 | 1 | 2 | 3
// 循環綁定
divs[i].onclick = function () {
console.log("***", i)
}
}
// i = 3
console.log(">>>", i);
*/
/* 利用塊級作用域解決
for (let i = 0; i < divs.length; i++) {
// {i=0 <= i} {i=1 <= i} {i=2 <= i}
// i = 3
// 循環綁定
divs[i].onclick = function () {
console.log("***", i)
}
} // for運行結束, i=3會被銷毀
console.log(">>>", i)
*/
// 利用標簽的屬性解決
/*
for (var i = 0; i < divs.length; i++) {
divs[i].index = i;
divs[i].onclick = function () {
// console.log("###", i)
console.log(this.index)
}
}
*/
// 利用閉包處理循環綁定
for (var i = 0; i < divs.length; i++) {
(function () {
var index = i;
divs[index].onclick = function () {
console.log("###", index)
}
})()
/*
(function (index) {
divs[index].onclick = function () {
console.log("###", index)
}
})(i)
*/
/*
(function (i) {
divs[i].onclick = function () {
console.log("###", i)
}
})(i)
*/
}
</script>
</html>
面向對象JS
屬性與方法
var obj = {}; | var obj = new Object();
屬性
obj.prop = "";
方法
obj.func = function () {}
刪除屬性與方法
delete obj.prop delete obj.func
屬性和方法實際使用
對象: 特征與行為的結合體, 是一個具象的實體
// js對象語法
var obj = {
// 屬性
name: 'Zero',
// 方法
teach: function () {
console.log("教學");
}
};
// 對象使用屬性與方法, 采用.語法
console.log(obj.name);
obj.teach();
JS中中括號([ ])與 .
中括號運算符總是能代替點運算符。但點運算符卻不一定能全部代替中括號運算符 中括號運算符可以用字符串變量的內容作為屬性名。點運算符不能 中括號運算符可以用純數字為屬性名。點運算符不能 中括號運算符可以用js的關鍵字和保留字作為屬性名。點運算符不能
下面的例子中,a.b表示對象a的屬性b,既可以設置也可以讀取
object[key]=>key為常量時,object[key]等價于object.key,例如:a.b == a['b']
特殊的,object[key] 中key為變量時,只能用中括號形式
var a = {};
// a.b = 1;
a['b'] = 1;
c = a.b;
// c = a['b'];
alert(c);
標識符是否合法對兩種用法的影響
var obj = {};
// 為obj添加一個屬性name,name是合法的標識符,即也可以通過obj.name方式來定義
obj['name'] = 'jack';
// 為obj添加一個屬性2a,2a不是合法的標識符(不能以數字開頭),不能通過obj.2a來定義
obj['2a'] = 'test';
var obj = {name:'jack'};
obj['2a'] = 'test';
obj['name']; // --> jack
obj['2a']; // --> test (不能通過obj.2a獲取)
總結:常量用點,變量就用中括號
運算符左側應當是一個表達式,它返回一個對象。
對于點(.)來說,右側必須是一個以屬性名稱命名的簡單標識符。
對于方括號([])來說,方括號里必須是一個計算結果為字符串的表達式,這個字符串就是屬性的名字
當通過點運算符(.)方法對象屬性時,屬性名用一個標識符來表示。標識符必須直接出現在js程序中,它們不是數據類型,因此程序無法修改它們。
反過來講,當通過[]來方式對象的屬性時,屬性名通過字符串表示。字符串是js的數據類型,在程序運行時可以修改和創建它們
<script type="text/javascript">
var addr = "";
for(i=0;i<4;i++){
addr += cutomer["address" + i] + "
";
}
</script>
這段代碼讀取customer對象的address0,adddress1,address2,adddress3屬性,并將他們連接起來
類字典結構使用
結構
var dict = {name: "zero", age: 18}
拓展
var dict = {"my-name": "zero", fn: function () {}, fun () {}}
使用
dict.name | dict["my-name"] | dict.fn()
構造函數(ES5)
// 構造函數: 聲明與普通函數一樣, 只是函數名采用大駝峰命名規則
function Person(name) { // 類似于python中的類一樣來使用
// 構造函數內部屬性方式不同于普通函數
this.name = name; // this代表Person構造函數實例化出的所有具體對象中的某一個
this.teach = function () {
console.log(this.name + "正在教學");
}
}
// 如何使用構造函數中的屬性與方法
// 1. 通過構造函數實例化出具體對象
// 2. 通過對象.語法調用屬性與方法
var p1 = new Person("楊虎虎"); // name: 楊虎虎
var p2 = new Person("劉xx"); // name: 劉xx
console.log(p1.name);
console.log(p2.name);
p1.teach();
p2.teach();
為什么要用new?
new 會創建 pre 的對象,
但是沒有 new 的話就沒有沒有可返回的值或對象了,所以是 undefined。
如果不想new 新的對象的話,可以在 pre 的方法里 返回一個值或對象。
function pre(){
this.radius = Math.random();
return this.radius;
}
加 new 會把這個函數當作是一個構造器,返回一個對象。
不加的話,就是調用一個普通的函數,結果視函數返回值而定。
有new,就返回對象,不管函數返回值如何。
無new,就看函數返回值。
構造函數最好返回 this 或者無返回值, 否則容易混淆。
類及繼承(ES6)
// ES6
// 引入了類
class Student { // 類, 可以實例化對象, 但實例化出的對象需要加以區分
// 需要構造器(構造函數)來完成對象的聲明與初始化
// ES6規定方法的語法
constructor (name) {
// 屬性在構造器中聲明并完成初始化
this.name = name;
}
// 類中規定普通方法
study () {
console.log(this.name + "正在學習");
}
// 類方法
static fn() {
console.log("我是類方法")
}
}
// 1.實例化類的對象
let stu1 = new Student("嘿嘿");
// 2.使用屬性與方法
console.log(stu1.name);
stu1.study();
let stu2 = new Student("嘻嘻");
console.log(stu2.name);
stu2.study();
Student.fn()
<script>
// 類方法
class Tool { // 功能類(工具類)中的方法都定義為類方法
static max (num1, num2) {
return num1 > num2 ? num1 : num2;
}
}
// 通過Tool類來求兩個數中的大值, 需要Tool類的對象出現嗎? 不需要 => 功能有類直接使用
console.log(Tool.max(666, 888));
// throw "自定義異常";
// console.log("上面如果出現了異常, 邏輯將會被強制停止");
// var num = 10 / 0;
// console.log(num)
</script>
總結
以上是生活随笔為你收集整理的JS高级语法与JS选择器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么寄笔记本电脑到日本电脑如何寄件
- 下一篇: 教你一个电脑上上传图片的好方法电脑如何传