內(nèi)容是《Web前端開發(fā)之Javascript視頻》的課件,請配合大師哥《Javascript》視頻課程學(xué)習(xí)。
Element類型用于表示XML或HTML元素,提供了對元素標(biāo)簽名、子節(jié)點及特性的訪問;
Element類繼承自Node接口;它繼承了Node接口中的所有屬性和方法,比如parentNode、childNode等;同時,它在Node接口的基礎(chǔ)上擴展了自己的屬性和方法;
Element類型的特征:
var mydiv=document.getElementById("mydiv");
console.log(mydiv.nodeType); // 1
console.log(mydiv.nodeName); // DIV
console.log(mydiv.nodeValue); // null
console.log(mydiv.parentNode); // <body>
console.log(mydiv.childNodes); // NodeList
Element的屬性:
id屬性:表示元素的標(biāo)識符,與全局屬性id對應(yīng);
var mydiv=document.getElementById("mydiv");
console.log(mydiv.id);
mydiv.id="yourdiv";
console.log(mydiv.id);
var yourdiv=document.getElementById("yourdiv");
console.log(yourdiv.id);
tagName屬性:與nodeName屬性一樣,可以返回元素的標(biāo)簽名,在HTML文檔中返回大寫,在XML中返回原生,因此在使用tagName時,最后使用toLowerCase()轉(zhuǎn)換;
var mydiv=document.getElementById("mydiv");
console.log(mydiv.tagName); // DIV
if(mydiv.tagName.toLowerCase()=="div"){
//...
}
一般使用tagName,因為從字義上理解更加清晰;
Element的子類型HTMLElement:
HTMLElement類型直接繼承自Element,因此,HTML元素即屬于HTMLElement類也屬于Element類;
所有HTML元素都由HTMLElement類型或其子類型表示,比如:HTMLDIVElement,就是具體的div元素的類型;
HTMLElement類型在Element類的基礎(chǔ)上,并添加了一些屬性,這些屬性分別對應(yīng)于每個HTML元素中都存在的標(biāo)準(zhǔn)特性:id、title、lang、dir、className;
這些屬性都是可讀可寫的,并且也是動態(tài)的;
<div id="mydiv" name="mydiv" title="DIV" lang="en" dir="ltr" class="divclass">
// …
<script>
var mydiv=document.getElementById("mydiv");
console.log(mydiv.id);
console.log(mydiv.title);
console.log(mydiv.lang);
console.log(mydiv.dir);
console.log(mydiv.className);
mydiv.id="yourdiv";
mydiv.title="你的DIV";
mydiv.lang="fr";
mydiv.dir="rtl";
mydiv.className="reddiv";
</script>
Element特性(屬性):
每個元素都有若干個特性,這些特性的用途是給出相應(yīng)元素或其內(nèi)容的附加信息;DOM為Element對象定義了一些API來獲取或設(shè)置這些XML或HTML屬性(特性);
操作特性主要有三個方法:
getAttribute()、setAttribute()、removeAttribute();這些方法可以針對任何特性使用,包括那些以HTMLElement類型屬性的形式定義的特性;
getAttribute(attributeName)方法:
返回元素上一個指定的特性值,如果指定的特性不存在,則返回null或 "";特性的名稱不區(qū)分大小寫;
如果取得class,需要傳入class,而不是className;
var mydiv=document.getElementById("mydiv");
console.log(mydiv.getAttribute("id")); // mydiv
console.log(mydiv.getAttribute("class")); // divclass
console.log(mydiv.getAttribute("title")); // null
也可以取得自定義特性(即不是HTML元素的標(biāo)準(zhǔn)特性),但要注意,根據(jù)HTML5的規(guī)范,自定義特性應(yīng)該加上data-前綴以便驗證;
console.log(mydiv.getAttribute("custom")); // customvalue
console.log(mydiv.getAttribute("data-name")); // wangwei
任何元素的所有特性,都可以通過DOM元素本身的屬性來訪問,不過,只有公認(rèn)的(非自定義)特性才會以屬性的形式添加到DOM對象中;但IE可以為自定義特性創(chuàng)建屬性;
console.log(mydiv.id);
console.log(mydiv.className);
console.log(mydiv.myname); // undefined
console.log(mydiv.align); // left,認(rèn)為align是公認(rèn)的
var img=document.getElementById("myimg");
var imgurl=img.src;
console.log(img.id==="myimg");
var f=document.forms[0];
f.action="https://www.zeronetwork.cn/do.php";
f.method="POST";
HTML屬性名不區(qū)分大小寫,但Javascript屬性名則大小寫敏感;從HTML屬性名轉(zhuǎn)換到Javascript屬性名應(yīng)該采用小寫,但是如果屬性名包含不止一個單詞,則采用小駝峰式,如:defaultCheded和tabIndex;
有些HTML屬性名在Javascript中是保留字,對于這些屬性,一般的規(guī)則是為該屬性名加前綴”html”,如,HTML的for屬性在Javascript中變?yōu)閔tmlFor屬性,class屬性比較特殊,它在Javascript中變成className屬性;
表示HTML屬性的值通常是字符串,但當(dāng)屬性為布爾值或數(shù)值時,Javascript中對應(yīng)的屬性也是布爾值或數(shù)值,而不是字符串;
<label id="lbInput" for="txtInput">文本框:</label>
<input id="txtInput" tabindex="2" type="text" readonly />
<script>
var txtInput=document.getElementById("txtInput");
console.log(txtInput.tabIndex); // 1
console.log(txtInput.readOnly); // true
var lbInput=document.getElementById("lbInput");
console.log(lbInput.htmlFor); // txtInput
</script>
style和事件處理程序特性:
style:在通過getAttribute()訪問時,返回的style特性值中包含的是CSS文本;而通過屬性訪問它會返回一個CSSStyleDeclaration對象(由于style屬性是用于以編程方式訪問元素樣式的對象,因此并沒有直接映射到style特性,有關(guān)CSS編程,后面我們會講到);
事件處理程序特性,類似于onclick等這樣的事件處理程序,當(dāng)在特性中使用時,onclick中包含的就是JS代碼,使用getAttribute()會返回相應(yīng)的代碼的字符串,但在訪問onclick屬性時,會返回一個Javascript函數(shù);
var mydiv=document.getElementById("mydiv");
console.log(mydiv.getAttribute("style")); // font-size: 14px;color:red;
console.log(mydiv.style); // CSSStyleDeclaration or CSS2Properties
console.log(mydiv.getAttribute("onclick")); // alert('zeronetwork');
console.log(mydiv.onclick); // function onclick(event)
setAttribute(name, value)方法:
設(shè)置指定元素上的某個特性值,如果特性已經(jīng)存在,則更新該值,否則,使用指定的名稱和值添加一個新的特性;
該接受兩個參數(shù):要設(shè)置的特性名和值;
此方法可以操作HTML特性也可以操作自定義特性;
var mydiv=document.getElementById("mydiv");
mydiv.setAttribute("id","outerdiv");
mydiv.setAttribute("class","outerdivclass");
mydiv.setAttribute("title","mydiv title");
mydiv.setAttribute("style","border-bottom:1px solid;color:purple;");
mydiv.setAttribute("custom","custom value");
console.log(mydiv.title); // mydiv title
console.log(mydiv.custom); // undefined
通過該方法設(shè)置的特性名會被統(tǒng)一轉(zhuǎn)換成小寫形式,即“ID”最終會變成“id”;
mydiv.setAttribute("ID","myID"); // id
mydiv.setAttribute("CID","customID"); // cid
布爾特性只要出現(xiàn)在元素上就會被認(rèn)為是 true,無論它的值是什么;一般來說,應(yīng)該將 value 設(shè)置為空字符串,也有人使用這個屬性的名稱作為值,雖然不會出現(xiàn)什么問題,但不規(guī)范的;
var txtInput=document.getElementById("txtInput");
txtInput.setAttribute("readonly",true);// 會渲染成readonly="true"
txtInput.setAttribute("readonly",""); // 渲染成readonly
console.log(txtInput.readOnly); // true
因為所有特性都是屬性,所以直接給屬性賦值可以設(shè)置特性的值,但如果添加的是一個自定義的屬性,該屬性不會自動成為元素的特性;
mydiv.title="mydiv title";
mydiv.style="border-bottom:1px solid;color:purple;";
mydiv.custom="custom value"; // html中并沒有渲染custom
console.log(mydiv.title); // mydiv title
console.log(mydiv.custom); // custom value
console.log(mydiv.getAttribute("title")); // mydiv title
console.log(mydiv.getAttribute("custom")); // null
可以通過setAttribute()方法設(shè)置class,但不能通過屬性設(shè)置class,因為class是關(guān)鍵字,需要className進行屬性設(shè)置;
var mydiv=document.getElementById("mydiv");
mydiv.setAttribute("class","att_class");
// mydiv.class="att_class"; // 無效,class是保留字
mydiv.className="att_class";
console.log(mydiv.class); // undefined
console.log(mydiv.className); // att_class
removeAttribute(attrName)方法:
用于從指定的元素徹底刪除元素的特性;
此方法不僅會清除特性的值,而且也會從元素中完全刪除特性;
此方法并不常用,但在序列化DOM元素時,可以通過它來確切地指定要包含哪些特性;
var mydiv=document.getElementById("mydiv");
mydiv.removeAttribute("class");
mydiv.removeAttribute("style");
mydiv.setAttribute("custom","custom_value");
mydiv.removeAttribute("custom");
mydiv.title="mydiv title";
mydiv.removeAttribute("title");
hasAttribute(attrName)方法和hasAttributes()方法:
用于檢測特性是否存在;其中hasAttribute()需要一個特性參數(shù),判斷該元素是否包含有指定的特性,而hasAttributes()檢測的是否有特性,具體是什么特性,則不是它所關(guān)心的了;
var mydiv=document.getElementById("mydiv");
console.log(mydiv.hasAttribute("title"));
if(!mydiv.hasAttribute("align"))
mydiv.setAttribute("align","center");
console.log(mydiv.hasAttributes()); // true
當(dāng)屬性為布爾值時,hasAttribute()方法特別有用,比如HTML表單的disabled屬性,只要判斷它有沒有這個屬性即可,不用管它的值;
attributes屬性:
返回該元素所有屬性節(jié)點的一個實時集合,該集合是一個NamedNodeMap對象,是一個只讀的類數(shù)組對象,只有Element類型擁有;該屬性與NodeList類似,也是一個動態(tài)的集合;也可以使用索引方式訪問,并且可以枚舉;
元素的每個特性都由一個Attr節(jié)點表示,Attr對象是一個特殊的Node,不會像普通的Node一樣去使用;Attr的name和value屬性返回該屬性的名字和值;
每個Attr節(jié)點都保存在NamedNodeMap對象中;此節(jié)點都有nodeName、nodeValue等屬性,nodeName就是特性的名稱,nodeValue就是特性的值;
var mydiv=document.getElementById("mydiv");
console.log(mydiv.attributes);
console.log(mydiv.attributes[1]);
console.log(mydiv.attributes.title);
console.log(mydiv.attributes.custom);
mydiv.attributes.title="wangwei"; // 無效
console.log(mydiv.attributes[1].nodeType); // ATTRIBUTE_NODE
console.log(mydiv.attributes[1].nodeName);
console.log(mydiv.attributes[1].nodeValue);
NamedNodeMap對象:
表示一個無順序的屬性節(jié)點 Attr 對象的集合;其是類數(shù)組對象,同時也是動態(tài)的;
屬性和方法:
length屬性:返回映射(map)中對象的數(shù)量;
getNamedItem(name):返回給定名稱name的屬性節(jié)點;
item(pos):返回位于數(shù)字pos位置處的節(jié)點;(注:各個瀏覽器會返回不同的順序);
setNamedItem(node):向列表中添加或替換特性節(jié)點;
removeNamedItem(name):從列表中移除特性為name的節(jié)點;與removeAttribute()相同,但其會返回被刪除的特性(Attr)節(jié)點;
可以通過attributes屬性使用方括號直接訪問特性;
var mydiv=document.getElementById("mydiv");
console.log(mydiv.attributes);
console.log(mydiv.attributes.item(1));
console.log(mydiv.attributes.getNamedItem("name"));
console.log(mydiv.attributes[1]);
console.log(mydiv.attributes["name"]);
mydiv.attributes["id"].nodeValue="newID";
mydiv.attributes.getNamedItem("name").nodeValue="newName";
var deleteStyle=mydiv.attributes.removeNamedItem("style");
console.log(deleteStyle);
var yourdiv=document.getElementById("yourdiv");
yourdiv.attributes.setNamedItem(deleteStyle);
var attr=document.createAttribute("dir");
attr.nodeValue="ltr";
mydiv.attributes.setNamedItem(attr);
使用attributes屬性較麻煩,因此使用getAttribute()、removeAttribute()和removeAttribute()方法比較常用;但在遍歷元素的特性時,attributes屬性比較方便;
遍歷attributes屬性:
在需要將DOM結(jié)構(gòu)序列化為XML或HTML字符串時,多數(shù)都會涉及遍歷元素特性;
// 迭代元素的所有特性,構(gòu)造成name=”value” name=”value”這樣的字符串格式
var mydiv=document.getElementById("mydiv");
function outputAttributes(element){
var pairs=new Array();
for(var attr in element.attributes){
if(element.attributes[attr] instanceof Attr){
// console.log(attr + element.attributes[attr]);
var attrName=element.attributes[attr].nodeName;
var attrValue=element.attributes[attr].nodeValue;
// console.log(attrName);
pairs.push(attrName + "=\"" + attrValue + "\"");
}
}
// 或者使用for循環(huán)
// for(var i=0,len=element.attributes.length; i<len; i++){
// var attrName=element.attributes[i].nodeName;
// var attrValue=element.attributes[i].nodeValue;
// // console.log(attrName);
// pairs.push(attrName + "=\"" + attrValue + "\"");
// }
return pairs.join(" ");
}
console.log(outputAttributes(mydiv));
創(chuàng)建Element元素:
document.createElement(tagName)方法:用于創(chuàng)建一個由標(biāo)簽名稱tagName指定的HTML元素,如果用戶代理無法識別tagName,則會生成一個未知 HTML 元素;
該方法只接受一個參數(shù),即要創(chuàng)建元素的標(biāo)簽名;此標(biāo)簽名在HTML中不區(qū)分大小寫,在XML(包括XHTML)中,是區(qū)分大小寫的;
在創(chuàng)建新元素的同時,也為新元素設(shè)置了ownerDocument屬性;同時還可以操作元素的特性,為它添加子節(jié)點,以及執(zhí)行其他操作;
新創(chuàng)建的元素,必須添加到文檔樹中,才能顯示出來,可以利用appendChild,insertBefore()或replaceChild()方法;
var div=document.createElement("div");
div.innerHTML="<h2>零點程序員</h2>";
div.id="outerDiv";
div.className="outerDiv";
div.setAttribute("style","color:green;");
console.log(div.ownerDocument);
document.body.appendChild(div);
var h3=document.createElement("h3");
h3.setAttribute("onclick","alert('this is zeronetwork');");
h3.innerText="zeronetwork";
div.insertBefore(h3, null);
Element的子節(jié)點:
元素可以有任意數(shù)目的子節(jié)點和后代節(jié)點,這些子節(jié)點可能是元素、文本、注釋處處理指令;但HTML中的空白也會被解析為文本節(jié)點;因此在執(zhí)行某項操作時,要先檢查一下nodeType屬性;
<!-- 結(jié)構(gòu) -->
<ul id="myList">
<li>HTML</li>
<li>CSS</li>
<li>Javascript</li>
</ul>
<!-- 或者刪除空白 -->
<ul id="myList"><li>HTML</li><li>CSS</li><li>Javascript</li></ul>
// js代碼
var myList=document.getElementById("myList");
console.log(myList.childNodes.length);
for(var i=0,len=myList.childNodes.length; i<len; i++){
if(myList.childNodes[i].nodeType==Node.ELEMENT_NODE)
console.log(myList.childNodes[i].nodeName);
}
// 或者
// for(var n in myList.childNodes){
// if(myList.childNodes[n].nodeType && myList.childNodes[n].nodeType==Node.ELEMENT_NODE)
// console.log(myList.childNodes[n].nodeName);
// }
元素節(jié)點也支持getElementsByTagName() 方法,可以通過它獲得某個特定的標(biāo)簽名的子節(jié)點或后代節(jié)點;
var myList=document.getElementById("myList");
var lis=myList.getElementsByTagName("li");
console.log(lis); // dom.html:23 HTMLCollection(3)
自定義Element的方法:
Element和HTMLDocument等類型都像String和Array一樣是類,它們不是構(gòu)造函數(shù),但它們有原型對象,可以自定義方法擴展它;
Element.prototype.next=function(){
if(this.nextElementSibling) return this.nextElementSibling;
var sib=this.nextSibling;
while(sib && sib.nodeType !==1) sib=sib.nextSibling;
return sib;
}
console.log(document.getElementById("mydiv").next());
Web前端開發(fā)之Javascript-零點程序員-王唯
要說 js 的深淺拷貝,就不得不提 js 的兩大數(shù)據(jù)類型:基本數(shù)據(jù)類型和引用類型。基本數(shù)據(jù)類型的變量名和值都存儲在棧中,對于引用類型的變量名存儲在棧中,而值存儲在堆中。由于存儲方式不同,所以導(dǎo)致了他們復(fù)制的時候方式不同。
淺拷貝是創(chuàng)建一個新對象,這個對象有著原始對象屬性值的一份精準(zhǔn)拷貝。如果屬性是基本類型,拷貝的就是基本類型的值,如果是引用類型,拷貝的就是內(nèi)存地址,所以如果其中一個對象改變了這個地址,就會影響到另外一個對象。
深拷貝是將一個對象從內(nèi)存中完整的拷貝一份出來,從內(nèi)存堆中存放一個新的對象。這是兩個對象,所以修改其中一個,另外一個不會受影響。
深淺拷貝主要針對的是引用類型,簡單數(shù)據(jù)類型不受影響。
相關(guān)筆試題
var person={
name:"前端人",
hobby:['學(xué)習(xí)','敲代碼','潛水']
}
function copy(source){
var newObj=new Object()
for(var i in source){
if(source.hasOwnProperty(i)){
newObj[i]=source[i]
}
}
return newObj
}
var p1=copy(person);
p1.name="Web Person"
console.log(person.name)
console.log(p1.name)
p1.hobby=["內(nèi)卷"]
console.info(person.hobby)
console.info(p1.hobby)
/*運行結(jié)果:
前端人
Web Person
["學(xué)習(xí)", "敲代碼", "潛水"]
["內(nèi)卷"]
*/
js 數(shù)據(jù)類型一共有 8 種,分為兩大類:基本類型和引用類型。
它們的數(shù)據(jù)類型分別為:
基本類型:string、number、boolean、null、undefined、symbol、bigint
引用類型:object
相關(guān)面試題
// 注意:其他類型與數(shù)值進行相加時,其他類型的轉(zhuǎn)為 number 類型
console.log( true+1 ) // 2
console.log( undefined +1 ) // NaN
console.log( null ) //object
console.log( undefined ) // undefined
共有 6 種方式,分別為:
它們的區(qū)別介紹:
1、async:為 <script>標(biāo)簽定義了 async 屬性。async 和 html 解析是同步的,不是順次執(zhí)行 js 腳本,誰先加載完成先執(zhí)行誰。
<script async type="text/javascript" src="demo1.js" ></script>
<script async type="text/javascript" src="demo2.js" ></script>
2、defer 會等到 html 解析完成之后再執(zhí)行 js 代碼,如果有多個腳本時,會按照順序依次執(zhí)行腳本。
<script defer type="text/javascript" src="demo1.js" ></script>
3、js 最后加載
把 js 外部引入的文件放置在頁面的底部,讓 js 最后加載,從而加快頁面加載速度。
4、利用 setTimeout
5、動態(tài)創(chuàng)建 DOM 的方式
var element=document.createElement("script");
element.src="box.js";
document.body.appendChild(element);
這種方式通過操作動態(tài)加載 js 文件,不觸發(fā)的時候不加載,減少頁面文件大小,加快加載速度。
6、使用 jQuery 的 getScript 方法
$.getScript( "box.js",function(){//回調(diào)函數(shù),成功獲取文件后執(zhí)行的函數(shù)
console.log("腳本加載完成")
});
相關(guān)面試題:
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="text/javascript" src="box.js"></script>
</head>
<body>
<div id="box"></div>
</body>
</html>
//box.js 代碼如下
console.log( document.getElementById('box') ) // null
box.js 想正常獲取元素 box ,并進行一系列操作應(yīng)該如何延遲加載 js 文件呢?
作用域通俗地講,就是指一個變量的作用范圍。分為全局作用域和函數(shù)作用域。
全局作用域
函數(shù)作用域(局部)
函數(shù)在被調(diào)用的時候會先進行預(yù)編譯:
全局作用域預(yù)編譯:
函數(shù)作用域預(yù)編譯:
相關(guān)面試題:
<script type="text/javascript">
function fn(a,c){
console.log(a)
var a=12
console.log(a)
console.log(c)
function a(){ }
if(false){
var d=34
}
console.log(d)
console.log(b)
var b=function(){}
console.log(b)
function c(){}
console.log(c)
}
fn(1,2)
</script>
// 運行結(jié)果:
/*
function a(){}
12
function c(){}
undefined
undefined
function (){}
function c(){}
*/
null 和 undefined 兩個都表示無的值。
作者設(shè)計 js 的時候,借鑒的 java 語言先設(shè)計的 null 。null 使用的時候會被隱式轉(zhuǎn)化成 0,不容易發(fā)現(xiàn)錯誤。
console.log( number(null) ) //0
undefined 是為了填補 null 的坑。所以后來又新增了 undefined 。
console.log( number(undefined) ) //NaN
實現(xiàn) new 操作符的方法:
function create( fn,...args ){
var obj={}
Object.setPrototypeOf( obj,fn.prototype )
var resault=fn.apply(obj,args)
return (resault instanceof Object) ? result : obj
}
7.1、什么是閉包?
閉包就是函數(shù)嵌套函數(shù),通過函數(shù)內(nèi)的函數(shù)訪問變量的規(guī)則,實現(xiàn)外部訪問函數(shù)內(nèi)的變量。
7.2、閉包的特點:
實例3:閉包解決問題
var liArr=document.getElementsByTagName('li')
for(var i=0;i<liArr.length;i++){
(function(i){
liArr[i].onclick=function(){
console.log('點擊元素',liArr[i])
}
})(i)
}
7.3、閉包優(yōu)點:
防抖和節(jié)流就是閉包的經(jīng)典應(yīng)用。
7.4、閉包缺點:
8.1、什么是防抖函數(shù)?
當(dāng)持續(xù)觸發(fā)事件,一定時間內(nèi)沒有再觸發(fā)事件,事件處理函數(shù)才會執(zhí)行一次,如果在設(shè)定的時間到來之前又觸發(fā)了事件,就會重新計時。
防抖函數(shù)常見的實際應(yīng)用:使用 echart 的時候,瀏覽器 resize 時,需要重新繪制圖表大小,還有典型的輸入框搜索應(yīng)用。
8.2、節(jié)流函數(shù)是什么?
當(dāng)持續(xù)觸發(fā)事件的時候,保證一段時間內(nèi)只調(diào)用一次事件處理函數(shù),一段時間內(nèi),只允許做一件事情。
防抖和節(jié)流主要是用來限制觸發(fā)頻率較高的事件,再不影響效果的前提條件下,降低事件觸發(fā)頻率,減小瀏覽器或服務(wù)器的壓力,提升用戶體驗效果。
方法1: new set()
return Array.from(new Set(arr))
// 或
return [...new Set(arr)]
方法2:使用兩次循環(huán)
for(var i=0,len=arr.length;i<len;i++){
for(var j=i+1,len=arr.length;j<len;j++){
if( arr[i]===arr[j] ){
arr.splice(i,1)
j--;
len--
}
}
}
return arr
方法3:indexOf 實現(xiàn)
let arr1=[]
for(var i=0;i<arr.length;i++){
if( arr1.indexOf(arr[i])===-1 ){
arr1.push(arr[i])
}
}
return arr1
方法4:includes 實現(xiàn)
let arr1=[]
for(var i=0;i<arr.length;i++){
if( !arr1.includes(arr[i]) ){
arr1.push(arr[i])
}
}
return arr1
方法5:filter 實現(xiàn)
array.indexOf(item,start) start 表示開始檢索的位置。
return arr.filter(( item, index )=>{
return arr.indexOf( item, 0 )==index
})
三者都是改變函數(shù)執(zhí)行的上下文,即改變 this 指向。
它們之間的區(qū)別為:
使用場景:
1、需要改變某個函數(shù)的this指向時
2、當(dāng)參數(shù)較少時可以使用call,參數(shù)較多可以使用apply以數(shù)組的方式傳遞
3、當(dāng)需要重復(fù)調(diào)用時,可以使用bind新定義一個方法
方法1:isArray
var arr=[1,2,3]
console.log(Array.isArray(arr))
方法2:instanceof
var arr=[1,2,3]
console.log( arr instanceof Array )
console.log( arr instanceof Object )
該方法不夠嚴(yán)謹(jǐn)。
方法3:prototype
console.log( Object.prototype.toString.call(arr).indexOf('Array')>-1 )
方法4:isPrototypeOf
console.log( Array.prototype.isPrototypeOf( arr ) )
方法5:constructor
console.log(arr.constructor.toString().indexOf('Array')>-1 )
slice 是用來截取字符串的,返回一個新數(shù)組,但不會影響原數(shù)組。
使用語法:
arr.slice( start , end )
截取 arr 數(shù)組,從 start 開始到 end 結(jié)束,第二個參數(shù)是可選參數(shù),沒有時從 start 開始截取到結(jié)尾。
如果 start 參數(shù)是負數(shù)時,就會從 arr.lengtn + start 開始截取到結(jié)束。
var arr=['a','b','c','d','e']
console.log( arr.slice(-3) ) // ["c", "d", "e"]
console.log(arr) //["a", "b", "c", "d", "e"]
splice 是一個更強大的方法,可以添加、刪除、替換數(shù)組元素,返回的是被刪除元素,它的操作會改變原數(shù)組。
使用語法:
splice( start, n, new )
從 start 開始,刪除 n 個元素,然后把 new 添加到 start 元素之后。第三個參數(shù)為可選參數(shù)
var arr=['a','b','c','d','e']
var ar=arr.splice( 1, 1 ,'f','g')
console.log('ar',ar) // ["b"]
console.log('arr',arr) // ["a", "f", "g", "c", "d", "e"]
==比較的是值,===除了比較值,還比較類型。
console.log( [1,2]=='1,2' ) // true
console.log( [1,2]==='1,2' ) //false
valueOf 方法返回 Math 對象的原始值,通常由 javascript 在后臺自動調(diào)用,并不顯示的出現(xiàn)在代碼中。
console.log([1,2].valueOf()) //[1,2]
console.log('1,2'.valueOf()) //[1,2]
// 所以
console.log( [1,2]=='1,2' ) // true
不管是字符串和數(shù)字比較,還是布爾值和數(shù)字比較,都會使用 valueOf 隱式轉(zhuǎn)換。
總結(jié):==需要使用 valueOf() 進行隱式轉(zhuǎn)換,所以性能差。===會避開一些不必要的麻煩。
大廠筆試題:
var name='window name'
var p1={
name:'p1 name',
showName:function(){
console.info(this.name)
}
}
var fn=p1.showName
fn()
p1.showName()
var p2={
name:'p2 name',
showName:function(fun){
fun()
}
}
p2.showName(p1.showName)
p2.showName=p1.showName
p2.showName()
/*
運行結(jié)果:
window name
p1 name
window name
p2 name
*/
這是一道關(guān)于 this 指向的面試題,接下來我們就說說 this 是如何指向的?
this 對象是運行時基于函數(shù)的執(zhí)行環(huán)境綁定的:
第 1 種:原型鏈繼承
function Parent(){
this.name="前端人"
}
Parent.prototype.showName=function(){
console.log(this.name)
}
function Child(){}
//原型鏈繼承
Child.prototype=new Parent()
var p=new Child()
console.dir(p.name) //前端人
特點:
第 2 種:借用構(gòu)造函數(shù)
function Animal (name) {
this.name=name || 'Animal';
this.sleep=function(){
console.log(this.name + '正在睡覺!');
}
}
Animal.prototype.eat=function(food) {
console.log(this.name + '正在吃:' + food);
};
function Cat(name){
Animal.call(this);
this.name=name || 'Tom';
}
// Test Code
var cat=new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
特點:
還有組合式繼承、ES6 的繼承 和 寄生組合繼承等等。每種繼承方式都有各自的特點和缺點。
JavaScript 語言是一門弱類型語言,存在許多類型錯誤,因此 ES6 引入了嚴(yán)格模式概念。
如果不加 ‘use strict’ 常規(guī)模式下就是屬于非嚴(yán)格模式。
嚴(yán)格模式
在 js 文件頂部添加 ‘use strict’ 就屬于嚴(yán)格模式,嚴(yán)格模式也可以指定在函數(shù)內(nèi)部。
<script>
'use strict'
//或者函數(shù)內(nèi)部
(function(){
'use strict'
})()
</script>
嚴(yán)格模式,是為 js 定義來了一種不同的解析與執(zhí)行模型,在嚴(yán)格模式下,ECMAScipt 3 中一些不解和不確定的行為將得到處理,而且會對不安全的操作會拋出異常。‘use strict’ 會告訴瀏覽器引擎可以切換到嚴(yán)格模式執(zhí)行。
嚴(yán)格模式與非嚴(yán)格模式區(qū)別
嚴(yán)格模式 | 非嚴(yán)格模式 |
變量必須聲明才能賦值 | 變量不進行聲明,可直接賦值 |
不能使用 delete 字符刪除變量或?qū)ο?/p> | 可以使用 delete 刪除 |
函數(shù)參數(shù)變量名不允許重復(fù) | 變量名重復(fù),獲取最后最后那個值 |
普通函數(shù)內(nèi)的 this 為 undefined | 普通函數(shù)內(nèi)的 this 為 window |
不允許使用八進制 | 允許任意進制 |
eval 和 arguments 當(dāng)做關(guān)鍵字,不能被賦值和用作變量名 | 可以使用 eval 、arguments 作為變量名 |
call、apply 傳入 null undefined 保持原樣不被轉(zhuǎn)為window | 默認(rèn)轉(zhuǎn)為 window 對象 |
限制對調(diào)用棧的檢測能力,訪問 arguments.callee 會拋出異常 | arguments.callee 運行正常 |
console.log( '2'>10 ) //false
console.log( '2'>'10' ) //true
console.log( 'abc'>'b' ) //false
console.log( 'abc'>'aab' ) //true
console.log( undefined==null ) //true
console.log( NaN==NaN )//false
console.log( []==0 ) //true
console.log( ![]==0 ) //true
console.log( []==[] ) //false
console.log( {}=={} ) //false
console.log( {}==!{} ) //false
阿里面試題1:
<script type="text/javascript">
var p=new Promise(resolve=>{
console.log(4)
resolve(5)
})
function f1(){
console.log(1)
}
function f2(){
setTimeout(()=>{
console.log(2)
},0)
f1()
console.log(3)
p.then(res=>{
console.log(res)
})
}
f2()
</script>
// 運行結(jié)果 4 1 3 5 2
// 如果已經(jīng)了解事件運行機制,就可以跳過該問題了
事件循環(huán)機制,event-loop 。包含三部分:調(diào)用棧、消息隊列、微任務(wù)隊列。
事件循環(huán)開始的時候,會從全局一行一行的執(zhí)行代碼,遇到函數(shù)調(diào)用的時候,就會壓入調(diào)用棧中,當(dāng)函數(shù)執(zhí)行完成之后,彈出調(diào)用棧。
// 如:代碼會一行一行執(zhí)行,函數(shù)全部調(diào)用完成之后清空調(diào)用棧
function f1(){
console.log(1)
}
function f2(){
f1()
console.log(2)
}
f2()
// 執(zhí)行結(jié)果 1 2
如果遇到 fetch、setInterval、setTimeout 異步操作時,函數(shù)調(diào)用壓入調(diào)用棧時,異步執(zhí)行內(nèi)容會被加入消息隊列中,消息隊列中的內(nèi)容會等到調(diào)用棧清空之后才會執(zhí)行。
// 如:
function f1(){
console.log(1)
}
function f2(){
setTimeout(()=>{
console.log(2)
},0)
f1()
console.log(3)
}
f2()
// 執(zhí)行結(jié)果 :1 3 2
遇到 promise、async、await 異步操作時,執(zhí)行內(nèi)容會被加入微任務(wù)隊列中,會在調(diào)用棧清空之后立即執(zhí)行。
調(diào)用棧加入的微任務(wù)隊列會立即執(zhí)行。
如
let p=new Promise(resolve=>{
console.log('立即執(zhí)行')
resolve(1) //在 then 調(diào)用中執(zhí)行
})
微任務(wù)隊列中內(nèi)容優(yōu)先執(zhí)行,所以比消息隊列中的內(nèi)容執(zhí)行得早。
了解這些知識后,再試一下最前面的那道面試題,應(yīng)該就沒什么問題了。
這個問題就留給讀到最后,能夠堅持學(xué)習(xí)的人,問問我們自己有什么是我們擅長的?在哪塊領(lǐng)域是我們占據(jù)競爭優(yōu)勢的?
使用內(nèi)置JavaScript的對象實例。
Document 對象
使用 document.write() 輸出文本
使用 document.write() 輸出 HTML
返回文檔中錨的數(shù)目
返回文檔中第一個錨的 innerHTML
返回文檔中表單的數(shù)目
返回文檔中第一個表單的名字
返回文檔中的圖像數(shù)
返回文檔中第一個圖像的ID
返回文檔中的鏈接數(shù)
返回文檔中的第一個鏈接的ID
返回文檔中的所有cookies的名稱/值對
返回加載的文檔的服務(wù)器域名
返回文檔的最后一次修改時間
返回加載的當(dāng)前文檔的URL
返回文檔的標(biāo)題
返回文檔的完整的URL
打開輸出流,向流中輸入文本
write() 和 writeln()的不同
用指定的ID彈出一個元素的innerHTML
用指定的Name彈出元素的數(shù)量
用指定的tagname彈出元素的數(shù)量
更多的Document 對象的例子,在我們的JavaScript 參考手冊。
Anchor 對象
返回和設(shè)置鏈接的charset屬性
返回和設(shè)置鏈接的href屬性
返回和設(shè)置鏈接的hreflang屬性
返回一個錨的名字
返回當(dāng)前的文件和鏈接的文檔之間的關(guān)系
改變鏈接的target屬性
返回一個鏈接的type屬性的值
更多的Anchor 對象的例子,在我們的JavaScript 參考手冊。
Area 對象
返回圖像映射某個區(qū)域的替代文字
返回圖像映射某個區(qū)域的坐標(biāo)
返回一個區(qū)域的href屬性的錨部分
返回的主機名:圖像映射的某個區(qū)域的端口
返回圖像映射的某個區(qū)域的hostname
返回圖像映射的某個區(qū)域的port
返回圖像映射的某個區(qū)域的href
返回圖像映射的某個區(qū)域的pathname
返回圖像映射的某個區(qū)域的protocol
返回一個區(qū)域的href屬性的querystring部分
返回圖像映射的某個區(qū)域的shape
返回圖像映射的某個區(qū)域的target的值
更多的Area 對象的例子,在我們的JavaScript 參考手冊。
Base 對象
返回頁面上所有相對URL的基URL
返回頁面上所有相對鏈接的基鏈接
更多的Base 對象對象的例子,在我們的JavaScript 參考手冊。
Button 對象
當(dāng)點擊完button不可用
返回一個button的name
返回一個button的type
返回一個button的value
返回一個button所屬表的ID
更多Button 對象實例在我們的JavaScript 參考手冊。
Form 對象
返回一個表單中所有元素的value
返回一個表單acceptCharset屬性的值
返回一個表單action屬性的值
返回表單中的enctype屬性的值
返回一個表單中元素的數(shù)量
返回發(fā)送表單數(shù)據(jù)的方法
返回一個表單的name
返回一個表單target屬性的值
重置表單
提交表單
更多Button 對象實例在我們的JavaScript 參考手冊。
Frame/IFrame 對象
對iframe排版
改變一個包含在iframe中的文檔的背景顏色
返回一個iframe中的frameborder屬性的值
刪除iframe的frameborder
改變iframe的高度和寬度
返回一個iframe中的longdesc屬性的值
返回一個iframe中的marginheight屬性的值
返回一個iframe中的marginwidth屬性的值
返回一個iframe中的name屬性的值
返回和設(shè)置一個iframe中的scrolling屬性的值
改變一個iframe的src
更多Frame/IFrame 對象實例在我們的JavaScript 參考手冊。
Image 對象
對image排版
返回image的替代文本
給image加上border
改變image的高度和寬度
設(shè)置image的hspace和vspace屬性
返回image的longdesc屬性的值
創(chuàng)建一個鏈接指向一個低分辨率的image
返回image的name
改變image的src
返回一個客戶端圖像映射的usemap的值
更多Image 對象實例在我們的JavaScript 參考手冊。
Event 對象
被按下的鍵盤鍵的keycode?
鼠標(biāo)的坐標(biāo)?
鼠標(biāo)相對于屏幕的坐標(biāo)?
shift鍵被按下了嗎?
哪個事件發(fā)生了?
Option and Select 對象
禁用和啟用下拉列表
獲得有下拉列表的表單的ID
獲得下拉列表的選項數(shù)量
將下拉列表變成多行列表
在下拉列表中選擇多個選項
彈出下拉列表中被選中的選項
彈出下拉列表中被選中的選項的索引
改變下拉列表中被選中的選項的文本
刪除下拉列表中的選項
Table, TableHeader, TableRow, TableData 對象
改變表格邊框的寬度
改變表格的cellpadding和cellspacing
指定表格的frame
為表格指定規(guī)則
一個行的innerHTML
一個單元格的innerHTML
為表格創(chuàng)建一個標(biāo)題
刪除表格中的行
添加表格中的行
添加表格行中的單元格
單元格內(nèi)容水平對齊
單元格內(nèi)容垂直對齊
對單個單元格的內(nèi)容水平對齊
對單個單元格的內(nèi)容垂直對齊
改變單元格的內(nèi)容
改變行的內(nèi)容
如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。