日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > HTML >内容正文

HTML

前端面试题目汇总摘录(JS 基础篇)

發(fā)布時(shí)間:2023/12/15 HTML 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 前端面试题目汇总摘录(JS 基础篇) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

溫故而知新,保持空杯心態(tài)

JS 基礎(chǔ)

JavaScript 的 typeof 返回那些數(shù)據(jù)類型

object number function boolean undefined string

typeof null; // object typeof isNaN; // function typeof isNaN(123); //boolean typeof []; // object Array.isArray(); // false toString.call([]); // [object Array] var arr = []; arr.constructor; // ? Array() { [native code] } 復(fù)制代碼

強(qiáng)制類型轉(zhuǎn)換和隱式類型轉(zhuǎn)換?

顯示轉(zhuǎn)換(強(qiáng)制類型轉(zhuǎn)換)

js 提供了以下幾種轉(zhuǎn)型函數(shù):

轉(zhuǎn)換的類型函數(shù)
數(shù)值類型Number(mix),parseInt(string,radix),parseFloat(string);
字符串類型toString(radix),String(mix)
布爾類型Boolean(mix)
Number(mix) 函數(shù),可以將任意類型的參數(shù) mix 轉(zhuǎn)換為數(shù)值類型,規(guī)則為
  • 如果是布爾值,true 和 false分別被轉(zhuǎn)換為 1 和 0
  • 如果是數(shù)字值,返回本身
  • 如果是 null,返回 0
  • 如果是 undefined,返回 NaN
  • 如果是字符串,遵循以下規(guī)則:
  • 如果字符串中只包含數(shù)字,則將其轉(zhuǎn)換為十進(jìn)制(忽略前導(dǎo)0,前面正負(fù)號(hào)有效)
  • 如果字符串中包含有效的浮點(diǎn)格式,則將其轉(zhuǎn)換為對(duì)應(yīng)的浮點(diǎn)數(shù)值(忽略前導(dǎo)0,前面正負(fù)號(hào)有效)
  • 如果字符串中包含有效的十六進(jìn)制格式,則轉(zhuǎn)換為相同大小的十進(jìn)制整數(shù)值
  • 如果字符串是空的(不包含任何字符),則將其轉(zhuǎn)換為 0
  • 如果字符串中包含上述格式之后的字符,則將其轉(zhuǎn)換為 NaN
  • 如果是對(duì)象,則調(diào)用對(duì)象的 valueOf() 方法,然后按照前面的規(guī)則進(jìn)行轉(zhuǎn)換返回的值,如果是轉(zhuǎn)換結(jié)果是 NaN,則調(diào)用對(duì)象的 toString() 方法,然后再一次按照前面的規(guī)則進(jìn)行返回的字符串值的轉(zhuǎn)換
  • 下表是對(duì)象的 valueOf() 的返回值

    對(duì)象返回值
    Array數(shù)組的元素被轉(zhuǎn)換為字符串,這些字符串由逗號(hào)分隔,連接在一起。其操作與 Array.toString 和 Array.join 方法相同。
    BooleanBoolean 值。
    Date存儲(chǔ)的時(shí)間是從 1970 年 1 月 1 日午夜開(kāi)始計(jì)的毫秒數(shù) UTC。
    Function函數(shù)本身。
    Number數(shù)字值。
    Object對(duì)象本身。這是默認(rèn)情況。
    String字符串值。

    由于 Number()函數(shù)在轉(zhuǎn)換字符串時(shí)原理比較復(fù)雜,且不夠合理,因此在處理字符串時(shí),更常用的是 parseInt() 函數(shù)

    parstInt(string,radix) 函數(shù),將字符串轉(zhuǎn)換為整數(shù)類型的數(shù)值,其規(guī)則為
  • 忽略前面字符串前面的空格,直至找到第一個(gè)非空格字符
  • 如果第一個(gè)字符不是數(shù)字字符或者負(fù)號(hào),就會(huì)返回 NaN(也就是遇到空字符會(huì)返回 NaN)
  • 如果第一個(gè)字符是數(shù)字字符,會(huì)繼續(xù)解析第二個(gè)字符,知道解析完所有后續(xù)的字符或者是遇到一個(gè)非數(shù)字字符
  • 如果字符串中第一個(gè)字符是數(shù)字字符,也能夠識(shí)別各種進(jìn)制
  • 最好在 第二個(gè)參數(shù)指定轉(zhuǎn)換的基數(shù)(進(jìn)制),就不會(huì)有所歧義。
  • parseFloat(string)函數(shù),將字符串轉(zhuǎn)換為浮點(diǎn)數(shù)類型的數(shù)值。

    與parseInt()函數(shù)類似,parseFloat()也是從第一個(gè)字符(位置0)開(kāi)始解析每個(gè)字符。而且也是一直解析到字符串末尾,或者解析到遇見(jiàn)一個(gè)無(wú)效的浮點(diǎn)數(shù)字字符為止。也就是說(shuō),字符串中的第一個(gè)小數(shù)點(diǎn)是有效的,而第二個(gè)小數(shù)點(diǎn)就是無(wú)效的了,因此它后面的字符串將被忽略。

    toString(radix)

    除 undefined 和 null之外的所有類型的值都具有 toString() 方法,其作用是返回對(duì)象的字符串表示。

    多數(shù)情況下,調(diào)用toString()方法不必傳遞參數(shù)。但是,在調(diào)用數(shù)值的toString()方法時(shí),可以傳遞一個(gè)參數(shù):輸出數(shù)值的基數(shù)。默認(rèn)情況下,toString()方法以十進(jìn)制格式返回?cái)?shù)值的字符串表示。

    對(duì)象操作
    Array將 Array 的元素轉(zhuǎn)換為字符串。結(jié)果字符串由逗號(hào)分隔,且連接起來(lái)。
    Boolean如果 Boolean 值是 true,則返回 “true”。否則,返回 “false”。
    Date返回日期的文字表示法。
    Error返回一個(gè)包含相關(guān)錯(cuò)誤信息的字符串。
    Function返回如下格式的字符串,其中 functionname 是被調(diào)用 toString 方法函數(shù)的名稱:function functionname( ) { [native code] }
    Number返回?cái)?shù)字的文字表示。
    String返回 String 對(duì)象的值。
    默認(rèn)返回 “[object objectname]”,其中 objectname 是對(duì)象類型的名稱。

    在不知道要轉(zhuǎn)換的值是不是null或undefined的情況下,還可以使用轉(zhuǎn)型函數(shù)String(),這個(gè)函數(shù)能夠?qū)⑷魏晤愋偷闹缔D(zhuǎn)換為字符串。

    String(mix)函數(shù),將任何類型的值轉(zhuǎn)換為字符串,其規(guī)則為:
  • 如果有toString()方法,則調(diào)用該方法(不傳遞radix參數(shù))并返回結(jié)果
  • 如果是null,返回”null”
  • 如果是undefined,返回”undefined”
  • Boolean(mix)函數(shù),將任何類型的值轉(zhuǎn)換為布爾值。

    以下值會(huì)被轉(zhuǎn)換為false:false、”"、0、NaN、null、undefined,其余任何值都會(huì)被轉(zhuǎn)換為true。

    隱式轉(zhuǎn)換(非強(qiáng)制轉(zhuǎn)換類型)

    在某些情況下,即使我們不提供顯示轉(zhuǎn)換,Javascript也會(huì)進(jìn)行自動(dòng)類型轉(zhuǎn)換,主要情況有:

    用于檢測(cè)是否為非數(shù)值的函數(shù):isNaN(mix)

    isNaN()函數(shù),經(jīng)測(cè)試發(fā)現(xiàn),該函數(shù)會(huì)嘗試將參數(shù)值用 Number() 進(jìn)行轉(zhuǎn)換,如果結(jié)果為“非數(shù)值”則返回 true,否則返回 false。

    遞增遞減操作符(包括前置和后置)、一元正負(fù)符號(hào)操作符(經(jīng)過(guò)對(duì)比發(fā)現(xiàn),其規(guī)則與Number()規(guī)則基本相同)
  • 如果是包含有效數(shù)字字符的字符串,先將其轉(zhuǎn)換為數(shù)字值(轉(zhuǎn)換規(guī)則同 Number()),再執(zhí)行加減1的操作,字符串變量變?yōu)閿?shù)值變量。
  • 如果是不包含有效數(shù)字字符的字符串,將變量的值設(shè)置為 NaN,字符串變量變成數(shù)值變量。
  • 如果是布爾值 false,先將其轉(zhuǎn)換為0再執(zhí)行加減1的操作,布爾值變量編程數(shù)值變量。
  • 如果是布爾值 true,先將其轉(zhuǎn)換為1再執(zhí)行加減1的操作,布爾值變量變成數(shù)值變量。
  • 如果是浮點(diǎn)數(shù)值,執(zhí)行加減1的操作。
  • 如果是對(duì)象,先調(diào)用對(duì)象的 valueOf() 方法,然后對(duì)該返回值應(yīng)用前面的規(guī)則。如果結(jié)果是 NaN,則調(diào)用 toString() 方法后再應(yīng)用前面的規(guī)則。對(duì)象變量變成數(shù)值變量。
  • 加法運(yùn)算操作符

    加號(hào)運(yùn)算操作符在Javascript也用于字符串連接符,所以加號(hào)操作符的規(guī)則分兩種情況:

    如果兩個(gè)操作值都是數(shù)值,其規(guī)則為:

  • 如果一個(gè)操作數(shù)為 NaN,則結(jié)果為 NaN
  • 如果是 Infinity+Infinity,結(jié)果是 Infinity
  • 如果是 -Infinity+(-Infinity),結(jié)果是 -Infinity
  • 如果是 Infinity+(-Infinity),結(jié)果是 NaN
  • 如果是 +0+(+0),結(jié)果為 +0
  • 如果是 (-0)+(-0),結(jié)果為 -0
  • 如果是 (+0)+(-0),結(jié)果為 +0
  • 如果有一個(gè)操作值為字符串,則:

  • 如果兩個(gè)操作值都是字符串,則將它們拼接起來(lái) 如果只有一個(gè)操作值為字符串,則將另外操作值轉(zhuǎn)換為字符串,然后拼接起來(lái)
  • 如果一個(gè)操作數(shù)是對(duì)象、數(shù)值或者布爾值,則調(diào)用toString()方法取得字符串值,然后再應(yīng)用前面的字符串規(guī)則。
  • 對(duì)于undefined和null,分別調(diào)用String()顯式轉(zhuǎn)換為字符串。
  • 可以看出,加法運(yùn)算中,如果有一個(gè)操作值為字符串類型,則將另一個(gè)操作值轉(zhuǎn)換為字符串,最后連接起來(lái)。

    乘除、減號(hào)運(yùn)算符、取模運(yùn)算符

    這些操作符針對(duì)的是運(yùn)算,所以他們具有共同性:如果操作值之一不是數(shù)值,則被隱式調(diào)用Number() 函數(shù)進(jìn)行轉(zhuǎn)換。具體每一種運(yùn)算的詳細(xì)規(guī)則請(qǐng)參考ECMAScript中的定義。

    邏輯操作符(!、&&、||)

    邏輯非(!)操作符首先通過(guò)Boolean()函數(shù)將它的操作值轉(zhuǎn)換為布爾值,然后求反。

    邏輯與(&&)操作符,如果一個(gè)操作值不是布爾值時(shí),遵循以下規(guī)則進(jìn)行轉(zhuǎn)換:

  • 如果第一個(gè)操作數(shù)經(jīng) Boolean() 轉(zhuǎn)換后為 true,則返回第二個(gè)操作值,否則返回第一個(gè)值(不是 Boolean() 轉(zhuǎn)換后的值)
  • 如果有一個(gè)操作值為 null,返回 null
  • 如果有一個(gè)操作值為 NaN,返回 NaN
  • 如果有一個(gè)操作值為 undefined,返回 undefined
  • 邏輯或(||)操作符,如果一個(gè)操作值不是布爾值,遵循以下規(guī)則

  • 如果第一個(gè)操作值經(jīng) Boolean() 轉(zhuǎn)換后為 false,則返回第二個(gè)操作值,否則返回第一個(gè)操作值(不是 Boolean() 轉(zhuǎn)換后的值)
  • 對(duì)于 undefined、null 和 NaN 的處理規(guī)則與邏輯與(&&)相同
  • 關(guān)系操作符(<, >, <=, >=)

    與上述操作符一樣,關(guān)系操作符的操作值也可以是任意類型的,所以使用非數(shù)值類型參與比較時(shí)也需要系統(tǒng)進(jìn)行隱式類型轉(zhuǎn)換:

  • 如果兩個(gè)操作值都是數(shù)值,則進(jìn)行數(shù)值比較
  • 如果兩個(gè)操作值都是字符串,則比較字符串對(duì)應(yīng)的字符編碼值
  • 如果只有一個(gè)操作值是數(shù)值,則將另一個(gè)操作值轉(zhuǎn)換為數(shù)值,進(jìn)行數(shù)值比較
  • 如果一個(gè)操作數(shù)是對(duì)象,則調(diào)用 valueOf() 方法(如果對(duì)象沒(méi)有 valueOf() 方法則調(diào)用 toString() 方法),得到的結(jié)果按照前面的規(guī)則執(zhí)行比較
  • 如果一個(gè)操作值是布爾值,則將其轉(zhuǎn)換為數(shù)值,再進(jìn)行比較
  • 注:NaN 是非常特殊的值,它不和任何類型的值相等,包括它自己,同時(shí)它與任何類型的值比較大小時(shí)都返回 false。

    相等操作符(==)

    相等操作符會(huì)對(duì)操作值進(jìn)行隱式轉(zhuǎn)換后進(jìn)行比較:

  • 如果一個(gè)操作值為布爾值,則在比較之前先將其轉(zhuǎn)換為數(shù)值
  • 如果一個(gè)操作值為字符串,另一個(gè)操作值為數(shù)值,則通過(guò)Number()函數(shù)將字符串轉(zhuǎn)換為數(shù)值
  • 如果一個(gè)操作值是對(duì)象,另一個(gè)不是,則調(diào)用對(duì)象的 valueOf() 方法,得到的結(jié)果按照前面的規(guī)則進(jìn)行比較
  • null 與 undefined 是相等的
  • 如果一個(gè)操作值為 NaN,則相等比較返回 false
  • 如果兩個(gè)操作值都是對(duì)象,則比較它們是不是指向同一個(gè)對(duì)象
  • split()、join()的區(qū)別

    前者是切割成數(shù)組的形式

    后者是將數(shù)組轉(zhuǎn)換為字符串

    數(shù)組方法pop/push/unshift/shift

    數(shù)組方法描述
    pop()刪除原數(shù)組最后一項(xiàng),并返回刪除元素的值;如果數(shù)組為空則返回undefined
    push()將參數(shù)添加到原數(shù)組末尾,并返回?cái)?shù)組的長(zhǎng)度
    unshift()將參數(shù)添加到原數(shù)組開(kāi)頭,并返回?cái)?shù)組的長(zhǎng)度
    shift()刪除原數(shù)組第一項(xiàng),并返回刪除元素的值;如果數(shù)組為空則返回undefined

    事件綁定和普通事件有什么區(qū)別

    普通事件中的onclick是DOM0級(jí)事件只支持單個(gè)事件,會(huì)被其他onclick事件覆蓋,而事件綁定中的addEventListener是DOM2級(jí)事件可以添加多個(gè)事件而不用擔(dān)心被覆蓋

    普通添加事件的方法:

    var btn = document.getElementById("hello"); btn.onclick = function(){alert(1); } btn.onclick = function(){alert(2); } 復(fù)制代碼

    執(zhí)行上面的代碼只會(huì)alert 2

    事件綁定方式添加事件:

    var btn = document.getElementById("hello"); btn.addEventListener("click",function(){alert(1); },false); btn.addEventListener("click",function(){alert(2); },false); 復(fù)制代碼

    執(zhí)行上面的代碼會(huì)先alert 1 再 alert 2

    IE 和 DOM 事件流有什么區(qū)別

    事件

    HTML元素事件是瀏覽器內(nèi)在自動(dòng)產(chǎn)生的,當(dāng)有事件發(fā)生時(shí)html元素會(huì)向外界(這里主要指元素事件的訂閱者)發(fā)出各種事件,如click,onmouseover,onmouseout等等。

    DOM事件流

    DOM(文檔對(duì)象模型)結(jié)構(gòu)是一個(gè)樹(shù)型結(jié)構(gòu),當(dāng)一個(gè)HTML元素產(chǎn)生一個(gè)事件時(shí),該事件會(huì)在元素結(jié)點(diǎn)與根結(jié)點(diǎn)之間的路徑傳播,路徑所經(jīng)過(guò)的結(jié)點(diǎn)都會(huì)收到該事件,這個(gè)傳播過(guò)程可稱為DOM事件流。

    冒泡型事件(Bubbling)

    這是IE瀏覽器對(duì)事件模型的實(shí)現(xiàn)。冒泡,顧名思義,事件像個(gè)水中的氣泡一樣一直往上冒,直到頂端。從DOM樹(shù)型結(jié)構(gòu)上理解,就是事件由葉子結(jié)點(diǎn)沿祖先結(jié)點(diǎn)一直向上傳遞直到根結(jié)點(diǎn);從瀏覽器界面視圖HTML元素排列層次上理解就是事件由具有從屬關(guān)系的最確定的目標(biāo)元素一直傳遞到最不確定的目標(biāo)元素.

    捕獲型事件(Capturing)

    Netscape Navigator的實(shí)現(xiàn),它與冒泡型剛好相反,由DOM樹(shù)最頂層元素一直到最精確的元素,直觀上的理解應(yīng)該如同冒泡型,事件傳遞應(yīng)該由最確定的元素,即事件產(chǎn)生元素開(kāi)始。

    DOM標(biāo)準(zhǔn)事件模型

    因?yàn)閮蓚€(gè)不同的模型都有其優(yōu)點(diǎn)和解釋,DOM標(biāo)準(zhǔn)支持捕獲型與冒泡型,可以說(shuō)是它們兩者的結(jié)合體。它可以在一個(gè)DOM元素上綁定多個(gè)事件處理器,并且在處理函數(shù)內(nèi)部,this關(guān)鍵字仍然指向被綁定的DOM元素,另外處理函數(shù)參數(shù)列表的第一個(gè)位置傳遞事件event對(duì)象。

    首先是捕獲式傳遞事件,接著是冒泡式傳遞,所以,如果一個(gè)處理函數(shù)既注冊(cè)了捕獲型事件的監(jiān)聽(tīng),又注冊(cè)冒泡型事件監(jiān)聽(tīng),那么在DOM事件模型中它就會(huì)被調(diào)用兩次。

    實(shí)例

    <body><div><button>點(diǎn)擊這里</button></div> </body> 復(fù)制代碼

    冒泡:button -> div -> body (IE 事件流)

    捕獲:body -> div -> button (Netscape事件流)

    DOM: body -> div -> button -> button -> div -> body(先捕獲后冒泡)

    **事件偵聽(tīng)函數(shù)的區(qū)別 **

    // IE使用: [Object].attachEvent("name_of_event_handler", fnHandler); //綁定函數(shù) [Object].detachEvent("name_of_event_handler", fnHandler); //移除綁定 // DOM使用: [Object].addEventListener("name_of_event", fnHandler, bCapture); //綁定函數(shù) [Object].removeEventListener("name_of_event", fnHandler, bCapture); //移除綁定 復(fù)制代碼

    如何取消瀏覽器事件的傳遞與事件傳遞后瀏覽器的默認(rèn)處理

    取消事件傳遞是指,停止捕獲型事件或冒泡型事件的進(jìn)一步傳遞。

    事件傳遞后的默認(rèn)處理是指,通常瀏覽器在事件傳遞并處理完后會(huì)執(zhí)行與該事件關(guān)聯(lián)的默認(rèn)動(dòng)作(如果存在這樣的動(dòng)作)。例如,如果表單中input type 屬性是 “submit”,點(diǎn)擊后在事件傳播完瀏覽器就就自動(dòng)提交表單。又例如,input 元素的 keydown 事件發(fā)生并處理后,瀏覽器默認(rèn)會(huì)將用戶鍵入的字符自動(dòng)追加到 input 元素的值中。

    要取消瀏覽器的事件傳遞,IE與DOM標(biāo)準(zhǔn)又有所不同。

    在IE下,通過(guò)設(shè)置 event 對(duì)象的 cancelBubble 為 true 即可。

    function someHandle() { window.event.cancelBubble = true; } 復(fù)制代碼

    DOM標(biāo)準(zhǔn)通過(guò)調(diào)用 event對(duì)象的 stopPropagation() 方法即可。

    function someHandle(event) {event.stopPropagation(); } 復(fù)制代碼

    因些,跨瀏覽器的停止事件傳遞的方法是:

    function someHandle(event) { event = event || window.event; if(event.stopPropagation) event.stopPropagation(); else event.cancelBubble = true; } 復(fù)制代碼

    取消事件傳遞后的默認(rèn)處理,IE與DOM標(biāo)準(zhǔn)又不所不同。

    在IE下,通過(guò)設(shè)置 event 對(duì)象的 returnValue 為 false 即可。

    function someHandle() { window.event.returnValue = false; } 復(fù)制代碼

    DOM標(biāo)準(zhǔn)通過(guò)調(diào)用 event 對(duì)象的 preventDefault() 方法即可。

    function someHandle(event) { event.preventDefault(); } 復(fù)制代碼

    因些,跨瀏覽器的取消事件傳遞后的默認(rèn)處理方法是:

    function**` `someHandle(event) { event = event || window.event; if(event.preventDefault) event.preventDefault(); else event.returnValue = false; } 復(fù)制代碼

    IE 和標(biāo)準(zhǔn)下有哪些兼容性的寫(xiě)法

    var ev = ev || window.event document.documentElement.clinetWidth || document.body.clientWidth var target = ev.srcElement || ev.target 復(fù)制代碼

    call 和 apply 的區(qū)別

    call 和 apply 相同點(diǎn): 都是為了用一個(gè)本不屬于一個(gè)對(duì)象的方法,讓這個(gè)對(duì)象去執(zhí)行

    基本使用

    call()

    function.call(obj[,arg1[, arg2[, [,.argN]]]]]) 復(fù)制代碼
    • 調(diào)用call的對(duì)象必須是個(gè)函數(shù)function
    • call的第一個(gè)參數(shù)將會(huì)是function改變上下文后指向的對(duì)象.如果不傳,將會(huì)默認(rèn)是全局對(duì)象window
    • 第二個(gè)參數(shù)開(kāi)始可以接收任意個(gè)參數(shù),這些參數(shù)將會(huì)作為function的參數(shù)傳入function
    • 調(diào)用call的方法會(huì)立即執(zhí)行

    apply()

    function.apply(obj[,argArray]) 復(fù)制代碼

    與call方法的使用基本一致,但是只接收兩個(gè)參數(shù),其中第二個(gè)參數(shù)必須是一個(gè)數(shù)組或者類數(shù)組,這也是這兩個(gè)方法很重要的一個(gè)區(qū)別

    數(shù)組與類數(shù)組小科普

    數(shù)組我們都知道是什么,它的特征都有哪些呢?

  • 可以通過(guò)角標(biāo)調(diào)用,如 array[0]
  • 具有長(zhǎng)度屬性length
  • 可以通過(guò) for 循環(huán)和forEach方法進(jìn)行遍歷
  • 類數(shù)組顧名思義,具備的特征應(yīng)該與數(shù)組基本相同,那么可以知道,一個(gè)形如下面這個(gè)對(duì)象的對(duì)象就是一個(gè)類數(shù)組

    var arrayLike = {0: 'item1',1: 'item2',2: 'item3',length: 3 } 復(fù)制代碼

    類數(shù)組arrayLike可以通過(guò)角標(biāo)進(jìn)行調(diào)用,具有l(wèi)ength屬性,同時(shí)也可以通過(guò) for 循環(huán)進(jìn)行遍歷

    我們經(jīng)常使用的獲取dom節(jié)點(diǎn)的方法返回的就是一個(gè)類數(shù)組,在一個(gè)方法中使用 arguments關(guān)鍵字獲取到的該方法的所有參數(shù)也是一個(gè)類數(shù)組

    但是類數(shù)組卻不能通過(guò)forEach進(jìn)行遍歷,因?yàn)閒orEach是數(shù)組原型鏈上的方法,類數(shù)組畢竟不是數(shù)組,所以無(wú)法使用

    不同點(diǎn)

    call方法從第二個(gè)參數(shù)開(kāi)始可以接收任意個(gè)參數(shù),每個(gè)參數(shù)會(huì)映射到相應(yīng)位置的func的參數(shù)上,可以通過(guò)參數(shù)名調(diào)用,但是如果將所有的參數(shù)作為數(shù)組傳入,它們會(huì)作為一個(gè)整體映射到func對(duì)應(yīng)的第一個(gè)參數(shù)上,之后參數(shù)都為空

    function func (a,b,c) {}func.call(obj, 1,2,3) // function接收到的參數(shù)實(shí)際上是 1,2,3func.call(obj, [1,2,3]) // function接收到的參數(shù)實(shí)際上是 [1,2,3],undefined,undefined 復(fù)制代碼

    apply方法最多只有兩個(gè)參數(shù),第二個(gè)參數(shù)接收數(shù)組或者類數(shù)組,但是都會(huì)被轉(zhuǎn)換成類數(shù)組傳入func中,并且會(huì)被映射到func對(duì)應(yīng)的參數(shù)上

    func.apply(obj, [1,2,3]) // function接收到的參數(shù)實(shí)際上是 1,2,3func.apply(obj, {0: 1,1: 2,2: 3,length: 3 }) // function接收到的參數(shù)實(shí)際上是 1,2,3 復(fù)制代碼

    b 繼承 a 的方法

    方法一:對(duì)象冒充

    function Parent(username){this.username = username;this.hello = function(){console.log(this.username);} } function Child(username,password){this.method = Parent; // this.method 作為一個(gè)臨時(shí)的屬性,并且指向了 Parent所指向的對(duì)象函數(shù)this.method(username); // 執(zhí)行 this.method 方法,即執(zhí)行了 Parent 所指向的對(duì)象函數(shù)delete this.method; // 銷毀 this.method 屬性,即此時(shí) Child 就已經(jīng)擁有了 Parent 的所有方法和屬性 this.password = password;this.world = function(){console.log(this.password);} } const parent = new Parent('hello parent'); const child = new Child('hello child','123456'); console.log(child); parent.hello(); child.hello(); child.world(); 復(fù)制代碼

    **方法二:call() **

    call 方法是 Function 類中的方法 call 方法的第一個(gè)參數(shù)的值賦值給類(即方法)中出現(xiàn)的 this call 方法的第二個(gè)參數(shù)開(kāi)始依次賦值給類(即方法)所接受的參數(shù)

    function Parent(username){this.username = username;this.hello = function(){console.log(this.username);} } function Child(username,password){Parent.call(this,username);this.password = password;this.world = function(){console.log(this.password);} } const parent = new Parent('hello parent'); const child = new Child('hello child','123456'); parent.hello(); child.hello(); child.world(); 復(fù)制代碼

    方法三:apply()

    apply方法接受2個(gè)參數(shù)

    第一個(gè)參數(shù)與call方法的第一個(gè)參數(shù)一樣,即賦值給類(即方法)中出現(xiàn)的this

    第二個(gè)參數(shù)為數(shù)組類型,這個(gè)數(shù)組中的每個(gè)元素依次賦值給類(即方法)所接受的參數(shù)

    function Parent(username){this.username = username;this.hello = function(){console.log(this.username);} } function Child(username,password){Parent.apply(this,new Array(username));this.password = password;this.world = function(){console.log(this.password);} } const parent = new Parent('hello parent'); const child = new Child('hello child','123456'); parent.hello(); child.hello(); child.world(); 復(fù)制代碼

    方法四:原型鏈

    即子類通過(guò) prototype 將所有在父類中通過(guò) prototype 追加的屬性和方法都追加到 Child ,從而實(shí)現(xiàn)繼承

    function Parent(){} Parent.prototype.hello = "hello"; Parent.prototype.sayHello = function(){console.log(this.hello); } function Child(){} Child.prototype = new Parent();// 將 Parent 中所有通過(guò) prototype 追加的屬性和方法都追加到 Child 從而實(shí)現(xiàn)了繼承 Child.prototype.world = "world"; Child.prototype.sayWorld = function(){console.log(this.world); } const child = new Child(); child.sayHello(); child.sayWorld(); 復(fù)制代碼

    方法五:混合方式,call()+ 原型鏈

    function Parent(hello){this.hello = hello; } Parent.prototype.sayHello = function(){console.log(this.hello); } function Child(hello,world){Parent.call(this,hello); // 將父類的屬性繼承過(guò)來(lái)this.world = world; } Child.prototype = new Parent(); //將父類的方法繼承過(guò)來(lái) Child.prototype.sayWorld = function(){ // 新增方法console.log(this.world); } const child = new Child("hello","world"); child.sayHello(); child.sayWorld(); 復(fù)制代碼

    JavaScript this 指針、閉包、作用域

    **js 中的this 指針 **

    在函數(shù)執(zhí)行時(shí),this 總是指向調(diào)用該函數(shù)的對(duì)象。要判斷 this 的指向,其實(shí)就是判斷 this 所在的函數(shù)屬于誰(shuí)。

    在《javaScript語(yǔ)言精粹》這本書(shū)中,把 this 出現(xiàn)的場(chǎng)景分為四類,簡(jiǎn)單的說(shuō)就是:

    1)有對(duì)象就指向調(diào)用對(duì)象

    var myObject = { value: 123 } myObject.getValue = function(){console.log(this.value); // 123console.log(this); // {value: 123, getValue: ?} } myObject.getValue(); 復(fù)制代碼

    2)沒(méi)調(diào)用對(duì)象就指向全局對(duì)象

    var myObject = { value: 123 } myObject.getValue = function(){var foo = function(){console.log(this.value); // undefinedconsole.log(this); // Window?{postMessage: ?, blur: ?, focus: ?, close: ?, frames: Window,?…} // foo函數(shù)雖然定義在getValue 函數(shù)體內(nèi),但是不屬于 getValue也不屬于 myObject,所以調(diào)用的時(shí)候,它的 this 指針指向了全局對(duì)象}foo();return this.value; } console.log(myObject.getValue()); // 123 復(fù)制代碼

    3) 用new構(gòu)造就指向新對(duì)象

    // js 中通過(guò) new 關(guān)鍵詞來(lái)調(diào)用構(gòu)造函數(shù),此時(shí) this 會(huì)綁定雜該新對(duì)象上 var someClass = function(){this.value = 123; } var myCreate = new someClass(); console.log(myCreate.value); // 123 復(fù)制代碼

    4)通過(guò) apply 或 call 或 bind 來(lái)改變 this 的指向

    var myObject = { value: 123 }; var foo = function(){console.log(this); } foo(); // Window?{postMessage: ?, blur: ?, focus: ?, close: ?, frames: Window,?…} foo.apply(myObject); // {value: 123} foo.call(myObject); // {value: 123} var newFoo = foo.bind(myObject); newFoo(); // {value: 123} 復(fù)制代碼

    閉包

    閉包英文是 Closure ,簡(jiǎn)而言之,閉包就是

  • 函數(shù)的局部集合,只是這些局部變量在函數(shù)返回后會(huì)繼續(xù)存在
  • 函數(shù)的“堆棧”在函數(shù)返回后并不釋放,可以理解為這些函數(shù)堆棧并不在棧上分配而是在堆上分配
  • 當(dāng)在一個(gè)函數(shù)內(nèi)部定義另外一個(gè)函數(shù)就會(huì)產(chǎn)生閉包
  • 作為局部變量都可以被函數(shù)內(nèi)的代碼訪問(wèn),這個(gè)和靜態(tài)語(yǔ)言是沒(méi)有差別的,閉包的差別在于局部變量可以在函數(shù)執(zhí)行結(jié)束后仍然被函數(shù)外的代碼訪問(wèn),這意味著函數(shù)必須返回一個(gè)指向閉包的“引用”,或?qū)⑦@個(gè)“引用”賦值給某個(gè)外部變量,才能保證閉包中局部變量被外部代碼訪問(wèn),當(dāng)然包含這個(gè)引用的實(shí)體應(yīng)該是一個(gè)對(duì)象。但是ES并沒(méi)有提供相關(guān)的成員和方法來(lái)訪問(wèn)包中的局部變量,但是在ES中,函數(shù)對(duì)象中定義的內(nèi)部函數(shù)是可以直接訪問(wèn)外部函數(shù)的局部變量,通過(guò)這種機(jī)制,可以用如下方式完成對(duì)閉包的訪問(wèn)。

    function greeting(name){var text = "Hello " + name; // 局部變量// 每次調(diào)用時(shí),產(chǎn)生閉包,并返回內(nèi)部函數(shù)對(duì)象給調(diào)用者return function(){console.log(text);} } var sayHello = greeting('Closure'); // 通過(guò)閉包訪問(wèn)到了局部變量text sayHello(); // 輸出Hello Closure 復(fù)制代碼

    在 ECMAscript 的腳本函數(shù)運(yùn)行時(shí),每個(gè)函數(shù)關(guān)聯(lián)都有一個(gè)執(zhí)行上下文場(chǎng)景(Exection Context),這個(gè)執(zhí)行上下文包括三個(gè)部分

    • 文法環(huán)境(The LexicalEnvironment)
    • 變量環(huán)境(The VariableEnvironment)
    • this綁定

    其中第三點(diǎn)this綁定與閉包無(wú)關(guān),不在本文中討論。文法環(huán)境中用于解析函數(shù)執(zhí)行過(guò)程使用到的變量標(biāo)識(shí)符。我們可以將文法環(huán)境想象成一個(gè)對(duì)象,該對(duì)象包含了兩個(gè)重要組件,環(huán)境記錄(Enviroment Recode),和外部引用(指針)。環(huán)境記錄包含包含了函數(shù)內(nèi)部聲明的局部變量和參數(shù)變量,外部引用指向了外部函數(shù)對(duì)象的上下文執(zhí)行場(chǎng)景。全局的上下文場(chǎng)景中此引用值為NULL。這樣的數(shù)據(jù)結(jié)構(gòu)就構(gòu)成了一個(gè)單向的鏈表,每個(gè)引用都指向外層的上下文場(chǎng)景。

    例如上面我們例子的閉包模型應(yīng)該是這樣,sayHello函數(shù)在最下層,上層是函數(shù)greeting,最外層是全局場(chǎng)景。如下圖:

    因此當(dāng)sayHello被調(diào)用的時(shí)候,sayHello會(huì)通過(guò)上下文場(chǎng)景找到局部變量text的值,因此在屏幕的對(duì)話框中顯示出”Hello Closure”

    針對(duì)一些例子來(lái)幫助大家更加深入的理解閉包,下面共有5個(gè)樣例,例子來(lái)自于JavaScript Closures For Dummies(鏡像)。

    例子1:閉包中局部變量是引用而非拷貝

    function say667(){var num = 666;var sayConsole = function(){console.log(num);}num++;return sayConsole; } var sayConsole = say667(); sayConsole(); // 667 復(fù)制代碼

    例子2:多個(gè)函數(shù)綁定同一個(gè)閉包,因?yàn)樗麄兌x在同一個(gè)函數(shù)內(nèi)。

    function setupSomeGlobals(){var num = 666;gConsoleNumber = function() { console.log(num); }gIncreaseNumber = function() { num++; }gSetNumber = function(x) { num = x; } } setupSomeGlobals(); gConsoleNumber(); // 666 gIncreaseNumber(); gConsoleNumber(); // 667 gSetNumber(12); gConsoleNumber(); // 12 復(fù)制代碼

    例子3:當(dāng)在一個(gè)循環(huán)中賦值函數(shù)時(shí),這些函數(shù)將綁定同樣的閉包

    function buildList(list){var result = [];for(var i = 0; i < list.length; i++){var item = 'item' + list[i];result.push(function(){console.log(item+' '+list[i]);})}return result; } function testList(){var fnList = buildList([1,2,3]);for(var j = 0; j < fnList.length; j++){fnList[j]();} } testList(); // 輸出3次 item3 undefined 復(fù)制代碼

    testList的執(zhí)行結(jié)果是彈出item3 undefined窗口三次,因?yàn)檫@三個(gè)函數(shù)綁定了同一個(gè)閉包,而且item的值為最后計(jì)算的結(jié)果,但是當(dāng)i跳出循環(huán)時(shí)i值為4,所以list[4]的結(jié)果為undefined.

    例子4:外部函數(shù)所有局部變量都在閉包內(nèi),即使這個(gè)變量聲明在內(nèi)部函數(shù)定義之后。

    function sayAlice(){var sayConsole = function(){console.log(alice);}var alice = "Hello Alice";return sayConsole; } var helloAlice=sayAlice(); helloAlice(); 復(fù)制代碼

    執(zhí)行結(jié)果輸出”Hello Alice”的窗口。即使局部變量聲明在函數(shù)sayAlert之后,局部變量仍然可以被訪問(wèn)到。

    例子5:每次函數(shù)調(diào)用的時(shí)候創(chuàng)建一個(gè)新的閉包

    function newClosure(someNum,someRef){var num = someNum;var anArray = [1,2,3];var ref = someRef;return function(x){num += x;anArray.push(num);console.log('num: ' + num +'\nanArray ' + anArray.toString() +'\nref.someVar ' + ref.someVar);} }closure1=newClosure(40,{someVar:'closure 1'}); closure2=newClosure(1000,{someVar:'closure 2'});closure1(5); // num: 45 anArray 1,2,3,45 ref.someVar closure 1 closure2(-10); // num: 990 anArray 1,2,3,990 ref.someVar closure 2 復(fù)制代碼
    閉包的缺點(diǎn):

    (1)由于閉包會(huì)使得函數(shù)中的變量都被保存在內(nèi)存中,內(nèi)存消耗很大,所以不能濫用閉包,否則會(huì)造成網(wǎng)頁(yè)的性能問(wèn)題,在IE中可能導(dǎo)致內(nèi)存泄露。解決方法是,在退出函數(shù)之前,將不使用的局部變量全部刪除。

    (2)閉包會(huì)在父函數(shù)外部,改變父函數(shù)內(nèi)部變量的值。所以,如果你把父函數(shù)當(dāng)作對(duì)象(object)使用,把閉包當(dāng)作它的公用方法(Public Method),把內(nèi)部變量當(dāng)作它的私有屬性(private value),這時(shí)一定要小心,不要隨便改變父函數(shù)內(nèi)部變量的值。

    例子:

    function Cars(){this.name = "Benz";this.color = ["white","black"]; } Cars.prototype.sayColor = function(){var outer = this;return function(){return outer.color}; };var instance = new Cars(); console.log(instance.sayColor()()) 復(fù)制代碼

    改造:

    function Cars(){this.name = "Benz";this.color = ["white","black"]; } Cars.prototype.sayColor = function(){var outerColor = this.color; //保存一個(gè)副本到變量中return function(){return outerColor; //應(yīng)用這個(gè)副本};outColor = null; //釋放內(nèi)存 };var instance = new Cars(); console.log(instance.sayColor()()) 復(fù)制代碼

    作用域

    在JS當(dāng)中一個(gè)變量的作用域(scope)是程序中定義這個(gè)變量的區(qū)域。變量分為兩類:全局(global)的和局部的。其中全局變量的作用域是全局性的,即在JavaScript代碼中,它處處都有定義。而在函數(shù)之內(nèi)聲明的變量,就只在函數(shù)體內(nèi)部有定義。它們是局部變量,作用域是局部性的。函數(shù)的參數(shù)也是局部變量,它們只在函數(shù)體內(nèi)部有定義。

    我們可以借助JavaScript的作用域鏈(scope chain)更好地了解變量的作用域。每個(gè)JavaScript執(zhí)行環(huán)境都有一個(gè)和它關(guān)聯(lián)在一起的作用域鏈。這個(gè)作用域鏈?zhǔn)且粋€(gè)對(duì)象列表或?qū)ο箧湣.?dāng)JavaScript代碼需要查詢變量x的值時(shí)(這個(gè)過(guò)程叫做變量解析(variable name resolution)),它就開(kāi)始查看該鏈的第一個(gè)對(duì)象。如果那個(gè)對(duì)象有一個(gè)名為x的屬性,那么就采用那個(gè)屬性的值。如果第一個(gè)對(duì)象沒(méi)有名為x的屬性,JavaScript就會(huì)繼續(xù)查詢鏈中的第二個(gè)對(duì)象。如果第二個(gè)對(duì)象仍然沒(méi)有名為x的屬性,那么就繼續(xù)查詢下一個(gè)對(duì)象,以此類推。如果查詢到最后(指頂層代碼中)不存在這個(gè)屬性,那么這個(gè)變量的值就是未定義的。

    var a,b; (function(){alert(a); // undefined alert(b); // undefined var a = b = 3;alert(a); // 3alert(b); // 3 })();alert(a); // undefined alert(b); // 3 復(fù)制代碼

    以上代碼相當(dāng)于

    var a,b; (function(){alert(a);alert(b);var a = 3;b = 3;alert(a);alert(b); })();alert(a);復(fù)制代碼

    事件委托是什么?

    概述

    什么叫做事件委托,別名叫事件代理,JavaScript 高級(jí)程序設(shè)計(jì)上講。事件委托就是利用事件冒泡,只指定一個(gè)事件處理程序,就可以管理某一類型的所有事件。

    實(shí)際例子:

    有三個(gè)同事預(yù)計(jì)會(huì)在周一收到快遞,為簽收快遞,有兩種方法:一是三個(gè)人在公司門口等快遞,二是委托給前臺(tái)的小姐代為簽收。現(xiàn)實(shí)生活中,我們大多采用委托的方案(公司也不會(huì)容忍那么多人站在門口)。前臺(tái)小姐收到快遞后,會(huì)判斷收件人是誰(shuí),按照收件人的要求簽收,甚至是代付。這種方案還有一個(gè)好處就是,即使公司來(lái)了很多新員工(不管多少),前臺(tái)小姐也會(huì)在收到寄給新員工們的快遞后核實(shí)代為簽收。

    這里有2層意思: 第一、現(xiàn)在委托前臺(tái)的小姐是可以代為簽收的,即程序中的現(xiàn)有的 DOM 節(jié)點(diǎn)是有事件的。

    第二、新員工也可以被前臺(tái)小姐代為簽收,即程序中新添加的 DOM 節(jié)點(diǎn)也是有事件的。

    為什么要使用事件委托

    一般來(lái)說(shuō),DOM 需要有事件處理程序,就會(huì)直接給它設(shè)處理程序,但是如果是很多 DOM 需要添加處理事件呢?例如我們有100個(gè) li,每個(gè) li 都有相同的 click 點(diǎn)擊事件,可能我們會(huì)用到 for 循環(huán),來(lái)遍歷所有 li ,然后給它們添加事件,那么會(huì)存在什么樣的問(wèn)題?

    在 JavsScript 中,添加到頁(yè)面上的事件處理程序數(shù)量將直接影響到整體運(yùn)行性能,因?yàn)樾枰粩嗟嘏c DOM 進(jìn)行交互,訪問(wèn) DOM 的次數(shù)越多,引起瀏覽器重繪與重排的次數(shù)也就越多,就會(huì)延長(zhǎng)整個(gè)頁(yè)面的交互就緒時(shí)間,這就是為什么性能優(yōu)化的主要思想之一就是減少 DOM 操作的原因、如果要用到事件委托,就會(huì)將所有的操作都放在 js 程序里面,與 DOM 的操作就只需要交互一次,這樣就可以大大減少與 DOM 的交互次數(shù),提高性能。

    每個(gè)函數(shù)都是一個(gè)對(duì)象,是對(duì)象就會(huì)占用內(nèi)存,對(duì)象越多,內(nèi)存占用率就越大,自然性能就越差了(內(nèi)存不夠用,是硬傷,哈哈),比如上面的100個(gè)li,就要占用100個(gè)內(nèi)存空間,如果是1000個(gè),10000個(gè)呢,那只能說(shuō)呵呵了,如果用事件委托,那么我們就可以只對(duì)它的父級(jí)(如果只有一個(gè)父級(jí))這一個(gè)對(duì)象進(jìn)行操作,這樣我們就需要一個(gè)內(nèi)存空間就夠了,是不是省了很多,自然性能就會(huì)更好。

    事件委托的原理

    事件委托是利用事件的冒泡原理來(lái)實(shí)現(xiàn)的,何為事件冒泡?就是事件從最深的節(jié)點(diǎn)開(kāi)始執(zhí)行,然后逐步向上傳播事件,例子:

    頁(yè)面上有一個(gè)節(jié)點(diǎn)樹(shù),div>ul>li>a,比如給最里面的 a 加一個(gè) click 點(diǎn)擊事件,那么這個(gè)事件就會(huì)一層一層的往外執(zhí)行,執(zhí)行順序 a>li>ul>div,有這么一個(gè)機(jī)制,那么我們給最外面的 div 加點(diǎn)擊事件,那么里面的 ul,li,a 做點(diǎn)擊事件的時(shí)候,都會(huì)冒泡到最外層的 div 上面,都會(huì)觸發(fā),這就是事件委托,委托他們父級(jí)代為執(zhí)行事件。

    事件委托怎么實(shí)現(xiàn)

    <ul id="ul"><li>111</li><li>222</li><li>333</li><li>444</li> </ul> 復(fù)制代碼

    實(shí)現(xiàn)功能是點(diǎn)擊li,彈出123:

    window.onload = function(){var oUl = document.getElementById('ul');var aLi = oUl.getElementsByTagName('li');for(var i = 0; i < aLi.length; i++){aLi[i].onclick = function(){alert(123);}} } 復(fù)制代碼

    上面的代碼的意思很簡(jiǎn)單,相信很多人都是這么實(shí)現(xiàn)的,我們看看有多少次的dom操作,首先要找到ul,然后遍歷li,然后點(diǎn)擊li的時(shí)候,又要找一次目標(biāo)的li的位置,才能執(zhí)行最后的操作,每次點(diǎn)擊都要找一次li;

    那么我們用事件委托的方式做又會(huì)怎么樣呢?

    window.onload = function(){var oUl = document.getElementById('ul');oUl.onclick = function(){alert(123);} } 復(fù)制代碼

    這里用父級(jí)ul做事件處理,當(dāng)li被點(diǎn)擊時(shí),由于冒泡原理,事件就會(huì)冒泡到ul上,因?yàn)閡l上有點(diǎn)擊事件,所以事件就會(huì)觸發(fā),當(dāng)然,這里當(dāng)點(diǎn)擊ul的時(shí)候,也是會(huì)觸發(fā)的,那么問(wèn)題就來(lái)了,如果我想讓事件代理的效果跟直接給節(jié)點(diǎn)的事件效果一樣怎么辦,比如說(shuō)只有點(diǎn)擊li才會(huì)觸發(fā),不怕,我們有絕招:

    Event對(duì)象提供了一個(gè)屬性叫target,可以返回事件的目標(biāo)節(jié)點(diǎn),我們成為事件源,也就是說(shuō),target就可以表示為當(dāng)前的事件操作的dom,但是不是真正操作dom,當(dāng)然,這個(gè)是有兼容性的,標(biāo)準(zhǔn)瀏覽器用ev.target,IE瀏覽器用event.srcElement,此時(shí)只是獲取了當(dāng)前節(jié)點(diǎn)的位置,并不知道是什么節(jié)點(diǎn)名稱,這里我們用nodeName來(lái)獲取具體是什么標(biāo)簽名,這個(gè)返回的是一個(gè)大寫(xiě)的,我們需要轉(zhuǎn)成小寫(xiě)再做比較(習(xí)慣問(wèn)題):

    window.onload = function(){var oUl = document.getElementById("ul");oUl.onclick = function(ev){var ev = ev || window.event;var target = ev.target || ev.srcElement;if(target.nodeName.toLowerCase() == "li"){alert(target.innerHTML);}} } 復(fù)制代碼

    這樣改下就只有點(diǎn)擊li會(huì)觸發(fā)事件了,且每次只執(zhí)行一次dom操作,如果li數(shù)量很多的話,將大大減少dom的操作,優(yōu)化的性能可想而知!

    上面的例子是說(shuō)li操作的是同樣的效果,要是每個(gè)li被點(diǎn)擊的效果都不一樣,那么用事件委托還有用嗎?

    var Add = document.getElementById("add"); var Remove = document.getElementById("remove"); var Move = document.getElementById("move"); var Select = document.getElementById("select"); Add.onclick = function(){alert('添加'); }; Remove.onclick = function(){alert('刪除'); }; Move.onclick = function(){alert('移動(dòng)'); }; Select.onclick = function(){alert('選擇'); } 復(fù)制代碼

    上面實(shí)現(xiàn)的效果我就不多說(shuō)了,很簡(jiǎn)單,4個(gè)按鈕,點(diǎn)擊每一個(gè)做不同的操作,那么至少需要4次dom操作,如果用事件委托,能進(jìn)行優(yōu)化嗎?

    var oBox = document.getElementById("box"); oBox.onclick = function(ev){var ev = ev || window.event;var target = ev.target || ev.srcElement;if(target.nodeName.toLowerCase() == 'input'){switch(target.id) {case 'add':alert('添加');break;case 'remove':alert('刪除');break;case 'move':alert('移動(dòng)');break;case 'select':alert('選擇');break;default :alert('業(yè)務(wù)錯(cuò)誤');break;}} } 復(fù)制代碼

    用事件委托就可以只用一次dom操作就能完成所有的效果,比上面的性能肯定是要好一些的

    現(xiàn)在講的都是document加載完成的現(xiàn)有dom節(jié)點(diǎn)下的操作,那么如果是新增的節(jié)點(diǎn),新增的節(jié)點(diǎn)會(huì)有事件嗎?也就是說(shuō),一個(gè)新員工來(lái)了,他能收到快遞嗎?

    <input type="button" name="" id="btn" value="添加" /> <ul id="ul1"><li>111</li><li>222</li><li>333</li><li>444</li> </ul> 復(fù)制代碼

    現(xiàn)在是移入li,li變紅,移出li,li變白,這么一個(gè)效果,然后點(diǎn)擊按鈕,可以向ul中添加一個(gè)li子節(jié)點(diǎn)

    window.onload = function(){var oBtn = document.getElementById("btn");var oUl = document.getElementById("ul");var aLi = oUl.getElementsByTagName("li");var num = 4;// 鼠標(biāo)移入變紅,移出變白for(var i = 0; i < aLi.length; i++){aLi[i].onmouseover = function(){this.style.background = 'red';}aLi[i].onmouseout = function(){this.style.background = '#fff';}}// 新增節(jié)點(diǎn)oBtn.onclick = function(){num++;var oLi = document.createElement('li');oLi.innerHTML = 111 * num;oUl.appendChild(oLi);} } 復(fù)制代碼

    這是一般的做法,但是你會(huì)發(fā)現(xiàn),新增的li是沒(méi)有事件的,說(shuō)明添加子節(jié)點(diǎn)的時(shí)候,事件沒(méi)有一起添加進(jìn)去,這不是我們想要的結(jié)果,那怎么做呢?一般的解決方案會(huì)是這樣,將for循環(huán)用一個(gè)函數(shù)包起來(lái),命名為mHover,如下:

    // 將鼠標(biāo)移出移入包裝為一個(gè)函數(shù) window.onload = function(){var oBtn = document.getElementById("btn");var oUl = document.getElementById("ul");var aLi = oUl.getElementsByTagName("li");var num = 4;// 鼠標(biāo)移入變紅,移出變白function mHover(){for(var i = 0; i < aLi.length; i++){aLi[i].onmouseover = function(){this.style.background = 'red';}aLi[i].onmouseout = function(){this.style.background = '#fff';}}}mHover();// 新增節(jié)點(diǎn)oBtn.onclick = function(){num++;var oLi = document.createElement('li');oLi.innerHTML = 111 * num;oUl.appendChild(oLi);mHover();} } 復(fù)制代碼

    雖然功能實(shí)現(xiàn)了,看著還挺好,但實(shí)際上無(wú)疑是又增加了一個(gè)dom操作,在優(yōu)化性能方面是不可取的,那么有事件委托的方式,能做到優(yōu)化嗎?

    window.onload = function(){var oBtn = document.getElementById("btn");var oUl = document.getElementById("ul");var aLi = oUl.getElementsByTagName("li");var num = 4;// 事件委托 鼠標(biāo)移入變紅,移出變白// 添加的子元素也有事件oUl.onmouseover = function(){var ev = ev || window.event;var target = ev.target || ev.srcElement;if(target.nodeName.toLowerCase() == 'li'){target.style.background = 'red';}} oUl.onmouseout = function(){var ev = ev || window.event;var target = ev.target || ev.srcElement;if(target.nodeName.toLowerCase() == 'li'){target.style.background = '#fff';}}// 新增節(jié)點(diǎn)oBtn.onclick = function(){num++;var oLi = document.createElement('li');oLi.innerHTML = 111 * num;oUl.appendChild(oLi);} } 復(fù)制代碼

    另外一個(gè)思考的問(wèn)題

    現(xiàn)在給一個(gè)場(chǎng)景 ul > li > div > p,div占滿li,p占滿div,還是給ul綁定時(shí)間,需要判斷點(diǎn)擊的是不是li(假設(shè)li里面的結(jié)構(gòu)是不固定的),那么e.target就可能是p,也有可能是div,這種情況你會(huì)怎么處理呢?

    <ul id="test"><li><p>11111111111</p></li><li><div>22222222</div></li><li><span>3333333333</span></li><li>4444444</li> </ul> 復(fù)制代碼

    如上列表,有4個(gè)li,里面的內(nèi)容各不相同,點(diǎn)擊li,event對(duì)象肯定是當(dāng)前點(diǎn)擊的對(duì)象,怎么指定到li上,下面我直接給解決方案:

    var oUl = document.getElementById('test'); oUl.addEventListener('click',function(ev){var target = ev.target;while (target !== oUl) {if(target.tagName.toLowerCase() == 'li'){alert(target.innerHTML);break;}target = target.parentNode;} }); 復(fù)制代碼

    如何阻止事件冒泡和默認(rèn)事件

    在解答這個(gè)問(wèn)題之前,先來(lái)看看事件的執(zhí)行順序

    <div><ul><li>冒泡/捕獲</li></ul> </div> 復(fù)制代碼

    實(shí)例:

    var html = document.documentElement; var body = document.body; var div = body.querySelector('div'); var ul = body.querySelector('ul'); var li = body.querySelector('li');// 捕獲 ul.addEventListener('click',captureCallback,true); li.addEventListener('click',captureCallback,true); div.addEventListener('click',captureCallback,true); body.addEventListener('click',captureCallback,true); html.addEventListener('click',captureCallback,true); // 冒泡 ul.addEventListener('click',bubblingCallback,false); li.addEventListener('click',bubblingCallback,false); div.addEventListener('click',bubblingCallback,false); body.addEventListener('click',bubblingCallback,false); html.addEventListener('click',bubblingCallback,false);function captureCallback(e){// e.stopPropagation();var target = e.currentTarget;console.log(target.tagName); } function bubblingCallback(e){// e.stopPropagation();var target = e.currentTarget;console.log(target.tagName); } 復(fù)制代碼

    點(diǎn)擊 html 中的冒泡/捕獲,可以得到以下結(jié)果

    capturing&bubbling phase.html:36 HTML capturing&bubbling phase.html:36 BODY capturing&bubbling phase.html:36 DIV capturing&bubbling phase.html:36 UL capturing&bubbling phase.html:36 LI capturing&bubbling phase.html:40 LI capturing&bubbling phase.html:40 UL capturing&bubbling phase.html:40 DIV capturing&bubbling phase.html:40 BODY capturing&bubbling phase.html:40 HTML 復(fù)制代碼

    總結(jié)就是先捕獲,后冒泡,捕獲是從上到下,冒泡是從下到上。(形象說(shuō)法:捕獲像石頭沉入海底,冒泡像氣球冒出水面)

    去掉 函數(shù) bubblingCallback 中的 e.stopPropagation()的注釋,則只會(huì)進(jìn)行捕獲,輸出

    capturing&bubbling phase.html:40 HTML capturing&bubbling phase.html:40 BODY capturing&bubbling phase.html:40 DIV capturing&bubbling phase.html:40 UL capturing&bubbling phase.html:40 LI capturing&bubbling phase.html:45 LI 復(fù)制代碼

    而取消 函數(shù) captureCallback中的 e.stopPropagation() 注釋,則只捕獲到 最上面的標(biāo)簽

    capturing&bubbling phase.html:40 HTML 復(fù)制代碼

    通過(guò)上面,我們可以得知, event.stopPropagation(),可以阻止 捕獲和冒泡階段當(dāng)前事件的進(jìn)一步傳播。

    規(guī)則:

  • 在冒泡事件和捕獲事件同時(shí)存在的情況下,捕獲事件優(yōu)先級(jí)高一點(diǎn)
  • 在同一個(gè)元素的綁定事件中,冒泡和捕獲沒(méi)有次序之分,遵循Javascript的執(zhí)行順序。
  • 在元素上同時(shí)綁定捕獲事件和冒泡事件,如果通過(guò)此元素的子級(jí)元素觸發(fā),則優(yōu)先觸發(fā)捕獲事件,若不通過(guò)此元素的子級(jí)元素觸發(fā),則按照J(rèn)avascript執(zhí)行順序觸發(fā)。
  • 事件不同瀏覽器處理函數(shù)

    • element.addEventListener(type, listener[, useCapture]); // IE6~8不支持(捕獲和冒泡通過(guò)useCapture,默認(rèn)false)
    • element.attachEvent(’on’ + type, listener); // IE6~10,IE11不支持(只執(zhí)行冒泡事件)
    • element[’on’ + type] = function(){} // 所有瀏覽器(默認(rèn)執(zhí)行冒泡事件)

    W3C 中定義了 3個(gè)事件階段,依次是 捕獲階段、目標(biāo)階段、冒泡階段。事件對(duì)象按照上圖的傳播路徑依次完成這些階段。如果某個(gè)階段不支持或事件對(duì)象的傳播被終止,那么該階段就會(huì)被跳過(guò)。舉個(gè)例子,如果Event.bubbles屬性被設(shè)置為false,那么冒泡階段就會(huì)被跳過(guò)。如果Event.stopPropagation()在事件派發(fā)前被調(diào)用,那么所有的階段都會(huì)被跳過(guò)。

    • 捕獲 階段:在事件對(duì)象到達(dá)事件目標(biāo)之前,事件對(duì)象必須從 window 經(jīng)過(guò)目標(biāo)的祖先節(jié)點(diǎn)傳播到事件目標(biāo)。這個(gè)階段被我們稱為捕獲階段,在這個(gè)階段注冊(cè)的事件監(jiān)聽(tīng)器在事件到達(dá)其目標(biāo)前必須先處理事件。
    • 目標(biāo) 階段:事件對(duì)象到達(dá)其事件目標(biāo),這個(gè)階段被我們稱之為目標(biāo)階段。一旦事件對(duì)象達(dá)到事件目標(biāo),該階段的事件監(jiān)聽(tīng)器就要對(duì)它進(jìn)行處理。如果一個(gè)事件對(duì)象類型被標(biāo)志為不能冒泡。那么對(duì)應(yīng)的事件對(duì)象在到此階段時(shí)就會(huì)終止傳播。
    • 冒泡 階段:事件對(duì)象以一個(gè)與捕獲階段相反的方向從事件目標(biāo)傳播經(jīng)過(guò)其祖先節(jié)點(diǎn)傳播到 window ,這個(gè)階段被稱之為冒泡階段,在此階段注冊(cè)的事件監(jiān)聽(tīng)器會(huì)對(duì)應(yīng)的冒泡事件進(jìn)行處理

    在一個(gè)事件完成了所有階段的傳播路徑后,它的Event.currentTarget會(huì)被設(shè)置為null并且Event.eventPhase會(huì)被設(shè)為0。Event的所有其他屬性都不會(huì)改變(包括指向事件目標(biāo)的Event.target屬性)

    跨瀏覽器的事件處理函數(shù)

    var EventUtil = {addHandler: function(element, type, handler) {if (element.addEventListener) { // DOM2element.addEventListener(type, handler, false);} else if (element.attachEvent) { // IEelement.attachEvent('on' + type, handler);} else { // DOM0element['on' + type] = handler;}},removeHandler: function(element, type, handler) {if (element.removeEventListener) {element.removeEventListener(type, handler, false);} else if (element.detachEvent) {element.detachEvent('on' + type, handler);} else {element['on' + type] = null;}} }; 復(fù)制代碼

    跨瀏覽器的事件對(duì)象:

    var EventUtil = {getEvent: function(e) {return e ? e : window.e;},getTarget: function(e) {return e.target || e.srcElement;},preventDefault: function(e) {if (e.preventDefault) {e.preventDefault();} else {e.returnValue = false;}},stopPropagation: function(e) {if (e.stopPropagation) {e.stopPropagation()} else {e.cancelBubble = true;}} } 復(fù)制代碼

    js冒泡和捕獲是事件的兩種行為,使用event.stopPropagation()起到阻止捕獲和冒泡階段中當(dāng)前事件的進(jìn)一步傳播。使用event.preventDefault()可以取消默認(rèn)事件。

    防止冒泡和捕獲

    w3c的方法是e.stopPropagation(),IE則是使用e.cancelBubble = true

    topPropagation也是事件對(duì)象(Event)的一個(gè)方法,作用是阻止目標(biāo)元素的冒泡事件,但是會(huì)不阻止默認(rèn)行為。什么是冒泡事件?如在一個(gè)按鈕是綁定一個(gè)”click”事件,那么”click”事件會(huì)依次在它的父級(jí)元素中被觸發(fā) 。stopPropagation就是阻止目標(biāo)元素的事件冒泡到父級(jí)元素。如:

    <div id='div' onclick='alert("div");'><ul onclick='alert("ul");'><li onclick='alert("li");'>test</li></ul> </div> 復(fù)制代碼

    單擊時(shí),會(huì)依次觸發(fā)alert(“l(fā)i”),alert(“ul”),alert(“div”),這就是事件冒泡。

    阻止冒泡

    window.event? window.event.cancelBubble = true : e.stopPropagation(); 復(fù)制代碼

    取消默認(rèn)事件

    w3c的方法是e.preventDefault(),IE則是使用e.returnValue = false

    preventDefault它是事件對(duì)象(Event)的一個(gè)方法,作用是取消一個(gè)目標(biāo)元素的默認(rèn)行為。既然是說(shuō)默認(rèn)行為,當(dāng)然是元素必須有默認(rèn)行為才能被取消,如果元素本身就沒(méi)有默認(rèn)行為,調(diào)用當(dāng)然就無(wú)效了。什么元素有默認(rèn)行為呢?如鏈接 <a>,提交按鈕 <input type="submit"> 等。當(dāng)Event 對(duì)象的 cancelable為false時(shí),表示沒(méi)有默認(rèn)行為,這時(shí)即使有默認(rèn)行為,調(diào)用preventDefault也是不會(huì)起作用的。

    我們都知道,鏈接 <a> 的默認(rèn)動(dòng)作就是跳轉(zhuǎn)到指定頁(yè)面,下面就以它為例,阻止它的跳轉(zhuǎn):

    //假定有鏈接<a href="http://laibh.top/" id="testA" >laibh.top</a> var a = document.getElementById("test"); a.onclick =function(e){ if(e.preventDefault){e.preventDefault();}else{window.event.returnValue == false;} } 復(fù)制代碼

    return false

    javascript的return false只會(huì)阻止默認(rèn)行為,而是用jQuery的話則既阻止默認(rèn)行為又防止對(duì)象冒泡

    下面這個(gè)使用原生js,只會(huì)阻止默認(rèn)行為,不會(huì)停止冒泡

    <div id='div' onclick='alert("div");'> <ul onclick='alert("ul");'><li id='ul-a' onclick='alert("li");'><a href="http://caibaojian.com/"id="testB">caibaojian.com</a></li> </ul> </div> <script>var a = document.getElementById("testB");a.onclick = function(){return false;}; </script> 復(fù)制代碼

    總結(jié)使用方法

    當(dāng)需要停止冒泡行為時(shí),可以使用

    function stopBubble(e) { //如果提供了事件對(duì)象,則這是一個(gè)非IE瀏覽器 if ( e && e.stopPropagation ) //因此它支持W3C的stopPropagation()方法 e.stopPropagation(); else //否則,我們需要使用IE的方式來(lái)取消事件冒泡 window.event.cancelBubble = true; } 復(fù)制代碼

    當(dāng)需要阻止默認(rèn)行為時(shí),可以使用

    //阻止瀏覽器的默認(rèn)行為 function stopDefault( e ) { //阻止默認(rèn)瀏覽器動(dòng)作(W3C) if ( e && e.preventDefault ) e.preventDefault(); //IE中阻止函數(shù)器默認(rèn)動(dòng)作的方式 else window.event.returnValue = false; return false; } 復(fù)制代碼

    事件注意點(diǎn)

    • event代表事件的狀態(tài),例如觸發(fā)event對(duì)象的元素、鼠標(biāo)的位置及狀態(tài)、按下的鍵等等;
    • event對(duì)象只在事件發(fā)生的過(guò)程中才有效。

    firefox里的event跟IE里的不同,IE里的是全局變量,隨時(shí)可用;firefox里的要用參數(shù)引導(dǎo)才能用,是運(yùn)行時(shí)的臨時(shí)變量。

    在IE/Opera中是window.event,在Firefox中是event;而事件的對(duì)象,在IE中是window.event.srcElement,在Firefox中是event.target,Opera中兩者都可用。

    function a(e){var e = (e) ? e : ((window.event) ? window.event : null); var e = e || window.event; // firefox下window.event為null, IE下event為null } 復(fù)制代碼

    查找 添加 刪除 替換 插入到某個(gè)節(jié)點(diǎn)的方法

    // 查找節(jié)點(diǎn) document.getElementById('id'); // 通過(guò)id查找,返回唯一的節(jié)點(diǎn),如果有多個(gè)將會(huì)返回第一個(gè),在IE6、7中有個(gè)bug,會(huì)返回name值相同的元素,所有要做一個(gè)兼容 document.getElementsByClassName('class'); // 通過(guò)class查找,返回節(jié)點(diǎn)數(shù)組 document.getElementsByTagName('div'); // 通過(guò)標(biāo)簽名// 創(chuàng)建節(jié)點(diǎn) document.createDocumentFragment(); // 創(chuàng)建內(nèi)存文檔碎片 document.createElement(); // 創(chuàng)建元素 document.createTextNode(); // 創(chuàng)建文本節(jié)點(diǎn)// 添加節(jié)點(diǎn) var oDiv = document.createElement('div');// 插入 Dom 節(jié)點(diǎn) // 方法1:appendChild() 把節(jié)點(diǎn)插入到父節(jié)點(diǎn)的末尾 document.body.appendChild(oDiv) // 把 div 插入到 body 中,并且位于末尾 // 方法2:insertBefore() 把節(jié)點(diǎn)插入到父節(jié)點(diǎn)的某個(gè)兄弟節(jié)點(diǎn)的前面 var oP = createElement('p'); // 創(chuàng)建一個(gè) p 節(jié)點(diǎn) document.body.insertBefore(oP,oDiv); // 把 p 節(jié)點(diǎn)插入到 div 的前面// 刪除節(jié)點(diǎn) document.body.removeChild(oP); // 刪除 p 節(jié)點(diǎn)// 替換 Dom 節(jié)點(diǎn) var oSpan = document.createElement('span'); document.body.replaceChild(oSpan,oBox); // 用 span 標(biāo)簽替換 div 標(biāo)簽復(fù)制代碼

    javaScript 的本地對(duì)象,內(nèi)置對(duì)象和宿主對(duì)象

    內(nèi)部對(duì)象

    js中的內(nèi)部對(duì)象包括Array、Boolean、Date、Function、Global、Math、Number、Object、RegExp、String以及各種錯(cuò)誤類對(duì)象,包括Error、EvalError、RangeError、ReferenceError、SyntaxError和TypeError。

    本地對(duì)象

    Array、Boolean、Date、Function、Number、Object、RegExp、String、Error、EvalError、RangeError、ReferenceError、SyntaxError和TypeError 等 new 可以實(shí)例化

    內(nèi)置對(duì)象

    其中Global和Math這兩個(gè)對(duì)象又被稱為“內(nèi)置對(duì)象”,這兩個(gè)對(duì)象在腳本程序初始化時(shí)被創(chuàng)建,不必實(shí)例化這兩個(gè)對(duì)象。

    宿主對(duì)象

    宿主環(huán)境:一般宿主環(huán)境由外殼程序創(chuàng)建與維護(hù),只要能提供js引擎執(zhí)行的環(huán)境都可稱之為外殼程序。如:web瀏覽器,一些桌面應(yīng)用系統(tǒng)等。即由web瀏覽器或是這些桌面應(yīng)用系統(tǒng)早就的環(huán)境即宿主環(huán)境。

    那么宿主就是瀏覽器自帶的 document , window 等

    == 和 === 的不同

    前者會(huì)自動(dòng)轉(zhuǎn)換類型,而后者不會(huì)。

    比較過(guò)程:

    雙等號(hào)==:

  • 如果兩個(gè)值類型相同,再進(jìn)行三個(gè)等號(hào)(===)的比較
  • 如果兩個(gè)值類型不同,也有可能相等,需根據(jù)以下規(guī)則進(jìn)行類型轉(zhuǎn)換再比較
  • 如果一個(gè)是 null,一個(gè)是 undefined 那么相等
  • 如果一個(gè)是字符串,一個(gè)是數(shù)值,把字符串轉(zhuǎn)換成數(shù)值之后再進(jìn)行比較
  • 三等號(hào) === :

  • 如果類型不同,就一定不相等
  • 如果兩個(gè)都是數(shù)值,并且是同一個(gè)值,那么相等;如果其中至少一個(gè)是 NaN,那么不相等(判斷一個(gè)值是否是 NaN,只能使用 isNaN() 來(lái)判斷)
  • 如果兩個(gè)都是字符串,每個(gè)位置的字符都一樣,那么相等,否則不相等
  • 如果兩個(gè)值都是 true,或是 false,那么相等
  • 如果兩個(gè)值都引用同一個(gè)對(duì)象或者是函數(shù),那么相等,否則不相等
  • 如果兩個(gè)值都是 null,或者是 undefined 那么相等。
  • javaScript 的同源策略

    同源策略的含義:腳本只能讀取和所屬文檔來(lái)源相同的窗口和文檔的屬性。

    同源指的是主機(jī)名、協(xié)議和端口號(hào)的組合

    同源策略帶來(lái)的限制

  • cookie、LocalStorage 和 IndexDB無(wú)法讀取

  • DOM 無(wú)法獲取

  • AJAX請(qǐng)求無(wú)法發(fā)送

  • 主流跨域請(qǐng)求解決方案

    1、JSONP 實(shí)現(xiàn)跨域

    為了便于客戶端使用數(shù)據(jù),逐漸形成了一種非正式傳輸協(xié)議。人們把它稱作JSONP。該協(xié)議的一個(gè)要點(diǎn)就是允許用戶傳遞一個(gè)callback參數(shù)給服務(wù)端,然后服務(wù)端返回?cái)?shù)據(jù)時(shí)會(huì)將這個(gè)callback參數(shù)作為函數(shù)名來(lái)包裹住JSON數(shù)據(jù),這樣客戶端就可以隨意定制自己的函數(shù)來(lái)自動(dòng)處理返回?cái)?shù)據(jù)了。

    jsonp的核心是動(dòng)態(tài)添加 script標(biāo)簽 來(lái)調(diào)用服務(wù)器提供的js腳本。

    說(shuō)說(shuō)JSON和JSONP

    JSONP實(shí)現(xiàn)原理?

  • JS 跨域請(qǐng)求資源會(huì)被限制。但是在頁(yè)面中,script 標(biāo)簽跨域時(shí),卻是沒(méi)有限制的(frame,img同理)。
  • 我們通過(guò),script的src屬性,請(qǐng)求服務(wù)器,并通過(guò)參數(shù)(如:?callback=foo,foo為本地一個(gè)執(zhí)行的方法)告訴服務(wù)器返回指定格式的JS腳本,并將數(shù)據(jù)封裝在此腳本中。
  • 服務(wù)器再配合客戶端返回一段腳本 (如:* foo({“id”: 123, “name” : 張三, “age”: 17});* ),其實(shí)返回的就是 一個(gè)客戶端本地的一個(gè) 可執(zhí)行的方法的方法名, 并將要返回的 數(shù)據(jù)封裝在了參數(shù) 里。
  • 請(qǐng)求到資源后,本地就會(huì)執(zhí)行此方法,通過(guò)對(duì)參數(shù)的處理,也就獲取到了我們所要的數(shù)據(jù)。
  • JSONP的局限性

    JSONP 方式,固然方便強(qiáng)大。但是他的局限性在于,它無(wú)法完成POST請(qǐng)求。即是我們將type改為post,在發(fā)送請(qǐng)求時(shí),依然會(huì)是以Get的方式。

    2、CORS跨域

    CORS原理

    CORS(Cross-Origin-Resource Sharing,跨院資源共享)是一種允許多種資源(圖片,Css文字,Javascript等)在一個(gè)Web頁(yè)面請(qǐng)求域之外的另一個(gè)域的資源的機(jī)制。 跨域資源共享這種機(jī)制讓W(xué)eb應(yīng)用服務(wù)器支持跨站訪問(wèn)控制,從而使得安全的進(jìn)行跨站數(shù)據(jù)傳輸成為了可能。

    通過(guò)這種機(jī)制設(shè)置一系列的響應(yīng)頭,這些響應(yīng)頭允許瀏覽器與服務(wù)器進(jìn)行交流,實(shí)現(xiàn)資源共享。

    各語(yǔ)言設(shè)置響應(yīng)頭的方法

    CORS 解決方案相對(duì)于JSONP 更加靈活,而且支持POST請(qǐng)求,是跨域的根源性解決方案

    3、代理層

    JSONP 和CORS 是主流的 跨域問(wèn)題 的解決方案。除了他們吶,還有一種解決方案,就是代理層。簡(jiǎn)要說(shuō)一下

    JS 調(diào)用本源的后臺(tái)的方法(這樣就不存在跨域的問(wèn)題),而通過(guò)后臺(tái)(任何具有網(wǎng)絡(luò)訪問(wèn)功能的后臺(tái)語(yǔ)言,ASP.NET ,JAVA,PHP等)去跨域請(qǐng)求資源,而后將結(jié)果返回至前臺(tái)。

    另外也可以看看

    同源策略

    JavaScript的同源策略 Redirect 1

    編寫(xiě)一個(gè)數(shù)組去重的方法

    var arr = [1,1,3,4,2,4,7] => [1,2,4,2,7]

    // 方法1 雙重循環(huán),逐個(gè)判斷數(shù)組中某個(gè)元素是否與其他元素相同,相同則去掉,并且索引減1,重復(fù)執(zhí)行直到雙重遍歷完成 function DuplicateRemoval(arr){for(var i = 0; i < arr.length-1; i++){for(var j = i + 1; j < arr.length; j++){if(arr[i] == arr[j]){arr.splice(j,1);j--;}}}return arr; } var arr=[1,1,3,4,2,4,7]; console.log(DuplicateRemoval(arr));// 方法2 借助 indexOf() 方法判斷此元素在該數(shù)組中首次出現(xiàn)位置下標(biāo)與循環(huán)的下標(biāo)是否相同 function DuplicateRemoval(arr){for(var i = 0; i < arr.length; i++){if(arr.indexOf(arr[i]) !== i){arr.splice(i,1);i--}}return arr; } var arr=[1,1,3,4,2,4,7]; console.log(DuplicateRemoval(arr)); // 方法3 利用數(shù)組的方法 filter() var arr=[1,1,3,4,2,4,7]; var result = arr.filter( (element, index, self) => self.indexOf(element) === index ); console.log(result);// 方法4 利用新數(shù)組 通過(guò)indexOf判斷當(dāng)前元素在數(shù)組中的索引如果與循環(huán)相同則添加到新數(shù)組中 var arr=[1,1,3,4,2,4,7]; function Add(arr){var result = [];for(var i = 0; i < arr.length; i++){if(arr.indexOf(arr[i]) === i){result.push(arr[i]);}}return result; } console.log(Add(arr));// 方法5 ES6方法 Set() Set函數(shù)可以接受一個(gè)數(shù)組(或類似數(shù)組的對(duì)象)作為參數(shù),用來(lái)初始化。 var arr=[1,1,3,4,2,4,7]; console.log([...new Set(arr)]); 復(fù)制代碼

    JavaScript 的數(shù)據(jù)類型都有什么

    基本數(shù)據(jù)類型:String,Boolean,number,undefined,object,Null

    引用數(shù)據(jù)類型:Object(Array,Date,RegExp,Function)

    類型檢測(cè)

    typeof

    typeof 運(yùn)算精度只能是基礎(chǔ)類型也就是 number , string , undefined , boolean , object ,要注意的是 null 和數(shù)組使用 typeof 運(yùn)算符得到的也是 object

    console.log(typeof 123); // number console.log(typeof 'type'); // string console.log(typeof null); // object console.log(typeof undefined); // undefined console.log(typeof true); // boolean console.log(typeof []); // object console.log(typeof {}); // object console.log(typeof function(){}); // function 復(fù)制代碼
    instanceof

    用于判斷一個(gè)變量是否某個(gè)對(duì)象的實(shí)例,或用于判斷一個(gè)變量是否某個(gè)對(duì)象的實(shí)例

    instanceof 運(yùn)算符可以精確到是哪一種類型的引用,但 instanceof 也有一個(gè)缺陷就是對(duì)于直接賦值的數(shù)字,字符串,布爾值以及數(shù)組是不能將其識(shí)別為Number,String,Boolean,Array。

    console.log(123 instanceof Number); // false console.log('type' instanceof String); // false console.log(true instanceof Boolean); // false console.log([] instanceof Array); // true console.log({} instanceof Object); // true console.log(function(){} instanceof Function); // true 復(fù)制代碼
    toString.call()
    console.log(toString.call(123) ); // [object Number] console.log(toString.call('type')); // [object String] console.log(toString.call(null)); // [object Null] console.log(toString.call(undefined)); // [object Undefined] console.log(toString.call(true)); // [object Boolean] console.log(toString.call([])); // [object Array] console.log(toString.call({})); // [object Object] console.log(toString.call(function(){})); // [object Function] 復(fù)制代碼
    constructor

    構(gòu)造函數(shù)的屬性 用來(lái)判別對(duì)創(chuàng)建實(shí)例對(duì)象的函數(shù)的引用,另外 constructor 可以被改寫(xiě)

    var number = 123, string = 'type', boolean = true, arr = [], obj = {}, fn = function(){};console.log( number.constructor); // ? Number() { [native code] } console.log( string.constructor); // ? String() { [native code] } console.log( boolean.constructor); // ? Boolean() { [native code] } console.log( arr.constructor); // ? Array() { [native code] } console.log( obj.constructor); // ? Object() { [native code] } console.log( fn.constructor); // ? Function() { [native code] } 復(fù)制代碼

    也可以用 constructor.name就會(huì)返回函數(shù)名

    Object.prototype.toString.call()

    這個(gè)方法其實(shí)跟上面 toString()是一樣的,只是上面那個(gè)方法有可能會(huì)被重寫(xiě)。所以用這個(gè)比較穩(wěn)妥,所有對(duì)象都包含有一個(gè)內(nèi)部屬性[[Class]] ,這個(gè)屬性不能直接訪問(wèn),但是我們可以通過(guò)Object.prototype.toString.call()

    console.log(Object.prototype.toString.call(123) ); // [object Number] console.log(Object.prototype.toString.call('type')); // [object String] console.log(Object.prototype.toString.call(null)); // [object Null] console.log(Object.prototype.toString.call(undefined)); // [object Undefined] console.log(Object.prototype.toString.call(true)); // [object Boolean] console.log(Object.prototype.toString.call([])); // [object Array] console.log(Object.prototype.toString.call({})); // [object Object] console.log(Object.prototype.toString.call(function(){})); // [object Function] 復(fù)制代碼

    需要注意的是IE6/7/8中 Object.prototype.toString.apply(null)返回“[object Object]”。

    js 中 innerText/value/innerHTML三個(gè)屬性的區(qū)別

    <div value = "3" id="target3"><input type="text" value="1" id="target1"><span id="target2" value="2">span</span> </div> 復(fù)制代碼var a = document.getElementById("target1"); var b = document.getElementById("target2"); var c = document.getElementById("target3"); console.log('----------'); console.log(a.value); // 1 console.log(a.innerHTML); console.log(a.innerText); console.log('----------'); console.log(b.value); // undefined console.log(b.innerHTML); // span console.log(b.innerText); // span console.log('----------'); console.log(c.value); // undefined console.log(c.innerHTML); // <input type="text" value="1" id="target1"><span id="target2" value="2">span</span> console.log(c.innerText); // span 復(fù)制代碼

    總結(jié):

  • innerText是標(biāo)簽內(nèi)的文本,輸出的是字符串,它可以獲得某個(gè)節(jié)點(diǎn)下面的所有標(biāo)簽內(nèi)的文本
  • innerHtml 可以獲得某個(gè)DOM 節(jié)點(diǎn)內(nèi)部的 HTML 代碼
  • value是表單元素的屬性,獲得是表單元素里面的值
  • 希望獲取到頁(yè)面中所有的 checkbox 怎么做?( ( 不使用第三方框架) )

    html:

    <input type="checkbox"> <input type="checkbox"> <input type="checkbox"> 復(fù)制代碼window.onload = function(){var domList = document.getElementsByTagName('input');var checkBoxList = []; // 返回所有的 checkbox var len = domList.length; // 緩存到局部變量while(len--){if(domList[len].type = 'checkbox'){checkBoxList.push(domList[len]);}}console.log(checkBoxList); // ?[input, input, input] } 復(fù)制代碼

    當(dāng)一個(gè) Dom節(jié)點(diǎn)被點(diǎn)擊時(shí)候,我們希望能夠執(zhí)行一個(gè)函數(shù),應(yīng)該怎么做?

    <!-- 直接在 DOM 里綁定事件:--> <div onlick = "test()"> 復(fù)制代碼// 在js 里面通過(guò) onclick 綁定 xxx.onclick = test // 在事件里面添加綁定 addEventListener(xxx, 'click', test) 復(fù)制代碼

    Javascript 的事件流模型都有什么?

    "事件冒泡":事件開(kāi)始由最具體的元素接受,然后逐級(jí)向上傳播

    “事件捕捉”:事件由最不具體的節(jié)點(diǎn)先接收,然后逐級(jí)向下,一直到最具體的

    “DOM 事件流”:三個(gè)階段,事件捕捉,目標(biāo)階段。事件冒泡。

    已知有字符串 foo=”get-element-by-id”,寫(xiě)一個(gè) function 將其轉(zhuǎn)化成駝峰表示法”——getElementById”。

    var foo = "get-element-by-id"; function combo(msg){var arr = msg.split('-');for(var i=1;i < arr.length; i++){arr[i] = arr[i].charAt(0).toUpperCase()+arr[i].substr(1,arr[i].length-1);}msg = arr.join('');return msg; } console.log(combo(foo)); // getElementById 復(fù)制代碼

    輸出今天的日期,以 YYYY-MM-DD 的方式

    var date = new Date(); var year = date.getFullYear(); var month = date.getMonth() + 1; month = month < 10 ? '0' + month : month; var day = date.getDate(); day = day < 10 ? '0' + day : day; console.log([year,month,day].join('-')) // 2018-11-01 復(fù)制代碼

    將字符串 ” <tr><td>{${$name}</td></tr>” 中的 {$id} 替換 成 10 , {$name} 替換成 Tony (使用正則表達(dá)式)

    var str = '<tr><td>{$id}</td><td>{$name}</td></tr>'; str.replace(/{\$id}/g,10).replace(/{\$name}/,'Tony') 復(fù)制代碼

    為了保證頁(yè)面輸出安全,我們經(jīng)常需要對(duì)一些特殊的字符進(jìn)行轉(zhuǎn)義,請(qǐng)寫(xiě)一個(gè)函數(shù) escapeHtml ,將 <, >, &, “ 進(jìn)行轉(zhuǎn)義

    function escapeHtml(str){return str.replace(/[<>”&]/g,function(match){switch(match) {case "<":return '&lt';break;case ">":return '&gt'break;case "\”":return '&quot'break; case "&":return '&amp'break;}}); } 復(fù)制代碼

    參考鏈接:

  • JS類型轉(zhuǎn)換(強(qiáng)制和自動(dòng)的規(guī)則)
  • JavaScript 數(shù)據(jù)類型轉(zhuǎn)換(顯式與隱式)
  • DOM標(biāo)準(zhǔn)與IE的html元素事件模型區(qū)別
  • ie和dom事件流的區(qū)別
  • 前端面試題——call與apply方法的異同
  • JavaScript中B繼承A的方法Me丶微笑
  • Javascript 中 作用域、閉包與 this 指針
  • 理解JAVASCRIPT的閉包
  • 深入理解JS中的變量作用域
  • 解決js函數(shù)閉包內(nèi)存泄露問(wèn)題的辦法
  • js中的事件委托或是事件代理詳解
  • JavaScript捕獲和冒泡探討
  • JS阻止冒泡和取消默認(rèn)事件(默認(rèn)行為)
  • javascript 原生方法對(duì)dom節(jié)點(diǎn)的操作,創(chuàng)建、添加、刪除、替換、插入、復(fù)制、移動(dòng)等操作
  • JavaScript中本地對(duì)象、內(nèi)置對(duì)象和宿主對(duì)象
  • js中==和===區(qū)別
  • 同源策略與JS跨域請(qǐng)求(圖文實(shí)例詳解)
  • Js數(shù)組去重方法總結(jié)
  • javascript 六種數(shù)據(jù)類型(一)
  • 轉(zhuǎn)載于:https://juejin.im/post/5bcd892d6fb9a05d2e1bd758

    總結(jié)

    以上是生活随笔為你收集整理的前端面试题目汇总摘录(JS 基础篇)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    在线综合色 | 精品99免费视频 | 午夜久久影视 | 国产又粗又硬又爽的视频 | 啪啪动态视频 | 9i看片成人免费看片 | 日日干美女 | 国产精品麻豆视频 | 欧美在线一二区 | 日韩精品免费一区二区三区 | 麻豆成人精品视频 | 在线 国产 亚洲 欧美 | 国产日韩在线一区 | 久久精国产 | 成年免费在线视频 | 中文字幕在| 三级黄色网址 | 狠狠狠狠狠狠干 | 精品伊人久久久 | 青青草在久久免费久久免费 | 精品一区二区三区电影 | 国产在线精品二区 | 91精品国产高清自在线观看 | 色午夜影院 | 欧美在线观看小视频 | 欧美最新大片在线看 | 日韩高清毛片 | 日韩精品久久久久 | 国产高清视频在线免费观看 | 色综合中文字幕 | 亚洲男男gaygay无套同网址 | 91麻豆精品国产自产在线 | 91人网站 | 日本资源中文字幕在线 | 美女av免费看 | 中文字幕在线观看资源 | 天操夜夜操 | 日韩欧美综合精品 | 99情趣网视频 | 国产精品一码二码三码在线 | 亚洲人久久久 | 国产免费av一区二区三区 | 亚洲免费永久精品国产 | 久久有精品 | 欧美日韩综合在线 | 中文av字幕在线观看 | 国产精品综合久久久久 | 91视频电影 | 欧美日韩一区二区在线观看 | 99视频在线精品 | 麻豆久久一区 | 亚洲在线成人精品 | 91在线公开视频 | 婷婷久久综合网 | 精品美女视频 | 波多野结衣在线观看视频 | 成人av.com| 午夜av在线| 91精品国产欧美一区二区成人 | 在线视频观看你懂的 | 国产免费久久 | 美女网站久久 | 精久久久久 | 久精品在线观看 | 又黄又刺激又爽的视频 | 激情婷婷六月 | 免费99视频 | 国产视频日韩视频欧美视频 | 日本韩国中文字幕 | 伊人天天狠天天添日日拍 | 日韩h在线观看 | 色成人亚洲 | 免费看的黄色 | 欧美黑人猛交 | 久久国产成人午夜av影院潦草 | 免费黄色在线网址 | 最近中文字幕完整视频高清1 | 91传媒91久久久 | 中文字幕精品视频 | 亚洲理论在线观看电影 | 91久久久久久久一区二区 | 国产精品久久久久久999 | 国产精品免费视频观看 | 91高清视频免费 | a天堂中文在线 | 日本在线精品视频 | 国产日韩视频在线播放 | 夜夜夜夜猛噜噜噜噜噜初音未来 | 成人免费大片黄在线播放 | 欧美在线视频第一页 | 国产九九热视频 | 69av在线视频| 日本久久久久久久久久 | 99在线视频精品 | 欧美美女激情18p | 久久99电影 | 久久国产精品久久w女人spa | 黄色小说视频在线 | 日韩| 国产不卡免费 | 黄色aaa毛片| 国产在线观看你懂的 | 国产精品麻豆果冻传媒在线播放 | 午夜精品一区二区国产 | 超碰97人人爱 | 黄色大全免费网站 | 在线99| 91丨porny丨九色 | 久久伊人八月婷婷综合激情 | 四虎免费在线观看视频 | 干干日日 | 国产精品一级在线 | 国产v视频 | 精久久久久 | 中文字幕高清免费日韩视频在线 | 亚洲激情在线观看 | 亚洲精品高清视频在线观看 | 中文在线中文a | 久草爱 | 中文字幕av最新 | 免费精品国产 | 欧美一区在线看 | 亚洲日本一区二区在线 | 伊人va| 亚洲精品视频免费观看 | 国产成人精品免费在线观看 | 在线播放 亚洲 | 在线中文字幕网站 | 激情婷婷av | 九九在线精品视频 | 亚洲三级av | 国产一区成人在线 | 黄色天堂在线观看 | 亚洲第一区在线观看 | 在线看的av网站 | 欧美精品免费在线 | 在线看国产 | 免费看黄在线 | 在线免费观看国产精品 | 在线午夜 | 色婷婷丁香 | 999电影免费在线观看 | 天天艹 | 国产精品久久网站 | 超碰午夜| 男女免费av | 国产精国产精品 | 亚洲综合五月 | 久久激情视频 久久 | 色婷婷色 | 超级碰碰碰视频 | 在线免费91 | 91色欧美| 97视频免费看 | 国产精品久久久久久妇 | 久久久久久黄色 | 国产精品高清免费在线观看 | 在线观看日韩免费视频 | 久久在线一区 | 成人在线你懂得 | 久久久久久久久久国产精品 | 成人a大片 | 看全黄大色黄大片 | 国产一区高清在线观看 | 国产午夜不卡 | 久久久在线免费观看 | 久久久亚洲电影 | 午夜精品久久久久久久久久久久 | 日韩黄色av网站 | 五月婷婷影院 | 69久久99精品久久久久婷婷 | 蜜臀久久99精品久久久酒店新书 | 久草在线免费电影 | 精品伊人久久久 | 久久久国产一区二区 | 337p日本欧洲亚洲大胆裸体艺术 | 国产精品久久99综合免费观看尤物 | 国产精品99在线播放 | 日韩va在线观看 | 黄a在线观看 | 久久激情五月激情 | 很黄很黄的网站免费的 | 国产又粗又猛又黄又爽 | 国产精品一区在线播放 | 国产精品一区二区三区视频免费 | 中文字幕av一区二区三区四区 | 一区三区在线欧 | 97色资源| 狠狠躁夜夜躁人人爽超碰97香蕉 | 成人av在线影院 | 亚洲中字幕 | 久久久精品影视 | 韩日精品在线 | 一区 二区 精品 | 日韩在线观看小视频 | 欧美性脚交 | 91桃色在线播放 | 超碰人人在线观看 | 国产小视频在线观看 | 国产一区 在线播放 | 亚洲精品2区 | 天天干天天做天天操 | 免费在线国产视频 | 久久国产成人午夜av影院潦草 | 91高清免费在线观看 | 欧美了一区在线观看 | 成人在线播放视频 | 超碰成人网 | www国产精品com | 久久久久久久久久久久国产精品 | 免费观看9x视频网站在线观看 | 九九九九九九精品任你躁 | 手机av观看 | 亚洲好视频 | 国产高清免费视频 | 久久不见久久见免费影院 | 国产精品久久久久久五月尺 | 黄网站色视频免费观看 | 91高清视频在线 | 欧美日韩不卡一区二区 | 日韩激情免费视频 | 免费福利在线播放 | 国产亚洲一区二区在线观看 | 日韩毛片在线播放 | 色网址99| 天天草天天干天天 | 日韩免费视频 | 四虎影视成人永久免费观看亚洲欧美 | 日韩成人免费在线观看 | 天天干人人干 | 日韩视频a | 水蜜桃亚洲一二三四在线 | 国产免费嫩草影院 | 免费视频网 | 日韩中文字幕视频在线 | 精品a视频 | 欧洲亚洲精品 | 永久免费视频国产 | 一级大片在线观看 | 美女视频一区二区 | 九九有精品 | 久久免费视频在线观看30 | 日韩一区二区三区免费电影 | 欧美男女爱爱视频 | 欧美少妇影院 | 干天天 | 亚洲国产视频a | 久久99精品热在线观看 | 波多野结衣视频一区二区三区 | 国产色婷婷精品综合在线手机播放 | 狠狠躁夜夜av | 在线看国产一区 | 亚洲国产一区av | 国产一级不卡视频 | 久久久久国产成人精品亚洲午夜 | 久草精品视频在线播放 | 在线亚洲激情 | 午夜精品久久久久久久99水蜜桃 | 91黄色影视 | 国产高清区 | 欧亚日韩精品一区二区在线 | 日韩欧美精品在线观看 | 色综合久久中文字幕综合网 | 亚洲精品黄色在线观看 | 久草免费在线视频 | 成年人在线免费看视频 | 在线免费观看视频a | 超碰在线人人爱 | 亚洲欧洲美洲av | 精品久久久免费视频 | 麻豆影视在线免费观看 | 国产黄a三级三级 | 国产成人免费观看 | 国产精品久久久电影 | 国产精品欧美在线 | 亚洲久草网 | 中文字幕av日韩 | 一本一本久久a久久精品综合小说 | 欧美日韩在线视频一区二区 | 欧美久久久久久久久 | 97人人爽人人| 六月丁香婷婷网 | 欧美永久视频 | 国产黑丝一区二区三区 | 成人在线观看你懂的 | 日韩在线观看第一页 | 国产精品一区二区av影院萌芽 | 日韩高清免费在线观看 | 在线看的av网站 | 狠狠搞,com | 国产a精品| 麻豆国产视频 | 久艹在线播放 | 97精品国产97久久久久久粉红 | 亚洲精品成人免费 | 国产成人三级三级三级97 | 国产福利午夜 | 黄色大全在线观看 | 欧美9999| 全久久久久久久久久久电影 | 天天操婷婷 | av高清免费 | 日韩日韩日韩日韩 | 久久夜色精品亚洲噜噜国4 午夜视频在线观看欧美 | 国产99在线免费 | 奇米网8888| 久久久国产在线视频 | 成人禁用看黄a在线 | 最新动作电影 | 日韩中文字幕a | 在线黄频 | 日本中文在线 | 91成人国产 | 日韩在线中文字幕视频 | 欧美一级片免费观看 | 成人资源在线观看 | 国产精品毛片一区二区 | 黄色a一级片 | 99免费视频 | 免费av观看网站 | 97精品国产91久久久久久 | 免费网站在线观看成人 | 成人av在线亚洲 | 久久这里只有精品视频首页 | 久久婷婷亚洲 | 91精品国产福利在线观看 | 久久电影国产免费久久电影 | 不卡的av在线| 在线观看的黄色 | 成人黄色片在线播放 | 又色又爽的网站 | 久久久久久久av | 免费黄色网址网站 | 麻豆视频免费在线播放 | 在线色亚洲 | 成人在线播放免费观看 | 最新久久久 | 97精品国产 | 国产伦精品一区二区三区免费 | 免费a级毛片在线看 | 日韩av电影网站在线观看 | 中文字幕一区二区三区精华液 | 91日韩在线播放 | 久久精品网站视频 | 久久精品视频中文字幕 | 久久久久久久久精 | 婷婷国产视频 | 国产精品亚| 久久久国产精品网站 | 久久这里有 | 国产一二三区在线观看 | 欧洲一区二区三区精品 | 超碰免费成人 | 韩国精品视频在线观看 | 亚洲全部视频 | 国产精华国产精品 | av中文字幕第一页 | 丁香五月网久久综合 | 欧美日韩国产一区 | 女人18精品一区二区三区 | 日韩二级毛片 | 日韩久久精品一区二区 | 亚洲一区日韩在线 | 中国一级特黄毛片大片久久 | 色婷婷综合久久久久 | 久久久精品免费看 | 亚洲欧洲久久久 | 成年人黄色免费视频 | 成人av一区二区三区 | 欧美一区二区三区特黄 | 黄色一级免费电影 | 欧美二区在线播放 | 日韩av电影中文字幕在线观看 | 精品国产片 | 亚洲无吗视频在线 | 久久精品韩国 | 欧美日在线观看 | www.超碰97.com | 欧美一区免费在线观看 | 国产精品亚洲a | 成人综合婷婷国产精品久久免费 | 麻花豆传媒一二三产区 | www视频免费在线观看 | 黄色片视频免费 | 日韩r级电影在线观看 | 成人a免费视频 | 国产亚洲午夜高清国产拍精品 | 国产 一区二区三区 在线 | x99av成人免费 | 国内精品在线看 | 精品国产免费av | 国产伦精品一区二区三区高清 | 免费三级骚 | 日日干天天爽 | 成年人免费在线观看网站 | 成人动漫视频在线 | 国产在线理论片 | 91九色在线视频 | 色九九视频| 日本中文一区二区 | 日韩精品久久一区二区 | 日本久久久久久久久久 | 成年人app网址 | 狠狠躁日日躁狂躁夜夜躁 | 草久视频在线 | 一区二区av | 亚洲一区二区三区毛片 | 一区二区三区日韩在线 | 精品国内自产拍在线观看视频 | 在线视频一区二区 | 成人免费视频网站 | 国产精品久久久久av | 麻豆视频在线播放 | 日b视频在线观看网址 | 黄色a在线观看 | 日韩欧美国产免费播放 | 亚洲精品a区 | 日韩国产精品一区 | 丁香激情综合 | 91传媒在线看 | 日韩有码专区 | 97av在线视频免费播放 | 在线影视 一区 二区 三区 | 免费www视频 | 日日夜夜精品 | 亚洲国产精品视频 | 日本韩国中文字幕 | 91视频观看免费 | 美女久久久久久 | 香蕉网在线播放 | 天天操狠狠操 | av专区在线 | 亚洲视频每日更新 | 精品国产伦一区二区三区观看方式 | 一区二区三区日韩精品 | 成人在线观看免费视频 | 欧美成人按摩 | 探花视频在线观看免费 | 精品在线观看免费 | 亚洲精品中文字幕视频 | 黄色片免费电影 | 天天干天天拍天天操天天拍 | 91高清免费在线观看 | 国产亚洲小视频 | 97精产国品一二三产区在线 | 99视频精品全部免费 在线 | 丁香婷婷综合激情五月色 | 免费高清国产 | 黄色的网站在线 | 天天干天天操天天做 | 永久黄网站色视频免费观看w | 久久天天躁夜夜躁狠狠躁2022 | 久久a久久 | 久久久免费看 | 欧美性黄网官网 | 中文字幕在线资源 | 福利精品在线 | 999超碰 | 88av视频| 五月天激情视频在线观看 | 久久手机看片 | 五月天综合激情 | 精品在线小视频 | 国产免费亚洲高清 | 亚洲一区二区三区四区精品 | 天天色图 | 激情视频一区二区 | 日日躁夜夜躁xxxxaaaa | 特级西西www44高清大胆图片 | 奇米影视8888在线观看大全免费 | 亚洲无吗av| 午夜精品一区二区三区在线 | 成片人卡1卡2卡3手机免费看 | 91av视频网站 | 日韩区欧美久久久无人区 | 日韩欧美大片免费观看 | 最新色视频 | 久久久精品欧美一区二区免费 | 人人射av| 免费观看www视频 | 国产不卡免费 | 亚洲精品视频第一页 | 一级久久精品 | 99久久99久久综合 | 精品一区二区在线免费观看 | 天天做天天爱天天综合网 | 精品字幕在线 | 911香蕉 | 午夜黄色 | av福利免费 | av免费在线网站 | 久久刺激视频 | 日韩激情视频在线 | 婷婷激情五月 | 国产98色在线 | 日韩 | 精品人人人人 | 欧美俄罗斯性视频 | 91丨九色丨勾搭 | 国产成人精品av | 日韩欧美一区二区三区视频 | 人人揉人人揉人人揉人人揉97 | a级国产乱理伦片在线播放 久久久久国产精品一区 | 在线观看免费一级片 | 中文字幕在线视频第一页 | 亚洲国产美女久久久久 | 国产精品免费一区二区三区 | 欧美性生活免费看 | 久久在线播放 | 最新一区二区三区 | 国产亚洲精品福利 | 999久久久久久 | 国产又粗又猛又爽又黄的视频免费 | 久99久在线 | 黄色精品在线看 | 天天色成人 | 麻豆果冻剧传媒在线播放 | 激情婷婷综合网 | 97超碰国产精品 | av片在线观看免费 | 综合久久久久久 | 天天操天天色综合 | 91精品国产成人观看 | 超碰日韩在线 | 啪啪资源| 91精品导航 | 亚洲天天 | 欧美福利网站 | 欧美日韩国产伦理 | 日日干视频 | 98涩涩国产露脸精品国产网 | 好看的国产精品视频 | 99在线精品视频在线观看 | 手机看片1042 | 免费开视频 | 91av在线免费视频 | 日韩激情在线视频 | 中文字幕一区二区三区在线播放 | 色av婷婷| 久久久人 | 在线观看中文字幕网站 | 亚洲麻豆精品 | 毛片网站免费在线观看 | 丁香视频五月 | 一本到在线 | 天堂av官网 | 精品国产1区二区 | 久久综合狠狠综合久久激情 | 成人午夜剧场在线观看 | 久久精品国产亚洲a | 伊人中文网 | 中文字幕在线观看免费高清完整版 | 欧美日韩aa| 四虎www | av福利第一导航 | 国产美女主播精品一区二区三区 | 婷婷在线不卡 | 亚洲精品在线观看中文字幕 | 亚洲精品91天天久久人人 | 久久精品免视看 | 91福利视频免费 | 人人干人人搞 | 精品91久久久久 | 91av精品 | 成年人在线视频观看 | 一区二区三区久久精品 | 亚洲精品av中文字幕在线在线 | 91精品国产高清 | 97超碰中文| 亚洲最大av在线播放 | 一区二区三区电影在线播 | 亚洲高清视频在线 | 日本高清xxxx| 高清有码中文字幕 | 久99久在线 | 波多野结衣电影久久 | 99在线看 | 久久毛片网站 | 349k.cc看片app| 日韩在线免费 | 91在线你懂的| 日韩久久精品一区二区 | 欧美日本一二三 | 麻豆视频一区 | 精品在线看 | 欧美日韩xxx | 国产一级精品视频 | 人人添人人澡人人澡人人人爽 | 91视频高清 | 成年人免费在线播放 | 成年人免费av | 国产 字幕 制服 中文 在线 | 亚洲日本va午夜在线影院 | 在线有码中文 | 国产精品v欧美精品 | 四虎在线观看 | 日韩一区二区三免费高清在线观看 | 免费黄色av电影 | 三级视频国产 | 亚洲国产精品视频 | www.久久99 | 国产精品18久久久久久久网站 | 一本色道久久综合亚洲二区三区 | 色婷婷福利视频 | 国产一区二区三区在线免费观看 | 超碰在线人人爱 | 96国产精品视频 | 欧美一级在线观看视频 | 中文字幕在线看视频国产中文版 | 综合天堂av久久久久久久 | 久久久久久综合网天天 | 蜜桃av人人夜夜澡人人爽 | 日韩精品久久久 | 999视频在线播放 | 精品久久精品久久 | av大全在线播放 | 97超碰中文 | 岛国av在线免费 | 97av视频 | 五月婷婷色 | 久久伊人精品一区二区三区 | 亚洲成人第一区 | 中文字幕人成乱码在线观看 | 91精品视频免费 | 99精品国产福利在线观看免费 | 国产精品6| 在线影院中文字幕 | 亚洲成人网在线 | 久久综合免费 | 国产视频在线免费 | 揉bbb玩bbb少妇bbb| 中文综合在线 | 国产 日韩 中文字幕 | 亚洲一区视频在线播放 | 国产一级做a爱片久久毛片a | 349k.cc看片app| 成年人黄色在线观看 | 国产精品九九九 | 91视频链接 | 国产福利91精品 | av 一区 二区 久久 | 久久乐九色婷婷综合色狠狠182 | 久久综合国产伦精品免费 | 中文字幕av免费 | 视频在线日韩 | 99在线视频网站 | 91在线免费播放视频 | 1024手机看片国产 | 激情五月婷婷激情 | 精品久久网站 | 亚洲国产合集 | 99久久久久成人国产免费 | 国产自制av| 国产h在线播放 | 色综合网在线 | 三级在线国产 | 久久国产网 | 日日夜夜操av| 亚洲综合在线发布 | 欧美一区在线看 | 在线天堂中文www视软件 | 亚洲精品一区二区在线观看 | 中文字幕在线观看免费 | 亚洲精品免费视频 | 日韩网站一区二区 | 国产在线播放一区二区 | 99电影 | 91av在线电影 | 久久九九免费 | 中日韩欧美精彩视频 | 国产小视频网站 | 国产精品午夜久久久久久99热 | 国产精品中文字幕在线 | 成人理论电影 | va视频在线观看 | 国产在线精品播放 | 欧美午夜a | 91视频免费看网站 | 超碰97.com | 91av视频在线观看 | 人人插超碰| 成人一级电影在线观看 | 蜜臀久久99精品久久久久久网站 | 五月黄色 | av中文字幕网 | 久久精品视频18 | 婷婷网站天天婷婷网站 | 日日夜操 | 黄色a级片在线观看 | 亚洲精品乱码久久久久久高潮 | 免费国产一区二区视频 | 国产人成免费视频 | 久久久久久久久久久成人 | 天天干亚洲 | 国产日韩欧美在线看 | 国产免码va在线观看免费 | 91色网址 | 国产91成人 | 国产精品亚洲片在线播放 | 免费在线观看日韩视频 | 天天综合91| 国产视频99| 国产资源在线视频 | 日韩电影一区二区在线 | 黄色精品一区二区 | 午夜精品久久久 | 超碰在线个人 | 91av原创| 国产精品毛片久久久久久久 | 成人播放器 | 99精品欧美一区二区三区黑人哦 | 欧美日韩破处 | 日韩aⅴ视频 | 欧美日韩高清在线观看 | 婷婷av在线 | 久久久亚洲影院 | 国产精品久久久久av福利动漫 | 久久激情视频 久久 | 欧美电影在线观看 | 久久伦理电影 | 国产一区二区在线播放 | 天天搞天天干 | 日韩精品免费一区二区 | a资源在线 | 中午字幕在线观看 | 亚洲国产午夜视频 | 色精品视频| 成人午夜影院在线观看 | 日免费视频 | 色婷婷婷 | 99高清视频有精品视频 | 天天激情站 | av在线播放观看 | 久久永久免费视频 | 毛片3 | www.色国产| 网址你懂的在线观看 | 久久综合偷偷噜噜噜色 | 亚洲综合射 | 天天综合入口 | 亚洲va欧美va人人爽春色影视 | 久久久91精品国产一区二区精品 | 成年人免费看av | 亚洲无人区小视频 | 日本三级大片 | 国产精品中文字幕在线观看 | 久久综合国产伦精品免费 | 中文字幕婷婷 | 99热免费在线 | 成人久久18免费网站麻豆 | 999国内精品永久免费视频 | 日韩有码第一页 | 久久五月网 | 免费看黄电影 | 亚洲va欧美va人人爽 | 国产高清第一页 | www.婷婷色 | 日本黄区免费视频观看 | 六月丁香婷婷久久 | 日韩网站免费观看 | 亚洲婷久久 | 激情丁香综合 | 99精品一级欧美片免费播放 | 天天干,天天操,天天射 | 激情综合网色播五月 | 韩日三级在线 | 日日躁天天躁 | 在线观看av的网站 | 免费在线黄 | 中文字幕高清有码 | 国产精品久久久久婷婷 | 综合色综合| 国产亚洲精品久久久久久电影 | 久久99深爱久久99精品 | 最近中文字幕第一页 | 久草网在线| 日躁夜躁狠狠躁2001 | 日韩精品一区二区在线观看 | 丁香花五月 | 精品福利在线 | 91在线看| 日韩高清免费在线观看 | 国产精品久久久久久久久久久不卡 | 欧美色道| 日本在线观看黄色 | 亚洲精品456在线播放 | 亚洲国产精品成人精品 | www..com毛片 | www.久久免费视频 | 中文字幕一区二区三区四区在线视频 | 国产高清免费 | 中文字幕在线视频网站 | 中文字幕在线影视资源 | 成人毛片100免费观看 | 色天天天| avav99| 久操操 | 高清不卡免费视频 | 婷婷丁香五 | 婷婷久久丁香 | 91黄色免费网站 | 96看片 | 午夜12点 | 亚洲一一在线 | 99人成在线观看视频 | 日本久久免费视频 | 成人一级黄色片 | 欧美做受xxx | 天天干天天射天天操 | 99九九热只有国产精品 | 国产精品一区二区三区在线看 | 国产一区二区精品在线 | 人人澡澡人人 | av大全在线看 | 久久国产香蕉视频 | 欧美一二三视频 | 国产a免费 | 天天射网站 | 日本精品一区二区在线观看 | av在线之家电影网站 | 91色亚洲 | 成人在线视频免费观看 | 在线观看日韩一区 | 国产一级在线观看视频 | 国产精品18久久久久白浆 | 欧美aa一级 | 97人人添人澡人人爽超碰动图 | 亚洲午夜精品久久久久久久久久久久 | 超碰在线人人艹 | 激情视频免费在线 | 日韩欧美精品一区 | 婷婷 综合 色 | 99久国产 | 国内精自线一二区永久 | 五月天天av | 欧美日韩亚洲在线观看 | 欧美精品做受xxx性少妇 | 中文字幕高清有码 | 日韩有码网站 | 日日日爽爽爽 | 亚洲精品自拍 | 久久精品亚洲一区二区三区观看模式 | av免费在线免费观看 | 中文av字幕在线观看 | 久久久久久看片 | japanesexxx乱女另类 | 西西www4444大胆视频 | 亚洲另类人人澡 | 久久久久久久久久久高潮一区二区 | 久久这里 | 国产免费嫩草影院 | 国产精品免费在线观看视频 | 黄色av免费 | 日韩免费大片 | 成人免费影院 | 久久99久久99精品免费看小说 | 9999毛片| 人人超碰免费 | 日韩成人欧美 | 午夜狠狠操 | 久久精品99精品国产香蕉 | 中文字幕亚洲不卡 | 日本性生活免费看 | 国产97碰免费视频 | 久久欧美精品 | 毛片网站在线观看 | 在线观看免费91 | 日韩在线视频网站 | a级国产毛片 | 欧美日韩精 | 欧美激情另类文学 | 干av在线 | 日韩精品免费在线 | 成人aⅴ视频 | 精品麻豆入口免费 | 亚洲精品一区二区在线观看 | 99精品欧美一区二区蜜桃免费 | a级黄色片视频 | 国产色婷婷在线 | 91人人人| 国产91精品久久久久久 | 99精品久久久久久久久久综合 | 天天射天天爱天天干 | 日韩av中文在线观看 | 黄在线 | 综合天天 | 九九色网| 亚洲欧美视频在线 | 久久综合狠狠 | 国产一区二区午夜 | 成片视频免费观看 | 综合久久久久久 | 亚洲免费小视频 | 国产亚洲欧美精品久久久久久 | 99精品观看| 亚洲狠狠 | 婷婷视频在线观看 | 欧美精品一区二区三区四区在线 | 国产精品综合久久久久 | 亚洲小视频在线观看 | 免费视频久久久久久久 | 五月激情姐姐 | 日韩在线观看高清 | 在线影视 一区 二区 三区 | 有码中文字幕在线观看 | 国产性天天综合网 | 99精品欧美一区二区蜜桃免费 | 国产韩国精品一区二区三区 | 色99中文字幕 | 国产一区二区三区在线 | 亚洲精品乱码久久久久久蜜桃欧美 | 日本黄色免费在线 | 色九九视频 | 国产精品美女毛片真酒店 | 亚洲 欧美 综合 在线 精品 | 五月天狠狠操 | 亚洲在线视频网站 | 久久久久久网站 | 99久久精品日本一区二区免费 | 自拍超碰在线 | 国产精品9999久久久久仙踪林 | 91传媒在线播放 | 成人av中文字幕在线观看 | 国产精品一区二区三区久久久 | 久久久久99精品国产片 | 天堂网中文在线 | 中文字幕日本特黄aa毛片 | a天堂免费 | 亚洲 欧美 日韩 综合 | www.91成人| 九九视频热 | 麻豆视频免费在线 | 欧美,日韩 | 久久久综合精品 | 成人午夜精品久久久久久久3d | 国产精品美女久久久久久 | 色噜噜日韩精品欧美一区二区 | av电影免费 | 在线观看中文av | 视频精品一区二区三区 | 久久久香蕉视频 | 国产精品色视频 | 1区2区视频| 亚洲片在线观看 | 欧美国产一区在线 | 久久免费播放视频 | 日韩在线无 | 久久艹久久 | 国产黄免费在线观看 | 欧美午夜久久久 | 波多野结衣久久资源 | 国内成人av | 国产综合精品久久 | 国产精品岛国久久久久久久久红粉 | 欧美日韩有码 | 欧美日韩午夜爽爽 | 久久99精品国产99久久 | 日韩精品中文字幕一区二区 | 最新精品国产 | 久草在线免费在线观看 | 色片网站在线观看 | 久久夜夜夜 | 天天色天天射天天综合网 | 免费成人在线观看视频 | 国产一区二区成人 | 国产精品一区二区中文字幕 | 国产精品男女啪啪 | 天天干夜夜 | 欧美福利视频一区 | 国产一区二区三区网站 | 亚洲精品一区二区三区新线路 | 亚洲精品综合一区二区 | 国产精品不卡在线播放 | av一级黄| 久久免费观看视频 | 国产精品视频内 | 免费观看成年人视频 | av免费电影在线观看 | 99热高清| 一级黄色片在线播放 | 国产精品女同一区二区三区久久夜 | 久久久精品 一区二区三区 国产99视频在线观看 | 人人爽人人av | 国产精品18久久久 | 亚洲女同ⅹxx女同tv | 亚洲精品视频网站在线观看 | 国产三级午夜理伦三级 | 婷婷精品国产一区二区三区日韩 | 欧美,日韩 | 久久精品这里热有精品 | 国产又粗又猛又爽又黄的视频先 | 亚洲精品乱码久久久久久按摩 | 色吊丝在线永久观看最新版本 | 日韩免费在线观看视频 | 91爱看片| 婷婷色中文| 麻豆首页 | 在线播放一区 | 91激情在线视频 |