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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

「offer来了」保姆级巩固你的js知识体系(4.0w字)

發布時間:2023/12/4 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 「offer来了」保姆级巩固你的js知识体系(4.0w字) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


「面試專欄」前端面試之JavaScript篇

  • 🧐序言
  • 🥳思維導圖環節
  • 😏一、JS規范
    • 1、說幾條JavaScript的基本規范。
    • 2、對原生JavaScript的了解。
    • 3、說下對JS的了解吧。
    • 4、JS原生拖拽節點
    • 5、談談你對ES6的理解
    • 6、知道ES6的class嘛?
    • 7、說說你對AMD和Commonjs的理解
    • 8、如何理解前端模塊化
    • 9、面向對象編程思想
    • 10、用過 TypeScript 嗎?它的作用是什么?
    • 11、PWA使用過嗎?serviceWorker的使用原理是啥?
  • 😲二、數據類型
    • 1、問:0.1+0.2 === 0.3嗎?為什么?
    • 2、js數據類型有哪些?具體存在哪里?判斷方式是什么?
    • 3、什么是淺拷貝?什么是深拷貝?說明并分別寫出代碼。
      • (1)淺拷貝
      • (2)深拷貝
    • 4、JS整數是怎么表示的?
    • 5、Number的存儲空間是多大?如果后臺發送了一個超過最大數字怎么辦?
    • 6、NAN是什么,用typeof會輸出什么?
    • 7、Symbol有什么用處?
    • 8、null,undefined的區別
    • 9、JS隱式轉換,顯示轉換
    • 10、介紹下js有哪些內置對象
    • 11、js有哪些方法定義對象
    • 12、如何判斷一個對象是不是空對象?
    • 13、手寫題:獲取url參數getUrlParams(url)
    • 14、數組能夠調用的函數有哪些?
    • 15、函數中的arguments是數組嗎?類數組轉數組的方法了解一下?
    • 16、手寫題:如何判斷數組類型?
    • 17、手寫題:sort快速打亂數組
    • 18、手寫題:數組去重操作
    • 19、手寫題:數組扁平化
    • 20、`new` 操作符具體干了什么呢?
    • 21、手寫題:手寫一個new方法
    • 22、js如何實現繼承?
    • 23、JS中的垃圾回收機制
  • 🤐三、作用域、原型鏈、閉包
    • 1、作用域
      • (1)什么是作用域?
      • (2)什么是作用域鏈?
    • 2、原型鏈
      • (1)什么是原型?什么是原型鏈?
      • (2)什么是原型鏈繼承?
      • (3)手寫題:原型鏈之instance原理
    • 3、閉包
      • (1)閉包是什么?
      • (2)js代碼的執行過程
      • (3)一般如何產生閉包?
      • (4)閉包產生的本質
      • (5)閉包的特性
      • (6)閉包的優缺點
      • (7)解決方法
      • (8)let閉包
      • (9)閉包的應用場景
      • (10)手寫題:函數柯里化
      • (11)補充
    • 4、變量對象
      • (1)變量對象
      • (2)活動對象
      • (3)變量提升
  • 😜四、事件
    • 1、事件模型
    • 2、事件是如何實現的?
    • 3、怎么加事件監聽?
    • 4、什么是事件委托?
      • (1)定義
      • (2)原理
      • (3)好處
      • (4)補充
    • 5、說說事件循環 event loop
      • (1)定義
      • (2)常用的宏任務和微任務
      • (3)setTimeout(fn,0)多久才執行,Event loop?
      • (4)補充
  • 🤪五、this問題
    • 1、描述下this(談談對this對象的理解)
    • 2、this綁定的四大規則
      • (1)New綁定
      • (2)顯式綁定
      • (3)隱式綁定
      • (4)默認綁定
    • 3、如果一個構造函數,bind了一個對象,用這個構造函數創建出的實例會繼承這個對象的屬性嗎?為什么?
    • 4、箭頭函數和普通函數有啥區別?箭頭函數能當構造函數嗎?
      • (1)箭頭函數和普通函數定義
      • (2)箭頭函數和普通函數的區別
    • 5、了解this嘛,apply,call,bind具體指什么?
      • (1)三者的區別
      • (2)傳參方式
      • (3)手寫apply、call、bind
  • 😋六、Ajax問題
    • 1、Ajax原理
    • 2、Ajax解決瀏覽器緩存問題
    • 3、js單線程
    • 4、異步編程的實現方式
      • (1)回調函數
      • (2)事件監聽(采用時間驅動模式,取決于某個事件是否發生)
      • (3)發布/訂閱(觀察者模式)
      • (4)Promise 對象
      • (5)Generator 函數
      • (6)async 函數
    • 5、js腳本加載問題,async、defer問題
    • 6、關于window.onload 和 DOMContentLoaded
    • 7、ajax、axios、fetch區別
      • (1)ajax
      • (2)axios
      • (3)fetch
    • 8、手寫題:手寫Ajax函數
    • 9、手寫題:手寫Promise原理
    • 10、手寫題:基于Promise手寫Promise.all
  • 🥰七、手寫題補充
    • 1、性能優化相關
      • (1)手寫節流函數
      • (2)手寫防抖函數
      • (3)圖片懶加載
    • 2、原生API手寫
      • (1)forEach
      • (2)map
      • (3)filter
      • (4)reduce
    • 3、其余手寫題
      • (1)JSONP的實現
      • (2)Object.create
      • (3)Object.assign
      • (4)手寫發布訂閱
  • 😉八、結束語
  • 🐣彩蛋 One More Thing
    • (:pdf內容獲取
    • (:更新地址
    • (:番外篇

🧐序言

大家都知道, js 在前端面試中的占比可以說是非常大了。基本上在每一場面試中,有 40% 以上的題都是 js 的題目。 js 不僅考察一個前端人的基礎能力,更重要的是前端可以說是以 js 為本,所以也很考察我們的代碼能力和邏輯思維。如果說在面試前端中 js 都不過關,那其實還是蠻危險的。

下面的這篇文章中,將講解我整個秋招備試過程的所有題目。其中,有些知識點是一個很大的范圍,但是放在面試系列中整理的話只能是概括性介紹,我將會以鏈接的方式,將我之前寫的文章和其他相關模塊的文章,放在題目后進行標注,方便大家更詳細的了解當下模塊的擴展知識點。

下面開始本文的講解~📚

🥳思維導圖環節

在真正開篇之前,先用一張思維導圖來了解全文的內容。詳情見下圖👇

思維導圖收入囊中了,就該開始來架起 js 的知識體系啦~

😏一、JS規范

1、說幾條JavaScript的基本規范。

  • for-in 循環中的變量應該使用let關鍵字明確限定作用域,從而避免作用域污染。
for(let i in obj){}
  • 比較布爾值/數值時,需用 === / !== 來比較;
  • switch 語句必須帶有 default 分支;
  • 不要使用全局函數;
  • 使用對象字面量替代 new Array 這種形式,以下給出對象字面量的例子。
let person = {name:'張三',age:13,like:['打籃球','打排球'] }

2、對原生JavaScript的了解。

數據類型、運算、對象、 Function 、繼承、閉包、作用域、原型鏈、事件、RegExp 、JSON 、Ajax 、DOM 、BOM 、內存泄漏、異步裝載、模板引擎、前端MVC 、路由、模塊化、Canvas 、ECMAScript 。

3、說下對JS的了解吧。

是基于原型的動態語言,主要特性有this原型原型鏈

JS嚴格意義上來說分為:語言標準部分( ECMAScript )+ 宿主環境部分

語言標準部分

  • 2015年發布 ES6 ,引入諸多特性,使得能夠編寫大型項目成為可能,標準自 2015年 之后以年號作為代號,每年一更。

宿主環境部分

  • 在瀏覽器宿主環境包括 DOM + BOM 等
  • 在 Node ,宿主環境包括一些文件、數據庫、網絡、與操作系統的交互等

4、JS原生拖拽節點

  • 給需要拖拽的節點綁定 mousedown ,mousemove ,mouseup 事件。
  • mousedown 事件觸發后,開始拖拽。
  • mousemove 時,需要通過 event.clientX 和 clientY 獲取拖拽位置,并實時更新位置
  • mouseup 時,拖拽結束。
  • 需要注意瀏覽器邊界值,設置拖拽范圍

5、談談你對ES6的理解

  • 新增模板字符串(為 JavaScript 提供了簡單的字符串插值功能)。
  • 箭頭函數。
  • for-of(用來遍歷數據——例如數組中的值)。
  • arguments 對象可以被不確定的參數和默認參數完美替代。
  • ES6 將 promise 對象納入規范,提供了原生的 promise 對象。
  • 增加了 let 和 const 命令,用來聲明變量。
  • 還有就是引入 module 模塊的概念。

6、知道ES6的class嘛?

ES6 中的 class 是,為這個類的函數對象直接添加方法,而不是加在這個函數對象的原型對象上。

7、說說你對AMD和Commonjs的理解

  • CommonJS 是服務器端模塊的規范,Node.js 采用了這個規范。
  • CommonJS 規范加載模塊是同步的,也就是說,只有加載完成,才能執行后面的操作。AMD 規范則是非同步加載模塊,允許指定回調函數。
  • AMD 推薦的風格通過返回一個對象作為模塊對象。CommonJS 的風格則是通過對 module.exports 或 exports 的屬性賦值來達到暴露模塊對象的目的。

8、如何理解前端模塊化

前端模塊化就是復雜的文件編程中一個個獨立的模塊,比如js文件等等,分成獨立的模塊有利于重用(復用性)和維護(版本迭代),這樣會引來模塊之間相互依賴的問題,所以有了commonJS規范,AMD,CMD規范等等,以及用于js打包(變異等處理)的工具webpack。

9、面向對象編程思想

  • 基本思想是使用對象,類,繼承,封裝等基本概念來進行程序設計;
  • 易維護;
  • 易擴展;
  • 開發工作的重用性、繼承性高,降低重復工作量;
  • 縮短了開發周期。

10、用過 TypeScript 嗎?它的作用是什么?

TypeScript 為 JS 添加類型支持,以及提供最新版的 ES 語法的支持,有利于團隊協作和排錯,開發大型項目。

11、PWA使用過嗎?serviceWorker的使用原理是啥?

漸進式網絡應用(PWA)是谷歌在 2015年底 提出的概念。基本上算是web應用程序,但在外觀和感覺上與 原生app 類似。支持 PWA 的網站可以提供脫機工作推送通知設備硬件訪問等功能。

Service Worker 是瀏覽器在后臺獨立于網頁運行的腳本,它打開了通向不需要網頁或用戶交互的功能的大門。 現在,它們已包括如推送通知和后臺同步等功能。 將來, Service Worker 將會支持如定期同步或地理圍欄等其他功能。

:漸進式網絡應用 Progressive Network Application

😲二、數據類型

1、問:0.1+0.2 === 0.3嗎?為什么?

在正常的數學邏輯思維中, 0.1+0.2=0.3 這個邏輯是正確的,但是在 JavaScript 中 0.1+0.2 !== 0.3 ,這是為什么呢?這個問題也會偶爾被用來當做面試題來考查面試者對 JavaScript 的數值的理解程度。

0.1 + 0.2 == 0.3 // false

在 JS 中,二進制的浮點數 0.1 和 0.2 并不是精確的,所以它們相加的結果并非正好等于 0.3 ,而是一個比較接近 0.3 的數字 0.30000000000000004 ,所以條件判斷結果為 false 。

原因在于在 JS 當中,采用的是 IEEE 754 的雙精度標準,所以計算機內部在存儲數據編碼的時候,0.1在計算機內部不是精確的 0.1 ,而是一個有舍入誤差的 0.1 。當代碼被編譯或解析后, 0.1 已經被四舍五入成一個與之很接近的計算機內部數字,以至于計算還沒開始,一個很小的舍入錯誤就已經產生了。這也就是 0.1 + 0.2 不等于 0.3 的原因。

那如何避免這樣的問題?

最常用的方法就是將浮點數轉化成整數計算,因為整數都是可以精確表示的。

通常就是把計算數字提升10的N次方倍再除以 10 的 N 次方,一般都用 1000 就行了。

(0.1*1000 + 0.2*1000)/1000 == 0.3 //true

2、js數據類型有哪些?具體存在哪里?判斷方式是什么?

(1)js數據類型

js 數據類型包括基本數據類型引用數據類型

(2)具體存放在哪里?

基本數據類型:

基本數據類型,是指 Numer 、 Boolean 、 String 、 null 、 undefined 、 Symbol (ES6新增的)、 BigInt(ES2020) 等值,它們在內存中都是存儲在棧中的,即直接訪問該變量就可以得到存儲在中的對應該變量的值。

若將一個變量的值賦值給另一個變量,則這兩個變量在內存中是獨立的,修改其中任意一個變量的值,不會影響另一個變量。這就是基本數據類型。

引用數據類型:

那引用數據類型呢,是指 Object 、 Array 、 Function 等,他們在內存中是存在于棧和堆當中的,即我們要訪問到引用類型的值時,需要先訪問到該變量在中的地址(指向堆中的值),然后再通過這個地址,訪問到存放在中的數據。這就是引用數據類型。

(3) 常用判斷方式:typeof、instanceof、===

1)typeof:

定義:返回數據類型的字符串表達(小寫)

用法:typeof + 變量

可以判斷

  • undefined/ 數值 / 字符串 / 布爾值 / function (返回 ‘undefined’ / ‘number’ / ‘string’ / ‘boolean’ / ‘function’)

  • null與object 、object與array (null、array、object都會返回 ‘object’ )

<script type="text/javascript">console.log(typeof "Tony"); // 返回 string console.log(typeof 5.01); // 返回 numberconsole.log(typeof false); // 返回 booleanconsole.log(typeof undefined); // 返回 undefinedconsole.log(typeof null); // 返回 objectconsole.log(typeof [1,2,3,4]); // 返回 objectconsole.log(typeof {name:'John', age:34}); // 返回 object </script>

2)instanceof:

定義:判斷對象的具體類型

用法:b instanceof A →表明 b 是否是 A 的實例對象

可以判斷

專門用來判斷對象數據的類型: Object , Array 與 Function

判斷 String , Number , Boolean 這三種類型的數據時,直接賦值為 false ,調用構造函數創建的數據為 true

<script type="text/javascript">let str = new String("hello world") //console.log(str instanceof String); → truestr = "hello world" //console.log(str instanceof String); → falselet num = new Number(44) //console.log(num instanceof Number); → truenum = 44 //console.log(num instanceof Number); → falselet bool = new Boolean(true) //console.log(bool instanceof Boolean); → truebool = true //console.log(bool instanceof Boolean); → false</script> <script type="text/javascript">var items = []; var object = {}; function reflect(value) { return value;} console.log(items instanceof Array); // true console.log(items instanceof Object); // true console.log(object instanceof Object); // true console.log(object instanceof Array); // false console.log(reflect instanceof Function); // true console.log(reflect instanceof Object); // true

3)===:

可以判斷: undefined , null

<script type="text/javascript">let str;console.log(typeof str, str === undefined); //'undefined', truelet str2 = null;console.log(typeof str2, str2 === null); // 'object', true</script>

3、什么是淺拷貝?什么是深拷貝?說明并分別寫出代碼。

(1)淺拷貝

所謂淺拷貝,就是一個變量賦值給另一個變量,其中一個變量的值改變,則兩個變量的值都變了,即對于淺拷貝來說,是數據在拷貝后,新拷貝的對象內部仍然有一部分數據會隨著源對象的變化而變化。

// 分析 function shallowCopy(obj){let copyObj = {};for(let i in obj){copyObj[i] = obj[i];}return copyObj; }// 實例 let a = {name: '張三',age: 19,like: ['打籃球', '唱歌', '跳舞'] }let b = shallowCopy(a);a.name = '李四'; a.like[0] = '打打乒乓球'; console.log(a); console.log(b);

(2)深拷貝

定義:深拷貝 就是,新拷貝的對象內部所有數據都是獨立存在的,不會隨著源對象的改變而改變。

深拷貝有兩種方式:遞歸拷貝和利用JSON函數進行深拷貝。

  • 遞歸拷貝的實現原理是:對變量中的每個元素進行獲取,若遇到基本類型值,直接獲取;若遇到引用類型值,則繼續對該值內部的每個元素進行獲取。
  • JSON深拷貝的實現原理是:將變量的值轉為字符串形式,然后再轉化為對象賦值給新的變量。

局限性:深拷貝的局限性在于,會忽略 undefined ,不能序列化函數,不能解決循環引用的對象。

遞歸拷貝方式實現代碼:

// 分析 function deepCopy(obj){// 判斷是否為引用數據類型if(typeof obj === 'object'){let result = obj.constructor === Array ? [] : {};// 對引用類型繼續進行遍歷,如果遍歷沒有結束的話for(let i in obj){result[i] = typeof obj[i] === 'object' ? deepCopy(obj[i]) : obj[i];}return result;}// 為基本數據類型,直接賦值返回else{return obj;} }// 實例 - 利用遞歸函數做深拷貝 let c = {name:'張三',age:12,like:['打乒乓球','打羽毛球','打太極'] }let d = deepCopy(c);c.name = '李四'; c.like[0] = '打籃球'; console.log(c); console.log(d);

JSON深拷貝實現代碼:

// 實例 - 利用json函數做深拷貝 let e = {name: '張三',age: 19,like:['打羽毛球', '唱歌', '跳舞'] }let f = JSON.parse(JSON.stringify(e));// 注意: JSON函數做深度拷貝時不能拷貝正則,Date,方法函數等e.name = '李四'; e.like[0] = '打乒乓球';// console.log(e); // console.log(f);

這里可以在參考我之前寫過的一篇文章輔助理解👉棧在前端中的應用,順便再了解下深拷貝和淺拷貝!

4、JS整數是怎么表示的?

JS整數通過 Number 類型來表示,遵循 IEEE 754 標準,通過 64位 來表示一個數字,即 1+11+52 (符號位+指數位+小數部分有效位),最大安全數字是 253 - 1,對應 16位 十進制數。

:1位十進制數對應4位二進制數

5、Number的存儲空間是多大?如果后臺發送了一個超過最大數字怎么辦?

Math.pow(2,53),53為有效數字;如果后臺發送一個超過最大數字,會發生截斷,等于 JS 能支持的最大安全數字 253 - 1。

6、NAN是什么,用typeof會輸出什么?

Not a Number,表示非數字。

typeof NaN === 'number'; //true

7、Symbol有什么用處?

  • 可以用來表示一個獨一無二的變量,防止命名沖突
  • 除此之外, Symbol 還可以用來模擬私有屬性。
  • 詳細文章補充👇
  • 原文:面試官:JavaScript 原始數據類型 Symbol 有什么用?
  • 鏈接:https://www.cnblogs.com/lzkwin/p/12666300.html

8、null,undefined的區別

  • undefined 表示不存在這個值。
  • undefined 是一個表示“無”的原始值或者說表示“缺少值”,就是此處應該有一個值,但是還沒有定義。嘗試讀取時就會返回 undefined 。
  • 例如變量被聲明了,但沒有賦值時,就等于 undefined 。
  • null 表示一個對象被定義了,值為“空值”。
  • null 是一個對象(空對象,沒有任何屬性和方法)。
  • 例如作為函數的參數時,表示該函數的參數不是對象。
  • 在驗證 null 時,一定要使用 === ,因為 == 無法區分 null 和 undefined 。

9、JS隱式轉換,顯示轉換

一般非基礎類型進行轉換時會調用valueOf,如果 valueOf 無法返回基本類型值,就會調用toString

(1)字符串和數字

  • “+”操作符,如果有一個為字符串,那么都轉化到字符串然后執行字符串拼接。
  • “-”操作符,轉換為數字,相減(-a, a*1, a/1)都能進行隱式強制類型轉換。
[] + {} 和 {} + []

(2)布爾值到數字

  • 1 + true = 2;
  • 1 + false = 1;

(3)轉換為布爾值

  • for中第二個
  • while
  • if
  • 三元表達式
  • || (邏輯或)和 &&(邏輯與)左邊的操作個數

(4)符號

  • 不能被轉換為數字
  • 能被轉換為布爾值(都是true)
  • 可以被轉換成字符串“Symbol(cool)”

(5)寬松相等和嚴格相等

寬松相等允許進行強制類型轉換,而嚴格相等不允許。

①字符串與數字

  • 轉換為數字然后比較

②其他類型與布爾類型

  • 先把布爾類型轉換為數字,然后繼續進行比較

③對象與非對象

  • 執行對象的 ToPrimitive (對象)然后繼續進行比較

④假值列表

  • undefined
  • null
  • false
  • +0,-0,NaN
  • “”

10、介紹下js有哪些內置對象

  • Object 是 Javascript 中所有對象的父對象;
  • 其他數據封裝類對象:Object 、Array 、Boolean 、Number 和 String;
  • 其他對象:Function 、Arguments 、Math 、Date 、RegExp 、Error。

11、js有哪些方法定義對象

  • 對象字面量:let obj = {} ;
  • 構造函數:let obj = new Object() ;
  • Object.create():let obj = Object.create(object.prototype) ;

12、如何判斷一個對象是不是空對象?

Object.keys(obj).length === 0

13、手寫題:獲取url參數getUrlParams(url)

//封裝函數getUrlParams, 將URL地址的參數解析為對象 function getUrlParams(url){let obj = {};if(url.indexOf('?') === -1){return obj;}let first_res = url.split('?')[1];let second_res = first_res.split('&');for(let i in second_res){third = second_res[i].split('=');obj[third[0]] = third[1];}return obj; }// 測試代碼let URL = 'https://www.sogou.com/web?ie=UTF-8&query=搜索內容&_em=3'; console.log(getUrlParams(URL));

14、數組能夠調用的函數有哪些?

  • push 向數組尾部添加元素
  • pop 刪除并返回數組最后一個元素
  • splice 添加/刪除元素
  • slice 返回選定的元素
  • shift 刪除第一個元素并返回
  • unshift 向數組開頭添加一個或更多元素,并返回新長度
  • sort 對數組元素進行排序
  • find 返回通過測試的數組的第一個元素
  • findIndex
  • map/filter/reduce 等函數式編程方法
  • 原型鏈上的方法:toString/valueOf

15、函數中的arguments是數組嗎?類數組轉數組的方法了解一下?

是類數組,是屬于鴨子類型的范疇,只是長得像數組。

  • … 運算符
  • Array.from
  • Array.prototype.slice.apply(arguments)

16、手寫題:如何判斷數組類型?

// 方法一:instanceof方法 let arr = [1, 2, 3]; console.log(arr instanceof Array);// 方法二:constructor方法 let arr = [1, 2, 3]; console.log(arr.constructor === Array);// 方法三:isArray方法 let arr = [1, 2, 3]; console.log(Array.isArray(arr));// 方法四:Object.prototype方法 let arr = [1, 2, 3]; console.log(Object.prototype.toString.call(arr) === '[object Array]');// 方法五:Array.__proto__方法 let arr = [1, 2, 3]; console.log(arr.__proto__ === Array.prototype);// 方法六:Object.getPrototypeOf方法 let arr = [1, 2, 3]; console.log(Object.getPrototypeOf(arr) === Array.prototype);// 方法七:Array.prototype.isPrototypeOf方法 let arr = [1, 2, 3]; console.log(Array.prototype.isPrototypeOf(arr));

17、手寫題:sort快速打亂數組

let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; arr.sort(() => Math.random() - 0.5); //利用sort,返回結果為大于等于0時被交換位置,小于0時交換位置。

18、手寫題:數組去重操作

/* 數組去重:讓數組所有元素都獨一無二,沒有重復元素 */// 創建一個含有重復元素的數組 let arr = [1, 1, 2, 3, 3, 6, 7, 2, 9, 9]// 第一種方法:利用 Set數據結構 + Array.from() 函數 function removeRepeat1(arr) {return Array.from(new Set(arr)) }// 第二種方法: 利用 Set數據結構 + ...擴展運算符 function removeRepeat2(arr) {return [...new Set(arr)] }// 第三種方法: 利用 indexOf 函數 function removeRepeat3(arr) {let new_arr = []for(let i in arr) {let item = arr[i]if(new_arr.indexOf(item) === -1) {new_arr.push(item)}}return new_arr }// 第四種方法: 利用 includes 函數 function removeRepeat4(arr) {let new_arr = []for(let i in arr) {let item = arr[i]if(!new_arr.includes(item)) {new_arr.push(item)}}return new_arr }// 第五種方法: 利用 filter 函數 function removeRepeat5(arr) {return arr.filter((value, index) => {return arr.indexOf(value) === index}) }// 第六種方法: 利用 Map 數據結構 function removeRepeat6(arr) {let map = new Map()let new_arr = []for(let i in arr) {let item = arr[i]if(!map.has(item)) {map.set(item, true)new_arr.push(item)}}return new_arr }// 測試方法 console.log(removeRepeat1(arr)); console.log(removeRepeat2(arr)); console.log(removeRepeat3(arr)); console.log(removeRepeat4(arr)); console.log(removeRepeat5(arr)); console.log(removeRepeat6(arr));

19、手寫題:數組扁平化

/* 數組扁平化就是將多維數組轉成一維數組 */// 多維數組 let arr = [1, 2, [3, 4, [6, 7]]]// 第一種方法:利用 flat() 函數 function flatArr1(arr) {return arr.flat(Infinity) }// 第二種方法: 正則匹配 function flatArr2(arr) {return JSON.parse('[' + JSON.stringify(arr).replace(/\[|\]/g, '') + ']') }// 第三種方法:利用 reduce() 遍歷所有的元素 function flatArr3(arr) {return arr.reduce((i, j) => {return i.concat(Array.isArray(j)? flatArr3(j) : j)}, []) }// 第四種方法:直接使用遞歸函數 function flatArr4(arr) {let new_arr = [] function innerArr(v) {for(let i in v) {let item = v[i]if(Array.isArray(item)) {innerArr(item)} else {new_arr.push(item)}}}innerArr(arr)return new_arr }// 方法測試 console.log(flatArr1(arr)); console.log(flatArr2(arr)); console.log(flatArr3(arr)); console.log(flatArr4(arr));

20、new 操作符具體干了什么呢?

new 一個對象的過程是:

  • 創建一個空對象
  • 對新對象進行 [prototype] 綁定(即 son. __ proto __ =father.prototype );
  • 新對象和函數調用的 this 會綁定起來;
  • 執行構造函數中的方法;
  • 如果函數沒有返回值則自動返回這個新對象。

21、手寫題:手寫一個new方法

function father(name){this.name = name;this.sayname = function(){console.log(this.name);} }function myNew(ctx, ...args){ //...args為ES6展開符,也可以使用arguments// 先用Oject創建一個空的對象let obj = new Object();// 新對象會執行prototype連接obj.__proto__ = ctx.prototype;// 新對象和函數調用的this綁定起來let res = ctx.call(obj, ...args);// 判斷函數返回值如果是null或者undefined則返回obj,否則就返回resreturn res instanceof Object ? res : obj; }let son = myNew(father, 'Bob'); son.sayname();

22、js如何實現繼承?

  • 原型鏈繼承
  • 盜用構造函數繼承
  • 組合繼承
  • 原型式繼承
  • 繼承式繼承
  • 寄生式組合繼承
  • class的繼承
  • 詳解文章補充👇
  • 原文:一文梳理JavaScript中常見的七大繼承方案
  • 鏈接:https://blog.csdn.net/weixin_44803753/article/details/119280627
  • 碎碎念:對于js的繼承問題來說,要明確幾種繼承之間的關系,以及各自的優缺點,還有手寫每一種繼承。

23、JS中的垃圾回收機制

簡單來說,垃圾回收機制就是,清除無用變量,釋放更多內存,展現更好性能

必要性:由于字符串對象數組沒有固定大小,所有只有當他們的大小已知時,才能對他們進行動態的存儲分配。

JavaScript 程序每次創建字符串、數組或對象時,解釋器都必須分配內存來存儲那個實體。只要像這樣動態地分配了內存,最終都要釋放這些內存以便他們能夠被再用,否則, JavaScript 的解釋器將會消耗完系統中所有可用的內存,造成系統崩潰。

這段話解釋了為什么系統需要垃圾回收, JS 不像 C/C++ ,它有自己的一套垃圾回收機制(GarbageCollection)。

JavaScript 的解釋器可以檢測到何時程序不再使用一個對象了,當他確定了一個對象是無用的時候,他就知道不再需要這個對象,可以把它所占用的內存釋放掉了。

例如:

var a="hello world"; var b="world"; var a=b; //這時,會釋放掉"hello world",釋放內存以便再引用

垃圾回收的方法:標記清除法、引用計數法。

標記清除法

這是最常見的垃圾回收方式,當變量進入環境時,就標記這個變量為”進入環境“,從邏輯上講,永遠不能釋放進入環境的變量所占的內存,只要執行流程進入相應的環境,就可能用到他們。當離開環境時,就標記為“離開環境”。

垃圾回收器在運行的時候會給存儲在內存中的變量都加上標記(所有都加),然后去掉環境變量中的變量,以及被環境變量中的變量所引用的變量(條件性去除標記),刪除所有被標記的變量,刪除的變量無法在環境變量中被訪問所以會被刪除,最后垃圾回收器完成了內存的清除工作,并回收他們所占用的內存。

引用計數法

另一種不太常見的方法就是引用計數法,引用計數法的意思就是每個值沒有引用的次數。當聲明了一個變量,并用一個引用類型的值賦值給該變量,則這個值的引用次數為 1 ;相反的,如果包含了對這個值引用的變量又取得了另外一個值,則原先的引用值引用次數就減 1 ,當這個值的引用次數為 0 的時候,說明沒有辦法再訪問這個值了,因此就把所占的內存給回收進來,這樣垃圾收集器再次運行的時候,就會釋放引用次數為 0 的這些值。

用引用計數法會存在內存泄露,下面來看原因:

function problem() { var objA = new Object();var objB = new Object();objA.someOtherObject = objB;objB.anotherObject = objA; }

在這個例子里面, objA 和 objB 通過各自的屬性相互引用,這樣的話,兩個對象的引用次數都為 2 ,在采用引用計數的策略中,由于函數執行之后,這兩個對象都離開了作用域,函數執行完成之后,因為計數不為 0 ,這樣的相互引用如果大量存在就會導致內存泄露。

特別是在 DOM 對象中,也容易存在這種問題:

var element=document.getElementById(’‘); var myObj=new Object(); myObj.element=element; element.someObject=myObj;

這樣就不會有垃圾回收的過程。

  • 詳解文章補充👇

  • 原文:JavaScript的垃圾回收機制,清除無用變量,釋放多余內存,展現更好的性能

  • 鏈接:https://blog.csdn.net/l_ppp/article/details/106858295

🤐三、作用域、原型鏈、閉包

1、作用域

(1)什么是作用域?

ES5 中只存在兩種作用域:全局作用域函數作用域。在 Javascript 中,我們將作用域定義為一套規則,這套規則用來管理引擎如何在當前作用域以及嵌套子作用域中根據標識符名稱進行變量(變量名和函數名)查找。

作用域,就是當訪問一個變量時,編譯器在執行這段代碼時,會首先從當前的作用域中查找是否有這個標識符,如果沒有找到,就會去父作用域查找,如果父作用域還沒有找到則繼續向上查找,直到全局作用域為止。可理解為該上下文中聲明的變量和聲明的作用范圍,可分為塊級作用域函數作用域

(2)什么是作用域鏈?

  • 作用域鏈可以看成是將變量對象按順序連接起來的一條鏈子。
  • 每個執行環境中的作用域都是不同的。
  • 當我們引用變量時,會順著當前執行環境的作用域鏈,從作用域鏈的開頭開始,依次往上尋找對應的變量,直到找到作用域鏈的尾部,報錯 undefined 。
  • 作用域鏈保證了變量的有序訪問
  • 注意:作用域鏈只能向上訪問,到 window 對象即被終止。

2、原型鏈

(1)什么是原型?什么是原型鏈?

  • 原型和原型鏈:在 Javascript 中,每個對象都會在其內部初始化一個屬性,這個屬性就是 prototype(原型)。當我們訪問一個對象的屬性時,如果這個對象內部不存在這個屬性,那么它就會去 prototype 里找這個屬性,這個 prototype 又會有自己的 prototype ,于是就這樣一直找下去,這樣逐級查找形似一個鏈條,且通過 [[prototype]] 屬性連接,這個連接的過程被稱為原型鏈
  • 關系:instance.constructor.prototype === instance.__ proto __ ;

(2)什么是原型鏈繼承?

原型鏈繼承,是類比類的繼承,即當有兩個構造函數 A 和 B ,將一個構造函數 A 的原型對象,通過其 [[prototype]] 屬性連接另外一個構造函數B的原型對象時,這個過程被稱為原型繼承

(3)手寫題:原型鏈之instance原理

// 判斷A是否為B的實例 const instanceOf = (A, B) =>{// 定義一個指針P指向Alet p = A;// 當P存在時則繼續執行while(p){// 判斷P值是否等于B的prototype對象,是則說明A是B的實例if(p === B.prototype){return true;}// 不斷遍歷A的原型鏈,直到找到B的原型為止p = p.__proto__;}return false; }console.log(instanceOf([], Array));

3、閉包

(1)閉包是什么?

閉包,是指函數內部再嵌套函數,且在嵌套的函數內有權訪問另外一個函數作用域中的變量。

(2)js代碼的執行過程

看完閉包的定義,我們再來了解 js 代碼的整個執行過程,具體如下:

JavaScript 代碼的整個執行過程,分為兩個階段,代碼編譯階段代碼執行階段。編譯階段由編譯器完成,將代碼翻譯成可執行代碼,這個階段作用域規則會確定。執行階段由引擎完成,主要任務是執行可執行代碼,執行上下文在這個階段創建。

(3)一般如何產生閉包?

  • 函數作為返回值被傳遞
  • 函數作為參數被返回

(4)閉包產生的本質

  • 當前環境中存在指向父級作用域的引用

(5)閉包的特性

  • 函數內再嵌套函數
  • 內部函數可以引用外層的參數和變量
  • 參數和變量不會被垃圾回收機制回收

(6)閉包的優缺點

  • 優點:能夠實現封裝和緩存等。
  • 缺點消耗內存;使用不當會內存溢出。

(7)解決方法

  • 在退出函數之前,將不使用的局部變量全部刪除。

(8)let閉包

let會產生臨時性死區,在當前的執行上下文中,會進行變量提升,但是未被初始化,所以在上下文執行階段時,執行代碼如果還沒有執行到變量賦值,就引用此變量會引發報錯,因為此變量未被初始化。

(9)閉包的應用場景

  • 函數柯里化
  • 模塊

(10)手寫題:函數柯里化

1)柯里化是什么

柯里化指的是,有這樣一個函數,它接收函數 A ,并且能返回一個新的函數,這個新的函數能夠處理函數 A 的剩余參數

2)代碼實現

下面給出三種具體的實現方式,代碼如下:

/*** 函數柯里化:將一個接收多個參數的函數變為接收任意參數返回一個函數的形式,便于之后繼續調用,直到最后一次調用,才返回結果值 例子:有一個add函數,用于返回所有參數的和,add(1, 2, 3, 4, 5) 返回的是15現在要將其變為類似 add(1)(2)(3)(4)(5) 或者 add(1)(2, 3, 4)(5) 的形式,并且功能相同*/// 普通的add()函數 function add(){let sum = 0;let args = [...arguments];for(let i in args){sum += args[i];}return sum; }// 第一種add()函數柯里化方式 // 缺點:最后返回的結果是函數類型,但會被隱式轉化為字符串,調用toString()方法function add1(){// 創建數組,用于存放之后接收的所有參數let args = [...arguments];function getArgs(){args.push(...arguments);return getArgs;}getArgs.toString = function(){return args.reduce((a,b) => {return a + b;})}return getArgs; }// 第二種add()函數柯里化方式 // 缺點:需要在最后再自調用一次,即不傳參調用表示已沒有參數了 function add2(){let args = [...arguments];return function(){// 長度為0時直接把所有數進行相加if(arguments.length === 0){return args.reduce((a,b) => {return a + b;})}else{// 定義一個_args為了用來遍歷let _args = [...arguments];// 長度不為0時要進行遍歷for(let i = 0; i < _args.length; i++){args.push(_args[i]);}return arguments.callee;}} }// 第三種add()函數柯里化方式 // 缺點:在剛開始傳參之前,設定總共需要傳入參數的個數 function add3(length){// slice(1)表示從第二個元素開始取值let args = [...arguments].slice(1);return function(){args = args.concat([...arguments]);if(arguments.length < length){return add3.apply(this, [length - arguments.length].concat(args));}else{// 返回想要實現的目的return args.reduce((a,b) => a + b);}} }// 測試代碼 let res = add(1,2,3,4,5); let res1 = add1(1)(2)(3)(4)(5); let res2 = add2(1)(2,3,4)(5)(); let res3 = add3(5);console.log(res); console.log(res1); console.log(res2); console.log(res3(1)(2,3)(4)(5));

(11)補充

詳解文章補充👇

  • 原文:剖析作用域和閉包,淺析函數柯里化
  • 鏈接:https://juejin.cn/post/6970469489938792455

4、變量對象

(1)變量對象

變量對象,是執行上下文中的一部分,可以抽象為一種數據作用域,也可以理解為就是一個簡單的對象,它存儲著該執行上下文中的所有變量函數聲明(不包含函數表達式)。

(2)活動對象

活動對象(AO):當變量對象所處的上下文為 active EC 時,成為活動對象

(3)變量提升

函數在運行的時候,會首先創建執行上下文,然后將執行上下文入棧,當此執行上下文處于棧頂時,開始運行執行上下文。

在創建執行上下文的過程中會做三件事:創建變量對象創建作用域鏈確定 this 指向,其中創建變量對象的過程中,首先會為 arguments 創建一個屬性,值為 arguments ,然后會掃描 function 函數聲明,創建一個同名屬性,值為函數的引用,接著會掃碼 var 變量聲明,創建一個同名屬性,值為 undefined ,這就是變量提升 。

以下給出具體實例:

js (b) //call b console.log(a) //undefined let a = 'Hello World'; function b(){ console.log('call b'); } b(); // call b second function b() { console.log('call b fist'); } function b() { console.log('call b second'); } var b = 'Hello world';

😜四、事件

1、事件模型

W3C中定義事件的發生經歷三個階段:捕獲階段(capturing)、目標階段(targetin)、冒泡階段(bubbling)。

  • 冒泡型事件:當你使用事件冒泡時,子級元素先觸發,父級元素后觸發。
  • 捕獲型事件:當你使用事件捕獲時,父級元素先觸發,子級元素后觸發。
  • DOM 事件流:同時支持兩種事件模型:捕獲型事件和冒泡型事件。

2、事件是如何實現的?

基于發布訂閱模式,就是在瀏覽器加載的時候會讀取事件相關的代碼,但是只有實際等到具體的事件觸發的時候才會執行。

比如點擊按鈕,這是個事件( Event ),而負責處理事件的代碼段通常被稱為事件處理程序(Event Handler),也就是「啟動對話框的顯示」這個動作。

在 Web 端,我們常見的就是 DOM 事件:

  • DOM0 級事件,直接在 html 元素上綁定 on-event ,比如 onclick,取消的話,dom.onclick = null,同一個事件只能有一個處理程序,后面的會覆蓋前面的。
  • DOM2 級事件,通過 addEventListener 注冊事件,通過 removeEventListener 來刪除事件,一個事件可以有多個事件處理程序,按順序執行,捕獲事件和冒泡事件。
  • DOM3級事件,增加了事件類型,比如 UI 事件,焦點事件,鼠標事件。

3、怎么加事件監聽?

通過 onclick 和 addEventListener 來對事件進行監聽。

4、什么是事件委托?

(1)定義

  • 事件代理(Event Delegation),又稱為事件委托,是 Javascript 中常用的綁定事件技巧。
  • “事件代理”即是把原本需要綁定的事件委托給父元素,讓父元素擔當事件監聽的職務。

(2)原理

  • 事件代理的原理是 DOM 元素的事件冒泡。

(3)好處

  • 使用事件代理的好處是可以提高性能
  • 可以大量節省內存占用,減少事件注冊,比如說在 ul 上代理所有 li 的 click 事件。
  • 可以實現當新增子對象時無需再次對其進行綁定。

(4)補充

詳解文章補充(事件)👇

  • 原文:你真的理解事件綁定、事件冒泡和事件委托嗎?
  • 鏈接:https://juejin.cn/post/6971940848439132196

5、說說事件循環 event loop

(1)定義

首先, js 是單線程的,主要的任務是處理用戶的交互,而用戶的交互無非就是響應 DOM 的增刪改,那如何處理事件響應呢?

瀏覽器的各種 Web API 會為異步的代碼提供了一個單獨的運行空間,當異步的代碼運行完畢以后,會將代碼中的回調送入到 Task Queue(任務隊列)中去,等到調用棧空時,再將隊列中的回調函數壓入調用棧中執行,等到棧空以及任務隊列也為空時,調用棧仍然會不斷檢測任務隊列中是否有代碼需要執行,這一過程就是完整的 Event loop 了。

同時需要注意的是,js 引擎在執行過程中有優先級之分, js 引擎在一次事件循環中, 會先執行 js 線程的主任務,然后會去查找是否有微任務 microtask(promise),如果有那就優先執行微任務,如果沒有,再去查找宏任務 macrotask(setTimeout、setInterval) 進行執行。

(2)常用的宏任務和微任務

1)常用的宏任務和微任務有:

名稱舉例(常用)
宏任務script、setTimeout 、setInterval 、setImmediate、I/O、UI Rendering
微任務process.nextTick()、Promise

上訴的 setTimeout 和 setInterval 等都是任務源,真正進入任務隊列的是他們分發的任務。

2)優先級

  • setTimeout = setInterval 一個隊列
  • setTimeout > setImmediate
  • process.nextTick > Promise
for(const macroTask of macroTaskQueue){// 2.再執行宏任務handleMacroTask();for(const microTask of microTaskQueue){// 1.先執行微任務handleMicroTask();} }

(3)setTimeout(fn,0)多久才執行,Event loop?

setTimeout 按照順序放到隊列里面,然后等待函數調用棧清空之后才開始執行,而這些操作進入隊列的順序,則由設定的延遲時間來決定。

(4)補充

詳解文章補充(事件循環)👇

  • 原文1:詳解隊列在前端的應用,深剖JS中的事件循環Eventloop,再了解微任務和宏任務
  • 鏈接1:https://juejin.cn/post/6968750855071727630
  • 原文2:瀏覽器與Node環境下的Event Loop
  • 鏈接2:https://juejin.cn/post/6886992599006380045

🤪五、this問題

1、描述下this(談談對this對象的理解)

  • this ,函數執行的上下文,總是指向函數的直接調用者(而非間接調用者),可以通過 apply , call , bind 改變 this 的指向。
  • 如果有 new 關鍵字,this 指向 new 出來的那個對象。
  • 在事件中,this 指向觸發這個事件的對象,特殊的是,IE 中的 attachEvent 中的 this 總是指向全局對象 window 。
  • 對于匿名函數或者直接調用的函數來說,this 指向全局上下文(瀏覽器為 window ,NodeJS 為 global),剩下的函數調用,那就是誰調用它, this 就指向誰。
  • 對于 es6 的箭頭函數,箭頭函數的指向取決于該箭頭函數聲明的位置,在哪里聲明, this 就指向哪里。

2、this綁定的四大規則

this綁定四大規則遵循以下順序:

New 綁定 > 顯示綁定 > 隱式綁定 > 默認綁定

下面一一介紹四大規則。

(1)New綁定

  • New 綁定: new 調用函數會創建一個全新的對象,并將這個對象綁定到函數調用的 this 。New 綁定時,如果是 new 一個硬綁定函數,那么會用 new 新建的對象替換這個硬綁定 this 。具體實現代碼如下:
function foo(a) { this.a = a; } var bar = new foo(2); console.log(bar.a); //2

(2)顯式綁定

  • 顯示綁定:通過在函數上運行 call 和 apply ,來顯示綁定的 this 。具體實現代碼如下:
function foo() { console.log(this.a); } var obj = { a: 2 }; foo.call(obj); //2
  • 顯示綁定之硬綁定
function foo(something) { console.log(this.a, something); return this.a + something; } function bind(fn, obj) { return function() { return fn.apply(obj, arguments); }; } var obj = { a: 2 } var bar = bind(foo, obj);

(3)隱式綁定

  • 隱式綁定:調用位置是否有上下文對象,或者是否被某個對象擁有或者包含,那么隱式綁定規則會把函數調用中的 this 綁定到這個上下文對象。而且,對象屬性鏈只有上一層或者說最后一層在調用位置中起作用。具體實現代碼如下:
function foo() { console.log(this.a); } var obj = { a: 2, foo: foo, } obj.foo(); // 2

(4)默認綁定

  • 默認綁定:沒有其他修飾( bind 、 apply 、 call ),在非嚴格模式下定義指向全局對象,在嚴格模式下定義指向 undefined 。具體實現代碼如下:
function foo() { console.log(this.a); } var a = 2; foo(); //undefined

3、如果一個構造函數,bind了一個對象,用這個構造函數創建出的實例會繼承這個對象的屬性嗎?為什么?

不會繼承,因為根據 this 綁定四大規則,new 綁定的優先級高于 bind 顯示綁定,通過 new 進行構造函數調用時,會創建一個新對象,這個新對象會代替 bind 的對象綁定,作為此函數的 this,并且在此函數沒有返回對象的情況下,返回這個新建的對象。

4、箭頭函數和普通函數有啥區別?箭頭函數能當構造函數嗎?

(1)箭頭函數和普通函數定義

普通函數通過 function 關鍵字定義, this 無法結合詞法作用域使用,在運行時綁定,只取決于函數的調用方式,在哪里被調用,調用位置。(取決于調用者,和是否獨立運行)。

箭頭函數使用被稱為胖箭頭的操作 => 來定義,箭頭函數不應用普通函數 this 綁定的四種規則,而是根據外層(函數或全局)的作用域來決定 this ,且箭頭函數的綁定無法被修改( new 也不行)。

(2)箭頭函數和普通函數的區別

  • 箭頭函數常用于回調函數中,包括事件處理器定時器
  • 箭頭函數和 var self = this ,都試圖取代傳統的 this 運行機制,將 this 的綁定拉回到詞法作用域
  • 沒有原型、沒有 this 、沒有 super,沒有 arguments ,沒有 new.target 。
  • 不能通過 new 關鍵字調用。
    • 一個函數內部有兩個方法:[[Call]] 和 [[Construct]],在通過 new 進行函數調用時,會執行 [[construct]] 方法,創建一個實例對象,然后再執行這個函數體,將函數的 this 綁定在這個實例對象上。
    • 當直接調用時,執行 [[Call]] 方法,直接執行函數體
    • 箭頭函數沒有 [[Construct]] 方法,不能被用作構造函數調用,當使用 new 進行函數調用時會報錯。
function foo(){return (a) => {console.log(this.a);} }let obj1 = {a: 2 };let obj2 = {a: 3 };let bar1 = foo.call(obj1); let bar2 = bar1.call(obj2);console.log(bar1); // object console.log(bar2); // 2 undefind

5、了解this嘛,apply,call,bind具體指什么?

(1)三者的區別

  • apply 、call 、bind 三者都是函數的方法,都可以改變函數的 this 指向。
  • apply 和 call 都是改變函數 this 指向,并在傳入參數后立即調用執行該函數。
  • bind 是在改變函數 this 指向后,并傳入參數后返回一個新的函數,不會立即調用執行。

(2)傳參方式

apply 傳入的參數是數組形式的,call 傳入的參數是按順序的逐個傳入并以逗號隔開, bind 傳入的參數既可以是數組形式,也可以是按順序逐個傳入具體方式見下方:

apply: Array.prototype.apply(this, [args1, args2]) ES6 之前用來展開數組調用, foo.apply(null, [])ES6 之后使用 ... 操作符;call: Array.prototype.call(this, args1, args2)。bind: Array.prototype.bind(this, args1, args2)Array.prototype.bind(this, [args1, args2])

(3)手寫apply、call、bind

apply:

// 實現apply函數,在函數原型上封裝myApply函數 , 實現和原生apply函數一樣的效果Function.prototype.myApply = function(context){// 存儲要轉移的目標對象_this = context ? Object(context) : window;// 在轉移this的對象上設定一個獨一無二的屬性,并將函數賦值給它let key = Symbol('key');_this[key] = this;// 將數組里存儲的參數拆分開,作為參數調用函數let res = arguments[1] ? _this[key](...arguments[1]) : _this[key]();// 刪除delete _this[key];// 返回函數返回值return res; }// 測試代碼 let obj = {'name': '張三' }function showName(first, second, third){console.log(first, second, third);console.log(this.name); }showName.myApply(obj, [7,8,9]);

call:

// 實現call函數,在函數原型上封裝myCall函數 , 實現和原生call函數一樣的效果Function.prototype.myCall = function(context){// 存儲要轉移的目標對象let _this = context ? Object(context) : window;// 在轉移this的對象上設定一個獨一無二的屬性,并將函數賦值給它let key = Symbol('key');_this[key] = this;// 創建空數組,存儲多個傳入參數let args = [];// 將所有傳入的參數添加到新數組中for(let i =1; i < arguments.length; i++){args.push(arguments[i]);}// 將新數組拆開作為多個參數傳入,并調用函數let res = _this[key](...args);// 刪除delete _this[key];// 返回函數返回值return res; }let obj = {'name': '張三' }function showName(first, second, third){console.log(first, second, third);console.log(this.name); }showName.myCall(obj, 7, 8, 9);

bind:

// 實現Bind函數,在函數原型上封裝myBind函數 , 實現和原生bind函數一樣的效果Function.prototype.myBind = function(context){// 存儲要轉移的目標對象let _this = context ? Object(context) : window;// 在轉移this的對象上設定一個獨一無二的屬性,并將函數賦值給它let key = Symbol('key');_this[key] = this;// 創建函數閉包return function(){// 將所有參數先拆分開,再添加到新數組中,以此來支持多參數傳入以及數組參數傳入的需求let args = [].concat(...arguments);// 調用函數let res = _this[key](...args);// 刪除delete _this[key];// 返回函數返回值return res;} }// 測試代碼 let obj = {'name' : '張三' }function showName(first, second, third){console.log(first, second, third);console.log(this.name); }showName.myBind(obj)([7,8,9]);

😋六、Ajax問題

1、Ajax原理

  • Ajax 的原理簡單來說是在用戶服務器之間加了一個中間層(AJAX引擎),通過 XMLHTTPRequest 對象來向服務器發起異步請求,從服務器獲得數據,然后用 javascript 來操作 DOM 而更新頁面。
  • 使用戶操作與服務器響應異步化。這其中最關鍵的一步就是從服務器獲得請求數據
  • Ajax 的過程只涉及 Javascript 、XMLHttpRequest 和 DOM ,其中 XMLHttpRequest 是 ajax 的核心機制。

2、Ajax解決瀏覽器緩存問題

  • 在 ajax 發送請求前加上 anyAjaxObj.setRequestHeader("If-Modified-Since","0") 。
  • 在 ajax 發送請求前加上 anyAjaxObj.setRequestHeader("Cache-Control","no-cache") 。
  • 在 URL 后面加上一個隨機數: "fresh=" + Math.random() 。
  • 在 URL 后面加上時間搓:"nowtime=" + new Date().getTime() 。

3、js單線程

  • 單線程:只有一個線程,只能做一件事情。

  • 原因:避免 DOM 渲染的沖突。

    • 瀏覽器需要渲染 DOM ;
    • JS 可以修改 DOM 結構;
    • JS 執行的時候,瀏覽器 DOM 渲染會暫停;
    • 兩段 JS 也不能同時執行(都修改 DOM 就沖突了);
    • Webworker 支持多線程,但是不能訪問 DOM。
  • 解決方案:異步。

4、異步編程的實現方式

(1)回調函數

  • 優點:簡單、容易理解
  • 缺點:不利于維護,代碼耦合高

(2)事件監聽(采用時間驅動模式,取決于某個事件是否發生)

  • 優點:容易理解,可以綁定多個事件,每個事件可以指定多個回調函數
  • 缺點:事件驅動型,流程不夠清晰

(3)發布/訂閱(觀察者模式)

  • 類似于事件監聽,但是可以通過“消息中心”,了解現在有多少發布者,多少訂閱者

(4)Promise 對象

  • 優點:可以利用 then 方法,進行鏈式寫法;可以書寫錯誤時的回調函數
  • 缺點:編寫和理解,相對比較難

(5)Generator 函數

  • 優點:函數體內外的數據交換錯誤處理機制
  • 缺點:流程管理不方便

(6)async 函數

  • 優點:內置執行器、更好的語義、更廣的適用性、返回的是 Promise 、結構清晰。
  • 缺點:錯誤處理機制

5、js腳本加載問題,async、defer問題

  • 如果依賴其他腳本和 DOM 結果,使用 defer。
  • 如果與 DOM 和其他腳本依賴不強時,使用 async。
  • 總結:依賴性強用 defer ,依賴性不強用 async 。

6、關于window.onload 和 DOMContentLoaded

window.addEventListener('load', function(){//頁面的全部資源加載完才會執行,包括圖片、視頻等 });document.addEventListener('DOMContentLoaded', function(){//DOM 渲染完即可執行,此時圖片、視頻還可能沒加載完 -> 盡量選擇此方法 });
  • 關于 DOM 和 BOM 操作的補充👇

  • 原文:提升對前端的認知,不得不了解Web API的DOM和BOM

  • 鏈接:https://juejin.cn/post/6971567246174846989

7、ajax、axios、fetch區別

(1)ajax

  • 本身是針對 MVC 的編程,不符合現在前端 MVVM 的浪潮。
  • 基于原生的 XHR 開發, XHR 本身的架構不清晰,已經有了 fetch 的替代方案。
  • JQuery 整個項目太大,單純使用 ajax 卻要引入整個 JQuery 非常的不合理(采取個性化打包的方案又不能享受 CDN 服務)。

(2)axios

  • 從瀏覽器中創建 XMLHttpRequest。
  • 從 node.js 發出 http 請求。
  • 支持 Promise API 。
  • 攔截請求和響應。
  • 轉換請求和響應數據。
  • 取消請求。
  • 自動轉換 JSON 數據。
  • 客戶端支持防止 CSRF/XSRF。

(3)fetch

  • fetch 返回的 promise 不會被標記為 reject ,即使該 http 響應的狀態碼是 404 或 500 。僅當網絡故障或請求被阻止時,才會標記為 reject 。
  • 只對網絡請求報錯,對 400 , 500 都當做成功的請求,需要封裝去處理。
  • 這里對于 cookie 的處理比較特殊,不同瀏覽器對 credentials 的默認值不一樣,也就使得默認情況下 cookie 變的不可控。
  • 本身無自帶 abort ,無法超時控制,可以使用 AbortController 解決取消請求問題。
  • 沒有辦法原生監測請求的進度,而 XHR 可以。

8、手寫題:手寫Ajax函數

/*1. get()方法參數:url(請求的地址)、data(攜帶數據)、callback(成功回調函數)、dataType(返回數據類型)2. post()方法參數:url(請求的地址)、data(攜帶數據)、callback(成功回調函數)、dataType(返回數據類型)3. ajax()方法參數:obj(對象中包含了各種參數),其中有url、data、dataType、async、type */let $ = {createXHR: function() {if(window.XMLHttpRequest) {return new XMLHttpRequest()} else {return new ActiveXObject()} },get: function(url, data, callback, dataType) {let dataType = dataType.toLowerCase()if(data) {url += '?'Object.keys(data).forEach(key => url += `${key}=${data[key]}&`)url = url.slice(0, -1)}let xhr = this.createXHR()xhr.open('get', url)xhr.send()xhr.onreadystatechange = function() {if(xhr.readyState === 4) {if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {let res = dataType === 'json' ? JSON.parse(xhr.responseText) : xhr.responseTextcallback(res, xhr.status, xhr)}}}},post: function(url, data, callback, dataType) {let dataType = dataType.toLowerCase()let xhr = this.createXHR()let str = ''if(data) {Object.keys(data).forEach(key => str += `${key}=${data[key]}&`)str = str.slice(0, -1)}xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')xhr.send(str)xhr.onreadystatechange = function() {if(xhr.readyState === 4) {if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {let res = dataType === 'json' ? JSON.parse(xhr.responseText) : xhr.responseTextcallback(res, xhr.status, xhr)}}}},ajax: function(params) {// 初始化參數let type = params.type ? params.type.toLowerCase() : 'get'let isAsync = params.isAsync ? params.isAsync : 'true'let url = params.urllet data = params.data ? params.data : {}let dataType = params.dataType.toLowerCase()let xhr = this.createXHR()let str = ''// 拼接字符串Object.keys(data).forEach(key => str += `${key}=${data[key]}&`)str = str.slice(0, -1)if(type === 'get') url += `?${str}`;return new Promise((resolve, reject) => {// 創建請求xhr.open(type, url, isAsync)if(type === 'post') {xhr.setRequestHeader('Content-Type', 'application/x-www-form-rulencoded')xhr.send(str)} else {xhr.send()}xhr.onreadystatechange = function() {if(xhr.readyState === 4) {if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {let res = dataType === 'json' ? JSON.parse(xhr.responseText) : xhr.responseTextresolve(res) // 請求成功,返回數據} else {reject(xhr.status) // 請求失敗,返回狀態碼}}}}) } }

9、手寫題:手寫Promise原理

class MyPromise{constructor(fn){this.resolvedCallbacks = [];this.rejectCallbacks = [];// pending 即在等待狀態this.state = 'PENDING';this.value = '';fn(this.resolve.bind(this), this.reject.bind(this));}resolve(value){if(this.state === 'PENDING'){this.state = 'RESOLVED';this.value = value;this.resolvedCallbacks.map(cb => cb(value));}}reject(value){if(this.state === 'PENDING'){this.state = 'REJECTED';this.value = value;this.rejectCallbacks.map(cb => cb(value));}}then(onFulfilled, onRejected){if(this.state === 'PENDING'){this.resolvedCallbacks.map(cb => cb(onFulfilled));this.rejectCallbacks.map(cb => cb(onRejected));}if(this.state === 'RESOLVED'){onFulfilled(this.value);}if(this.state === 'REJECTED'){onRejected(this.value);}} }

10、手寫題:基于Promise手寫Promise.all

/*** promise的三種狀態:* 1.pending:等待狀態,比如正在網絡請求,或定時器沒有到時間;* 2.fulfill:滿足狀態,當我們主動回調了resolve時,就處于該狀態,并且會回調then函數* 3.reject:拒絕狀態,當我們主動回調了reject時,就處于該狀態,并且會回調catch函數*/ /*----------------------------------------------------------------- */ // 函數.then() // 函數then是Promise中的一個方法,它會在Promise處于fulfill狀態時調用觸發 // resolve和reject是默認傳入的函數參數 new Promise((resolve, reject) => {setTimeout(() => {// 在Promise中調用resolve函數,會使Promise變為fulfill狀態// resolve函數可以傳入一個參數,作為then函數的默認傳入參數resolve('成功');}, 1000); }) .then(data => {console.log(data); //結果輸出成功 });/*----------------------------------------------------------------- */ // 函數 .catch() // 函數catch是Promise的一個方法。它會在Promise處于reject狀態時調用觸發 new Promise((resolve, reject) => {setTimeout(() => {// 在Promise調用reject函數,會使Promise變為reject狀態// reject函數可以傳入一個參數,作為catch函數的默認傳入參數reject('失敗');}, 1000) }) .catch(err => {console.log(err); //結果輸出:失敗 })/*----------------------------------------------------------------- */ // 函數.finally() // 函數finally是Promise中的一個方法,它會在Promise的最后觸發,無論Promise處于什么狀態 new Promise((resolve, reject) => {setTimeout(() => {resolve('成功啦!')},1000) }) .then(data => {console.log(data); }) .finally(() => {console.log('Promise結束'); })/* 結果輸出:成功啦!Promise結束 *//*----------------------------------------------------------------- */ // 函數all() // 函數all是Promise中的一個方法,它用于將多個promise實例,包裝成一個新的promise實例 Promise.all([new Promise((resolve, reject) => {setTimeout(() => {resolve('我是第一個異步請求的數據');});}, 1000),new Promise((resolve, reject) => {setTimeout(() => {resolve('我是第二個異步請求的數據');}, 1000);}) ]) .then(results => {console.log(results); // ['我是第一個異步請求的數據', '我是第二個異步請求的數據'] })/*----------------------------------------------------------------- */ // 實際應用 let string1 = 'I am'; new Promise((resolve, reject) => {setTimeout(() => {let string2 = string1 + 'Monday';resolve(string2);}, 1000); }) .then(data => {return new Promise((resolve, reject) => {let string3 = data + 'in CSDN';resolve(string3);}) }) .then(data => {console.log(data); }) .finally(() => {console.log('Promise結束'); })/*輸出結果:I am Monday in CSDN!Promise結束 */

詳解文章補充(Promise)👇

  • 原文:保姆級一步步帶你實現promise的核心功能
  • 鏈接:https://blog.csdn.net/weixin_44803753/article/details/119392804

🥰七、手寫題補充

1、性能優化相關

(1)手寫節流函數

節流:每隔一段時間執行一次,通常用在高頻率觸發的地方,降低頻率。—— 如:鼠標滑動、拖拽

通俗來講,節流是從頻繁觸發執行變為每隔一段時間才執行一次。

//封裝節流函數,實現節流 function throttle(func, delay=500) {let timer = null;let status = false;return function (...args) {if(status) return;status = true;timer = setTimeout(() => {func.apply(this, args)status = false}, delay);} }

(2)手寫防抖函數

防抖:一段時間內連續觸發,不執行,直到超出限定時間執行最后一次。—— 如: input 、 scroll 滾動

通俗來講,防抖是從頻繁觸發執行變為最后一次才執行。

//封裝防抖函數,實現防抖 function denounce(func, delay=500){let timer = null;return function(...args){// 如果有值,清除定時器,之后繼續執行if(timer){clearTimeout(timer);}timer = setTimeout(() => {func.apply(this, args);},delay);} }
  • 詳解文章補充(防抖節流)👇

  • 原文:關于前端性能優化問題,認識網頁加載過程和防抖節流

  • 鏈接:https://juejin.cn/post/6973062729925918756

(3)圖片懶加載

定義:

懶加載突出一個“懶”字,懶就是拖延遲的意思,所以“懶加載”說白了就是延遲加載,比如我們加載一個頁面,這個頁面很長很長,長到我們的瀏覽器可視區域裝不下,那么懶加載就是優先加載可視區域的內容,其他部分等進入了可視區域在加載。

代碼實現:

let img = document.getElementsByTagName('img'); // 獲取img標簽相關的 let num = img.length; // 記錄有多少張圖片 let count = 0; // 計數器,從第一張圖片開始計數lazyload(); // 首次加載別忘了加載圖片function lazyload() {let viewHeight = document.documentElement.clientHeight; // clientHeight 獲取屏幕可視區域的高度let scrollHeight = document.documentElement.scrollTop || document.body.scrollTop; // 滾動條卷去的高度for (let i = 0; i < num; i++) {// 元素現在已經出現在視覺區域中if (img[i].offsetTop < scrollHeight + viewHeight) {// 當src不存在時,跳出本輪循環,繼續下一輪if (img[i].getAttribute('src') !== 'default.jpg') {continue;} else {// 當src屬性存在時,獲取src的值,并將其賦值給imgimg[i].src = img[i].getAttribute('data-src');count++;}}} }
  • 詳細文章補充👇
  • 原文:原生js實現圖片懶加載(lazyLoad)
  • 鏈接:https://zhuanlan.zhihu.com/p/55311726

2、原生API手寫

(1)forEach

用法:

forEach() 方法對數組的每個元素執行一次給定的函數。原生 API 具體解析如下:

arr.forEach(function(currentValue, currentIndex, arr) {}, thisArg)//currentValue 必需。當前元素 //currentIndex 可選。當前元素的索引 //arr 可選。當前元素所屬的數組對象。 //thisArg 可選參數。當執行回調函數時,用作 this 的值。

代碼實現:

Array.prototype.myForEach = function (fn, thisArg) {if (typeof fn !== 'function') {throw new Error('參數必須為函數');}if (!Array.isArray(this)) {throw new Error('只能對數組使用forEach方法');}let arr = this;for (let i = 0; i < arr.length; i++) {fn.call(thisArg, arr[i], i, arr);} }// 測試 let arr = [1, 2, 3, 4, 5]; arr.myForEach((item, index) => {console.log(item, index); });// 測試 thisArg function Counter() {this.sum = 0;this.count = 0; }// 因為 thisArg 參數(this)傳給了forEach(),每次調用時,它都被傳給 callback 函數,作為它的 this 值 Counter.prototype.add = function (array) {array.myForEach(function (entry) {this.sum += entry;++this.count;}, this); }const obj = new Counter(); obj.add([2, 5, 9]);console.log(obj.count); // 3 === (1 + 1 + 1) console.log(obj.sum); // 16 === (2 + 5 + 9)

(2)map

用法:

map 函數會依次處理數組中的每一個元素,并返回一個新的數組,且對原來的數組不會產生影響。

array.map(function(currentValue,index,arr){})

代碼實現:

Array.prototype.myMap = function (arr, mapCallback) {// 檢查參數是否正確if (!Array.isArray(arr) || !Array.length || typeof mapCallback !== 'function') {return [];} else {let result = [];for (let i = 0; len = arr.length; i++) {result.push(mapCallback(arr[i], i, arr));}return result;} }// 測試 let arr = [1, 2, 3, 4, 5]; arr.map((item, index) => {console.log(item * 2); }); // 2, 4, 6, 8, 10

(3)filter

用法:

filter() 方法返回執行結果為true的項組成的數組

arr.filter(function(item, index, arr){}, context)

代碼實現:

Array.prototype.myFilter = function (fn, context) {if (typeof fn !== 'function') {throw new Error(`${fn} is not a function`);}let arr = this;let temp = [];for (let i = 0; i < arr.length; i++) {let result = fn.call(context, arr[i], i, arr);// 判斷條件是否為真if (result) {temp.push(arr[i]);}}return temp; }// 測試 let arr = [1, 2, 3, 4, 5, 'A', 'B', 'C']; console.log(arr.myFilter((item) => typeof item === 'string')); // [ 'A', 'B', 'C' ]

(4)reduce

用法:

  • 參數: 一個回調函數,一個初始化參數 (非必須)
  • 回調函數參數有 4 個值( res : 代表累加值, cur : 目前值, index : 第幾個, arr :調用 reduce 的數組)
  • 整體返回 res 累加值
arr.reduce((res,cur, index, arr) => res+cur, 0)

代碼實現:

/*** * @param {fn} callback res→代表累加值,cur→目前值,index→第幾個,arr→調用reduce的數組* @param {*} initialValue 初始化參數(可選)*/Array.prototype.myReduce = function (cb, initValue) {if (!Array.isArray(this)) {throw new TypeError("not a array");}// 數組為空,并且有初始值,報錯if (this.length === 0 && arguments.length < 2) {throw new TypeError('Reduce of empty array with no initial value');}let arr = this;let res = null;// 判斷有沒有初始值if (arguments.length > 1) {res = initValue;} else {res = arr.splice(0, 1)[0]; //沒有就取第一個值}arr.forEach((item, index) => {res = cb(res, item, index, arr); // cb 每次執行完都會返回一個新的 res值,覆蓋之前的 res})return res; };// 測試結果 let arr = [1, 2, 3, 4]; let result = arr.myReduce((res, cur) => {return res + cur; }) console.log(result); // 10

3、其余手寫題

(1)JSONP的實現

JSONP 的原理:JSONP 的出現使得 script 標簽不受同源策略約束,用來進行跨域請求,優點是兼容性好,缺點就是只能用于 GET 請求

const jsonp = ({ url, params, callbackName }) => {const generateUrl = () => {let dataSrc = '';for (let key in params) {if (params.hasOwnProperty(key)) {dataSrc += `${key}=${params[key]}&`;}}dataSrc += `callback=${callbackName}`;return `${url}?${dataSrc}`;}return new Promise((resolve, reject) => {const scriptElement = document.createElement('script')scriptElement.src = generateUrl()document.body.appendChild(scriptElement)window[callbackName] = data => {resolve(data)document.removeChild(scriptElement)}}) }

(2)Object.create

用法:

Object.creat(object[,propertiesObject]) ,用于創建一個新對象,且這個新對象繼承 object 的屬性。第二個參數 propertyObject 也是對象,是一個可選參數,它旨在為新創建的對象指定屬性對象。該屬性對象可能包含以下值:

屬性說明
configurable表示新創建的對象是否是可配置的,即對象的屬性是否可以被刪除或修改,默認false
enumerable對象屬性是否可枚舉的,即是否可以枚舉,默認false
writable對象是否可寫,是否或以為對象添加新屬性,默認false
get對象getter函數,默認undefined
set對象setter函數,默認undefined

代碼實現:

/*** * @param {*} proto 新創建對象的原型對象* @param {*} propertyObject 要定義其可枚舉屬性或修改的屬性描述符的對象* @returns */ Object.create2 = function (proto, propertyObject = undefined) {if (typeof proto !== 'object' && typeof proto !== 'function') {throw new TypeError('Object prototype may only be an Object or null.')}// 創建一個空的構造函數 Ffunction F() { }// F 原型指向 protoF.prototype = proto// 創建 F 的實例const obj = new F()// propertiesObject有值則調用 Object.definePropertiesif (propertyObject != undefined) {Object.defineProperties(obj, propertyObject)}if (proto === null) {// 創建一個沒有原型對象的對象,Object.create(null)obj.__proto__ = null}// 返回 這個 objreturn obj }const person = {name: 'monday',printIntroduction: function() {console.log(`My name is ${this.name}, and my age is ${this.age}`);} };const me = Object.create2(person);me.name = 'Tuesday'; me.age = 18; me.printIntroduction();

(3)Object.assign

用法:

Object.assign() 方法用于將所有可枚舉屬性的值從一個或多個源對象分配到目標對象。它將返回目標對象。

代碼實現:

Object.assign2 = function (target, ...source) {if (target == null) {throw new TypeError('Cannot convert undefined or null to object');}let res = Object(target);source.forEach(function (obj) {if (obj != null) {for (let key in obj) {if (obj.hasOwnProperty(key)) {res[key] = obj[key];}}}})return res; }const target = { a: 1, b: 2 }; const source = { b: 4, c: 5 };const returnedTarget = Object.assign2(target, source);console.log(target); // { a: 1, b: 4, c: 5 }console.log(returnedTarget); // { a: 1, b: 4, c: 5 }

(4)手寫發布訂閱

代碼實現:

class Subject {constructor(name) {this.name = name; // 被觀察者的名字this.message = '今天是晴天'; // 存放一個值this.observers = []; // 存放所有觀察者}on(observer) {this.observers.push(observer);}triggle(data) {this.message = data;this.observers.forEach(item => item.update(data));} }class Observer {constructor(name) {this.name = name;}update(newDate) {console.log(`我是觀察者${this.name}: ${newDate}`);} }// 測試代碼 let subject = new Subject('message');let o1 = new Observer('小紅'); let o2 = new Observer('小明');subject.on(o1); // 我是觀察者小紅: 明天會下雨 subject.on(o2); // 我是觀察者小明: 明天會下雨subject.triggle('明天會下雨');

😉八、結束語

以上收錄周一整個秋招備試過程中 JavaScript 的所有面試題,上面的面試題可能還不夠全,如有想要補充的內容也歡迎聯系 vx:MondayLaboratory ,希望能夠讓文章內容更加盡善盡美,造福更多備試的小伙伴~

最后,預祝各位看到這篇文章的小伙伴們,都能夠斬獲到自己心儀的 offer ~

🐣彩蛋 One More Thing

(:pdf內容獲取

👉 微信關注公眾號 星期一研究室 ,回復關鍵字 js面試pdf 即可獲取相關 pdf 內容~

👉 回復 面試大全pdf 可獲取全專欄內容!

(:更新地址

👉 offer來了面試專欄

(:番外篇

  • 如果您覺得這篇文章有幫助到您的的話不妨點贊支持一下喲~~😉
  • 以上就是本文的全部內容!我們下期見!👋👋👋

總結

以上是生活随笔為你收集整理的「offer来了」保姆级巩固你的js知识体系(4.0w字)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

色香蕉在线视频 | 狠狠操.com| 99热这里只有精品国产首页 | 欧美日韩国产免费视频 | 久久不射网站 | 久久爱资源网 | 免费在线观看视频a | 黄色aaa级片| 四虎国产精品成人免费4hu | 国产69精品久久99不卡的观看体验 | 亚洲成av人影院 | 黄色三级网站在线观看 | 日本黄色免费电影网站 | 国产午夜精品av一区二区 | 免费看黄20分钟 | 久久在视频 | 在线观看的av网站 | 国产午夜精品一区二区三区 | 最新av在线免费观看 | 中文字幕 国产 一区 | 三级黄色大片在线观看 | 99婷婷狠狠成为人免费视频 | 日韩在线观看视频免费 | 在线看不卡av | 黄色av免费看 | 国产裸体视频网站 | a特级毛片| 高清国产在线一区 | 九九九热精品免费视频观看网站 | 国产成人在线观看 | 九九视频精品免费 | 精品国产伦一区二区三区 | 99一区二区三区 | 亚洲一区黄色 | 日韩乱码中文字幕 | 91秒拍国产福利一区 | 国产九色91 | 超碰成人免费电影 | 国产精品久久久久久久免费观看 | 蜜臀久久99精品久久久久久网站 | 亚洲日本va在线观看 | 一区二区三区免费播放 | 久久久综合香蕉尹人综合网 | 黄色a三级 | 欧美二区三区91 | 九九爱免费视频在线观看 | 97视频在线看 | 久久久精品一区二区三区 | 午夜黄网 | 国产精品日韩在线观看 | 国产精品成久久久久三级 | 日韩高清免费在线观看 | 在线观看免费高清视频大全追剧 | 在线免费91 | 欧美成年网站 | 国产福利精品视频 | 免费人成在线观看网站 | 狠狠色丁香婷婷综合欧美 | 亚洲日韩中文字幕在线播放 | 日韩电影在线观看一区二区 | 97在线观看免费高清完整版在线观看 | 国产精品18videosex性欧美 | 黄色精品免费 | sesese图片| 521色香蕉网站在线观看 | 久草免费在线观看 | 日韩一级黄色大片 | 免费在线观看日韩 | 最近中文字幕大全 | 久草电影在线 | 99国内精品久久久久久久 | 国产中文字幕国产 | 91视频高清免费 | 欧美精品在线一区 | 国产91小视频 | 91在线视频播放 | 国产精品高潮呻吟久久av无 | 免费的黄色的网站 | 国产xvideos免费视频播放 | 一区二区三区视频 | 欧美孕妇与黑人孕交 | 爱色婷婷 | 精品国产成人av在线免 | 婷婷在线视频观看 | 免费a级大片 | 丝袜足交在线 | 午夜精品影院 | 亚洲成人av电影 | 国产一区二区久久久 | 日韩日韩日韩日韩 | 色大片免费看 | 色狠狠操 | 天天干天天操天天射 | 国产高清黄色 | 四虎5151久久欧美毛片 | 欧美激情精品 | 综合天天色| 开心激情综合网 | 超碰国产人人 | 免费三及片 | 国产在线毛片 | 97天堂| va视频在线 | 欧美午夜理伦三级在线观看 | 成人h视频 | 亚洲区精品视频 | 久久久久久久久久久久亚洲 | 国产中文视 | 97人人超碰在线 | 欧美最新大片在线看 | 中文字幕成人在线 | 中文字幕亚洲精品日韩 | 丁香六月在线观看 | 99久久精品免费 | 亚洲成av人片在线观看无 | 国产精品欧美久久久久三级 | www91在线 | 丁香婷婷基地 | 麻豆精品国产传媒 | 97色资源 | 久久精品99国产精品亚洲最刺激 | 亚洲理论电影网 | 日韩在线观看三区 | 成人国产精品一区二区 | 午夜精品中文字幕 | 亚洲精品在线观看免费 | 草久久av| 色婷婷综合久久久中文字幕 | 91亚洲视频在线观看 | 久久免费视频在线观看6 | 日韩在线观看一区二区三区 | 天堂av一区二区 | 天天色综合三 | 欧美日韩一区二区在线观看 | www亚洲精品 | 看片一区二区三区 | 亚洲永久在线 | 久久午夜国产 | 国产精品电影一区二区 | 久草热视频 | 久色免费视频 | 欧美超碰在线 | 欧美一区免费在线观看 | 婷婷丁香在线 | 久久黄色免费视频 | 久久精品视频国产 | 一区在线观看视频 | 亚洲国产三级在线观看 | 精品a级片 | 国产一级视频 | 国产免费一区二区三区最新6 | 91中文字幕一区 | 黄色片网站 | 中文字幕在线播出 | 亚洲 成人 一区 | 国产日韩欧美在线一区 | 国产精品一区二区三区四 | 精品国产一二区 | 日日夜夜精品视频天天综合网 | 激情婷婷色 | 国产区免费在线 | 国产精品久久99综合免费观看尤物 | 国产视频一级 | 国产精久久 | 一区二区精品在线观看 | 久久99视频 | 国产精品一区二 | 色综合久久五月天 | 99麻豆久久久国产精品免费 | 一级做a爱片性色毛片www | 亚洲 中文 欧美 日韩vr 在线 | 欧美在线一二 | 91视频在线免费下载 | 国产日韩精品一区二区三区在线 | 天天视频亚洲 | 国产午夜精品在线 | 亚洲国产无 | 精品久久91 | 狠狠色丁香婷婷综合久小说久 | 91大神精品视频在线观看 | 色诱亚洲精品久久久久久 | 天天干夜夜 | 精品国产一区二区三区久久 | 99精品电影 | 免费a网 | 99热超碰 | 久久美女精品 | 久久99免费| 91精品国产三级a在线观看 | www.狠狠插.com| 国产手机视频 | 亚洲精品免费在线 | 天堂网一区二区三区 | 欧美永久视频 | 在线观看不卡的av | 亚洲欧美日韩在线看 | 亚洲欧美日韩精品一区二区 | 天天射天天射天天 | 国产精品视频资源 | av片子在线观看 | 欧美日韩另类在线 | 在线视频国产区 | 97免费 | 久草久视频 | 日韩一级片观看 | 日日操夜夜操狠狠操 | 一区二区免费不卡在线 | 亚洲精品国产麻豆 | 色偷偷av男人天堂 | 日韩在线视频精品 | www亚洲一区 | 国产精品一区二区三区视频免费 | 91传媒在线播放 | 揉bbb玩bbb少妇bbb | 国产一区高清在线观看 | 粉嫩av一区二区三区四区五区 | 国产精品福利无圣光在线一区 | 亚洲 欧洲 国产 日本 综合 | 亚洲永久精品国产 | 9999在线视频 | 粉嫩av一区二区三区入口 | 久久久91精品国产一区二区精品 | 国产理论免费 | 成人久久国产 | 精品国产乱码久久久久久1区2匹 | 婷婷在线观看视频 | 久久免费视频5 | 色婷婷97 | 久久99精品久久久久久秒播蜜臀 | 午夜精品久久久久久久99 | 国产又黄又爽无遮挡 | av免费观看网站 | 午夜精品久久久久99热app | 亚洲1区 在线 | 天天操狠狠操网站 | 黄色不卡av | 99精品国产aⅴ | 国产一级电影在线 | 成年人国产在线观看 | www五月天婷婷 | 少妇自拍av | 久久久久国产免费免费 | 精品一区在线 | 色婷婷丁香 | 久久午夜国产 | 日韩久久久久久久久 | 色夜影院 | 麻豆传媒一区二区 | 久久一区二区三区国产精品 | 探花视频免费观看高清视频 | 亚洲黄色免费 | 国产视频精品免费播放 | 久久在线播放 | av网站在线观看免费 | 六月色丁香 | 狠狠狠色丁香婷婷综合久久五月 | 国产99久久久久 | 亚洲精品在线免费看 | 日本韩国精品在线 | av黄色大片 | 日韩精品专区在线影院重磅 | 香蕉网站在线观看 | 色欧美88888久久久久久影院 | 国内免费久久久久久久久久久 | 激情综合五月天 | 国产91aaa | 97精品国产手机 | 中文字幕a∨在线乱码免费看 | 日本视频精品 | 国产精品毛片一区二区 | 国内外成人在线视频 | 中文字幕免费一区二区 | 免费在线电影网址大全 | 国产一区二区在线免费观看 | 超碰人人在线观看 | 中文字幕一区二区三区乱码不卡 | 伊人网站 | 日本性高潮视频 | 色香蕉视频 | 免费视频91 | 中文字幕亚洲欧美日韩 | 激情欧美一区二区免费视频 | 亚洲精品乱码久久久久久蜜桃不爽 | 久草9视频 | a成人v在线 | 免费日韩一区二区三区 | 男女免费av | 天天舔天天搞 | 视频在线观看国产 | 国产精品久久久久婷婷二区次 | 91热爆视频 | 色一级片 | 在线 欧美 日韩 | 亚洲成a人片综合在线 | 亚洲精品中文字幕视频 | 91精品久久久久久综合五月天 | 久久精品久久精品久久精品 | 福利av影院 | 美腿丝袜一区二区三区 | 日韩欧美高清 | 国产一区二区网址 | 欧美专区日韩专区 | 久久久久久久免费 | a天堂中文在线 | 韩国一区二区在线观看 | 久热色超碰 | 久久人人爽人人片 | 久久成人精品视频 | 国产亚洲综合性久久久影院 | 日韩精品一区不卡 | 日本三级久久久 | 在线免费亚洲 | 中文字幕 成人 | 91看片在线免费观看 | 久久精品精品电影网 | 欧美性视频网站 | 国产探花视频在线播放 | 一级一片免费看 | 成年人在线观看网站 | www久| 丰满少妇久久久 | 欧美在线观看禁18 | 国产麻豆成人传媒免费观看 | www日韩在线观看 | 精品99在线视频 | 国产成人91 | 亚洲日本一区二区在线 | 国内精品视频免费 | 久久成视频| 成人免费看片网址 | 国产精品久久久一区二区三区网站 | 丁香婷婷色综合亚洲电影 | 在线观看视频一区二区 | 日日夜夜天天久久 | 国产视频日韩视频欧美视频 | 日韩中文字幕视频在线 | 国产无遮挡猛进猛出免费软件 | 免费观看一区二区三区视频 | 在线视频亚洲 | 麻花传媒mv免费观看 | 国产成人精品av | 免费一级片在线观看 | 午夜12点 | 久久精品国产亚洲aⅴ | 成人毛片100免费观看 | 女人18毛片a级毛片一区二区 | 久草a视频| 黄色毛片视频免费 | 91久久精品一区 | 99精品视频在线观看播放 | 美女国内精品自产拍在线播放 | a级免费观看 | 91精品国产一区二区在线观看 | 亚洲理论片在线观看 | 日韩激情片在线观看 | 免费久久99精品国产婷婷六月 | 久久视频在线 | 美女一区网站 | 久久久久视| 国产一区在线视频播放 | 欧美日韩一区二区在线 | 日本精品一区二区 | 黄色小网站在线观看 | 日韩肉感妇bbwbbwbbw | 中文字幕成人网 | 久久久国产99久久国产一 | 欧美男女爱爱视频 | 国产高清 不卡 | 91在线影院 | 综合久久婷婷 | 超碰人人干人人 | 蜜臀av在线一区二区三区 | 成人动漫视频在线 | 国产精品一级在线 | 国产一级二级三级在线观看 | 天天射天天添 | 日韩免费观看高清 | 久久艹欧美 | 久久精品在线视频 | 开心色停停 | 久草视频手机在线 | 天天人人 | 99精品国产99久久久久久97 | 日韩午夜av| 超碰免费成人 | 成人午夜网 | 婷婷丁香视频 | 亚洲精品成人在线 | 午夜色站 | 草莓视频在线观看免费观看 | 视频一区视频二区在线观看 | 欧美日韩视频精品 | 欧美午夜精品久久久久久孕妇 | 中文字幕人成人 | 西西4444www大胆艺术 | 日韩欧美在线综合网 | 狠狠色狠狠色 | 国产99久久 | 亚洲黄网站| 国产精品成人一区二区三区吃奶 | 精品久久久久久一区二区里番 | 久久99国产精品 | 成年人免费在线看 | 欧美成人亚洲 | 欧美日韩国产一区二区三区在线观看 | 麻豆视频在线 | 精品国产午夜 | 美女视频黄是免费的 | 在线观看av的网站 | 亚洲五月六月 | 黄色一及电影 | a级免费观看| 日韩视频一二三区 | 日韩一区二区三免费高清在线观看 | 久久久久亚洲精品 | 日韩综合在线观看 | 国内小视频 | 77国产精品 | 天天操天天操天天爽 | 欧美另类69 | 久久久亚洲成人 | 成人在线观看av | 九热在线 | 精品国产久 | 99视频一区| 亚洲精品自在在线观看 | 黄色.com| 丰满少妇对白在线偷拍 | 91大神精品视频 | 国产黄大片在线观看 | 欧美久久久一区二区三区 | 久久久综合香蕉尹人综合网 | 亚洲精品色视频 | 日韩电影在线观看一区二区 | 福利网址在线观看 | 三级av在线播放 | 成年免费在线视频 | 久久9999久久免费精品国产 | 99热99 | 中文字幕一区二区三 | 国产在线精品一区二区 | 懂色av一区二区在线播放 | 国产伦精品一区二区三区免费 | 黄色美女免费网站 | 久久一级片 | 久久久久免费精品视频 | 久久久免费毛片 | 日韩av片无码一区二区不卡电影 | 美女福利视频在线 | 色综合亚洲精品激情狠狠 | 欧美成人在线免费观看 | 天天操夜夜干 | 免费观看十分钟 | 在线免费观看麻豆 | 色综合天 | 国产精品四虎 | 日韩电影在线观看一区 | 爱色av.com| www.在线观看av | 精品在线观看一区二区三区 | 日日综合 | 日韩精品视频免费专区在线播放 | 久久久久久高潮国产精品视 | 亚洲国产福利视频 | 久久久 精品 | 亚洲在线精品视频 | 99中文字幕视频 | 亚洲欧洲精品久久 | 国产99久久久国产精品成人免费 | 蜜桃视频在线视频 | 亚洲最大的av网站 | 人人爽人人片 | 99久久精品一区二区成人 | av丝袜美腿 | 狠狠久久婷婷 | 97福利社| 国产成人在线看 | 蜜桃麻豆www久久囤产精品 | 91精品专区 | 一区二区三区免费在线播放 | 天天操夜夜逼 | 最近免费在线观看 | 欧美精品色| 国产一区二区手机在线观看 | 国产在线视频在线观看 | 成人一级在线观看 | 亚洲三级在线免费观看 | 大胆欧美gogo免费视频一二区 | 天天色天天操天天爽 | 久久久精品电影 | 91亚洲精品在线观看 | 欧美成人按摩 | 天天操天天干天天玩 | 91视频高清免费 | 欧美视频不卡 | 欧美日韩在线免费视频 | 婷婷日韩| 激情丁香月 | 久久久久欠精品国产毛片国产毛生 | 亚洲精品白浆高清久久久久久 | 日韩在线一级 | 国产日本亚洲 | 国内精品视频一区二区三区八戒 | 欧美a级一区二区 | 亚洲午夜电影网 | 97在线视| 黄色软件视频大全免费下载 | 亚洲第一中文字幕 | 欧美va电影| 四虎影视8848aamm | 日韩av免费在线看 | 亚洲成人在线免费 | 99九九视频 | 天天干天天干天天干 | 91在线看黄| 国产精品视频久久久 | 伊人天天| 四虎最新域名 | 99在线播放 | 2023亚洲精品国偷拍自产在线 | 国产一区免费在线 | 天天插日日操 | 黄色av三级在线 | 婷婷开心久久网 | 69xxxx欧美 | av韩国在线 | 成人免费视频网址 | a级国产片| 高清国产在线一区 | 成人动漫一区二区 | 亚洲国产午夜 | 91精品国自产在线观看欧美 | 麻豆视频免费入口 | 中国一级片在线 | 色偷偷88欧美精品久久久 | 啪啪免费试看 | 亚洲精品1234区 | 亚洲精品中文字幕在线 | 人人澡人人爽欧一区 | 中文字幕在线视频一区二区 | 日韩理论片在线 | 免费日韩 | 国产精品免费小视频 | 国产在线观看午夜 | 久草热久草视频 | 99视频在线| 99久在线精品99re8热视频 | 91亚洲精品久久久中文字幕 | 亚洲一区二区三区毛片 | 免费视频 三区 | 国产97碰免费视频 | 91av在线免费播放 | av大片免费看 | 成人sm另类专区 | 中文字幕中文字幕在线中文字幕三区 | 91看成人 | 日韩在线视频免费播放 | 在线观看中文字幕第一页 | 欧美日韩一区二区免费在线观看 | 国产精品久久在线 | 成人h动漫在线看 | 在线日韩一区 | 免费网站黄色 | 午夜精选视频 | 久久精品视频4 | 99热国产在线中文 | 欧美一区二视频在线免费观看 | 精品国产精品国产偷麻豆 | 黄色毛片视频免费观看中文 | 久久久久久久久久久久久久电影 | 国产精品黑丝在线观看 | 外国av网 | 国产69精品久久久久久 | 日韩免费观看高清 | 91丨精品丨蝌蚪丨白丝jk | 亚洲综合在线五月 | 天天看天天操 | 久久久免费少妇 | 日韩免费视频在线观看 | 手机av电影在线观看 | 中文在线字幕观看电影 | 久久综合九色综合久久久精品综合 | 福利一区二区在线 | 欧美一级性生活片 | 黄色片视频在线观看 | 99tvdz@gmail.com | 97在线精品国自产拍中文 | 99精品欧美一区二区蜜桃免费 | 亚洲视频 视频在线 | 中文在线免费一区三区 | 国产精品av电影 | 日本精品视频一区二区 | 五月婷婷综合久久 | 中文字幕在线观看免费高清电影 | 精品国产乱码久久 | 欧美精品亚洲精品 | 亚洲视频aaa | 99热精品在线观看 | 又黄又爽又湿又无遮挡的在线视频 | 国产乱码精品一区二区三区介绍 | 日韩一级成人av | 在线免费成人 | 182午夜在线观看 | 欧美日韩中文在线视频 | 91福利试看 | 精品国产一区二区三区久久久 | 国产小视频免费观看 | 久久久黄色 | 亚洲精品高清一区二区三区四区 | 99视频在线精品国自产拍免费观看 | 天天干天天射天天操 | 在线亚洲成人 | 久久久伊人网 | 一区三区视频在线观看 | 99精品在线视频播放 | 人人插人人费 | 国产精品 中文在线 | 国产精品久久久久久久久久ktv | av三区在线| www.久热 | 久久夜色精品国产欧美一区麻豆 | 午夜精品久久 | 99久久精品国产观看 | 日韩精品一区二区免费 | 国产精品自产拍在线观看蜜 | www.com在线观看| 成人欧美一区二区三区黑人麻豆 | 国产亚洲永久域名 | 人人爽人人爽人人爽学生一级 | 亚洲va欧洲va国产va不卡 | 日一日操一操 | 久久精品99国产精品酒店日本 | 国产在线播放观看 | 天堂黄色片 | 国产成人777777 | 日本精品一二区 | 狠狠干干 | 国产成人在线精品 | 国产免费专区 | 中文不卡视频在线 | 中文字幕一区二区三区视频 | 亚洲人在线7777777精品 | 国产一级片在线播放 | 中文在线www | 日韩视频一区二区在线观看 | 日韩伦理一区二区三区av在线 | 超碰在线国产 | 精品高清美女精品国产区 | 久久免费av电影 | 久久免费99精品久久久久久 | 国产在线观看高清视频 | 一区二区三区在线电影 | 国产小视频免费在线网址 | 2021av在线 | 一级黄色在线视频 | 免费av网站在线看 | av黄色国产 | 探花视频在线观看免费 | 一区二区三区 中文字幕 | 九九热久久免费视频 | 天堂在线视频免费观看 | 国产一区视频导航 | 精品亚洲免费视频 | 五月开心激情网 | 粉嫩av一区二区三区免费 | 激情欧美xxxx | 在线观看黄色av | 亚州国产精品视频 | 日本字幕网 | 午夜免费久久看 | 亚洲欧美在线观看视频 | 午夜精品av | 欧美激情第八页 | 亚洲成av人片在线观看无 | 九九热av | 黄色网在线播放 | 久久视频| 小草av在线播放 | 天堂在线一区 | 日本高清中文字幕有码在线 | 久久久久久久久久久久av | 国产v亚洲v| 91伊人影院| 国产最新视频在线 | www色网站| 在线观看亚洲专区 | 色婷婷影视 | 日本三级久久 | 国产不卡av在线 | 久久一视频 | 韩国精品视频在线观看 | 国产夫妻自拍av | 99免费观看视频 | 国产精品成人品 | 色香天天 | 国产美女免费观看 | 国产美女久久 | 在线性视频日韩欧美 | 免费福利在线播放 | 粉嫩av一区二区三区四区 | 99亚洲精品视频 | 日本公妇在线观看 | 色99中文字幕 | 岛国av在线免费 | 亚洲高清不卡av | 日韩理论在线观看 | 美女精品久久久 | 蜜臀aⅴ国产精品久久久国产 | 免费a现在观看 | 国内成人精品2018免费看 | 国产视频2 | 二区在线播放 | 精品视频9999 | 欧美国产不卡 | 久久久久久久久国产 | 久久精品国产亚洲aⅴ | 久久精品视 | 一区二区伦理 | av色影院| 日韩成人中文字幕 | 九九九热精品免费视频观看网站 | 99久久久国产精品免费99 | av电影免费观看 | 国产成人精品日本亚洲999 | 中文字幕美女免费在线 | 成人毛片100免费观看 | 一区二区三区精品久久久 | 久久午夜电影 | 久久乱码卡一卡2卡三卡四 五月婷婷久 | 日韩在线中文字幕视频 | 91精品国自产在线偷拍蜜桃 | 久久dvd| 免费看片黄色 | 亚洲精品免费观看 | 伊人五月天婷婷 | 精品96久久久久久中文字幕无 | 国产亚洲91| 波多野结衣在线播放视频 | 亚洲视频一区二区三区在线观看 | 国产精品一区电影 | 色婷av| 国产91国语对白在线 | 久久免费视频3 | 欧美一区二区伦理片 | 日韩国产欧美在线视频 | 日日日日日 | 国产中年夫妇高潮精品视频 | 91视频下载| 国产精品第10页 | 亚洲精品在线视频观看 | 成人一级影视 | 国产一级二级在线 | 麻豆一区二区 | 国产欧美精品一区aⅴ影院 99视频国产精品免费观看 | 玖玖国产精品视频 | 色婷婷综合久久久中文字幕 | 操久久免费视频 | 久在线 | 亚洲精品白浆高清久久久久久 | 五月天六月婷 | 日日久视频 | 在线免费黄色av | 91插插插免费视频 | 国产精品免费观看国产网曝瓜 | 国产高清在线视频 | a午夜在线 | 久久久久电影网站 | 久久伦理电影 | 国产一区二区三区免费观看视频 | 成人久久18免费网站麻豆 | 精品国模一区二区三区 | 日韩精品在线观看视频 | 亚洲小视频在线观看 | 五月天久久久久久 | 四虎国产免费 | 99热.com | 香蕉成人在线视频 | 激情开心站 | 手机av在线不卡 | 亚洲在线成人精品 | 日韩在线观看一区二区 | 免费看国产曰批40分钟 | av不卡免费看| 精品久久久久久一区二区里番 | 啪嗒啪嗒免费观看完整版 | 99精品国产免费久久 | 四虎成人精品永久免费av九九 | 国产999精品久久久久久绿帽 | 国产 欧美 在线 | 国产精品免费在线 | 色a资源在线 | 国产福利91精品 | 欧美在线18 | 精品国产中文字幕 | 国产精品剧情在线亚洲 | 中文字幕a∨在线乱码免费看 | av色影院 | 91在线免费播放 | 2024av在线播放| 国产.精品.日韩.另类.中文.在线.播放 | 看国产黄色片 | 久草免费在线观看 | 免费观看成年人视频 | 日免费视频 | 一区二精品 | 一级性av | 九九免费观看视频 | 日韩天天综合 | 亚洲精品视频网站在线观看 | 人人爽久久久噜噜噜电影 | 日日干 天天干 | 日韩av成人在线观看 | 成人免费视频免费观看 | www.夜夜操.com| 国产色综合天天综合网 | 久久免费在线视频 | 91在线视频一区 | 国产精品毛片一区视频播不卡 | 精品毛片久久久久久 | 国产成人精品女人久久久 | 色狠狠综合 | 97视频资源 | 国产精品嫩草55av | 播五月综合 | 国产一区二区电影在线观看 | 人人看人人爱 | 免费在线观看一区二区三区 | 在线不卡视频 | 国产一级视频 | 国产一卡二卡在线 | 97电影院网| 久久av免费| 久操视频在线播放 | 免费在线精品视频 | 又爽又黄又无遮挡网站动态图 | 国产在线精品一区 | 亚洲精品动漫在线 | av福利第一导航 | 色资源在线观看 | www.日日日.com | 欧美日韩一区二区三区不卡 | 亚洲国产精品小视频 | 日产乱码一二三区别在线 | 探花视频免费在线观看 | 在线观看亚洲a | 97视频在线| 中文字幕在线播放日韩 | 久草在线手机视频 | 国产综合久久 | 中文字幕乱在线伦视频中文字幕乱码在线 | 免费日韩视频 | 午夜影视剧场 | 亚洲视频每日更新 | 91精品视频在线免费观看 | 国产精品系列在线 | 久艹在线免费观看 | 国产精品一区二区三区电影 | 亚洲高清免费在线 | 久久免费的精品国产v∧ | 亚洲精品男人的天堂 | 九九热免费观看 | 手机av电影在线 | 一区二区三区在线观看免费视频 | 国产精品人成电影在线观看 | 深夜成人av | 99热99re6国产在线播放 | 91精品视频免费观看 | 黄色影院在线免费观看 | 国产精品电影在线 | 久久久久福利视频 | 欧美国产视频在线 | 免费日韩 精品中文字幕视频在线 | 亚洲综合欧美日韩狠狠色 | www日日 | 久久狠狠一本精品综合网 | 国内精品视频免费 | 欧美久久久久久久久久久久 | 国产免费一区二区三区最新6 | 成人国产网站 | 久久一二区| 看黄色.com| 久久好看 | 免费av网址大全 | 欧美在线视频第一页 | 丁香五婷 | 99精品视频免费 | 成人a毛片 | 久久夜色精品国产欧美乱极品 | 色综合久久88色综合天天 | 欧美精品一区二区三区一线天视频 | 网站在线观看日韩 | 国产成人av | 丁香婷婷深情五月亚洲 | 日韩美一区二区三区 | 日韩久久久久久久久 | 爱情影院aqdy鲁丝片二区 | 日韩精品91偷拍在线观看 | 国产一区二区精品在线 | 国产精品理论片在线观看 | 啪啪av在线 | 亚洲精品高清视频在线观看 | 美腿丝袜一区二区三区 | 国产97在线视频 | 奇米影视在线99精品 | 六月色| 色综合久久悠悠 | 天天天操天天天干 | 三级大片网站 | 久久精品视频2 | 亚洲成人动漫在线观看 | 国产福利在线免费观看 | 在线性视频日韩欧美 | 欧美 日韩 国产 中文字幕 | 婷婷 中文字幕 | 久久国产精品视频 | 天堂在线一区二区三区 | 伊人久在线 | 中文字幕第一 | 日韩欧美精品在线观看视频 | 国产精品久久久久久一二三四五 | 久久久久久久久久免费 | 中文字幕一区二区三区四区在线视频 | 午夜.dj高清免费观看视频 | 久久久久久电影 | 欧美色插 | 久热爱 | 久久99国产精品视频 | av网站在线观看播放 | 日韩在线资源 | 国产色 在线| 伊人久久精品久久亚洲一区 | 日韩专区在线播放 | 在线播放国产一区二区三区 | 一级a性色生活片久久毛片波多野 | 日韩欧美成| 国产精品欧美久久久久无广告 | 西西www4444大胆在线 | 精品中文字幕在线播放 | 黄色av影院 | 婷婷丁香七月 | 色婷婷久久一区二区 | 欧美日韩精品免费观看 | 手机在线欧美 | 六月天综合网 | 中文字幕 第二区 | 成人一区在线观看 | 久青草电影 | 亚洲经典中文字幕 | 久久er99热精品一区二区三区 | 色综合久久综合中文综合网 | 亚洲欧美va| 在线亚洲午夜片av大片 | 日韩欧美精品一区二区三区经典 | 国产精品不卡 | 久草网视频 | 99热这里有精品 | 波多野结衣一区三区 | 97成人精品区在线播放 | 国产糖心vlog在线观看 | 午夜电影中文字幕 | 性色av一区二区三区在线观看 | 久久亚洲精品国产亚洲老地址 | www.人人干| 久久久久久久久久久久久久免费看 | 国产精品久久久久久久久久不蜜月 | 天天操 夜夜操 | 毛片网站观看 | 韩国一区二区在线观看 | 草久在线播放 | 婷婷日韩| 在线观看国产永久免费视频 | 免费热情视频 | 成人午夜在线观看 | 中文字幕在线免费播放 | 亚洲欧美视频网站 | 五月婷婷综 | 在线电影日韩 | 99视频在线免费播放 | 色吊丝在线永久观看最新版本 | 亚洲国产高清视频 | 精品久久久久久亚洲 | 欧美亚洲成人免费 | 午夜久久久久 | av千婊在线免费观看 | 91福利区一区二区三区 | 曰韩精品 | 中文字幕中文字幕在线一区 | 精品国产乱码久久久久久1区二区 | 五月天综合在线 | 五月婷婷六月丁香激情 | 国产一区在线免费观看 | 国产视频在线观看一区 | 久久久久免费精品国产小说色大师 | 国产精品久久99综合免费观看尤物 | 麻豆精品传媒视频 | 久久视频一区 | 日本狠狠色 | 久久久久电影 |