<p id="m2nkj"><option id="m2nkj"><big id="m2nkj"></big></option></p>
    <strong id="m2nkj"></strong>
    <ruby id="m2nkj"></ruby>

    <var id="m2nkj"></var>
  • 一篇文章一次性搞定JavaScript 從 ES6 到 ES12的基礎(chǔ)框架知識

    共 16007字,需瀏覽 33分鐘

     ·

    2022-11-01 20:15

    英文 | https://medium.com/@bluetch/javascript-es6-es7-es8-es9-es10-es11-and-es12-519d8be7d48c


    前言
    Javascript 是前端三劍客技術(shù)最重要的技能之一。每個學(xué)習(xí)前端的人,這個JavaScript技術(shù)是必須要學(xué)的。隨著技術(shù)不斷更新迭代,所以現(xiàn)在有一些新的知識來支持我們?nèi)W(xué)習(xí) ES6 ~ ES12。
    一、ECMAScript簡介
    ECMA 規(guī)范由各方組成,包括瀏覽器供應(yīng)商,他們會開會推動 JavaScript 提案。
    二、ES6 (ES2015)
    1.Class
    JavaScript 是一種使用原型鏈的語言。
    早期,類似OO的概念是通過原型鏈做出來的,相當(dāng)復(fù)雜。Class 終于在 ES6 中推出。
    class Animal {   constructor(name, color) {     this.name = name;     this.color = color;   }   // This is a property on the prototype chain   toString() {     console.log('name:' + this.name + ', color:' + this.color);
    } }
    var animal = new Animal('myDog', 'yellow'); // instantiateanimal.toString(); // name: myDog, color: yellow
    console.log(animal.hasOwnProperty('name')); //trueconsole.log(animal.hasOwnProperty('toString')); // falseconsole.log(animal.__proto__.hasOwnProperty('toString')); // true
    class Cat extends Animal { constructor(action) { // The subclass must call the super function in the constructor, otherwise an error will be reported when new comes out // If the constructor was not written originally, the default constructor with super will be automatically generated super('cat','white'); this.action = action; } toString() { console.log(super.toString()); }}
    var cat = new Cat('catch')cat.toString();
    console.log(cat instanceof Cat); // trueconsole.log(cat instanceof Animal); // true

    2. 模塊

    每個模塊都有自己的命名空間以避免沖突,使用導(dǎo)入和導(dǎo)出來導(dǎo)入和導(dǎo)出。

    基本上將 .js 文件視為模塊。

    3.箭頭函數(shù)

    () => {…},是函數(shù)的縮寫。最重要的是,他可以確保這始終指向自己

    不再寫 var self = this、var that = this 等等!

    const add = (a, b) => { return a + b};
    const res = add(1, 2); // 3
    // If the syntax is simple, `{}` and `return` can be omitted. It will look neaterconst minus = (a, b) => a - b;const res1 = minus(3, 1); // 2

    4.函數(shù)參數(shù)默認值

    如果函數(shù)不傳遞參數(shù),則使用默認值,更簡潔的寫法。

    function example(height = 50, width = 40) {      const newH = height * 10;     const newW = width * 10;     return newH + newW;}
    example(); // 900 (50*10 + 40*10)

    5. 模板字面量

    過去,長字符串的組合是通過 + 號來連接的。

    它的可讀性很差,使用模板字符串,它更容易閱讀。

    const firstName = 'Ken';const lastName = 'Huang';// not use template literalconst name = 'Hello, My name is' + firstName + ', ' + lastName;// use template literalconst nameWithLiteralString = `Hello, My name is ${firstName}, ${lastName}`;

    6.解構(gòu)賦值

    允許 JavaScript 輕松地從數(shù)組和對象中獲取內(nèi)容。

    const arr = [1, 2, 3, 4, 5];const [one, two, three] = arr;console.log(one); // 1console.log(two); // 2console.log(three); // 3
    // To skip certain valuesconst [first,,,,last] = arr;console.log(first); // 1console.log(last); // 5
    // Objects can also be destructurized and assignedconst student = { name: 'Ken Huang', age: 38, city: 'Taipei'};const {name, age, city} = student;console.log(name); // "Ken Huang"console.log(age); // "38"console.log(city); // "Taipei"

    7.擴展運算符

    它是用三點(...)表示,Array是可以擴展的,如果是Object,會按照key-value進行擴展。

    const stuendts = ['Angel', 'Ryan']; const people = ['Sara', ...stuendts, 'Kelly', 'Eason'];conslog.log(people); // ["Sara", "Angel", "Ryan", "Kelly", "Eason"]

    8. 對象屬性簡寫

    如果構(gòu)成對象的字段名稱與前面段落中的變量相同,則可以省略該值,看起來更流線型。

    const name = 'Angel', age = 18, city = 'ChangHwa';
    // Before ES6, we must write like thisconst customer = { name: name, age: age, city: city} // // {name: 'Angel', age: 18, city: 'ChangHwa'}
    // After ES6, we can do itconst newCustomer = { name, age, city} // {name: '小明Angel, age: 18, city: 'ChangHwa'}

    9. Promise

    Promise 是一種異步(非同步)寫法的解決方案,比原來的回調(diào)寫法更加優(yōu)雅。

    早期是開源社區(qū)的套件,后來被納入語言標(biāo)準(zhǔn)。

    早期回調(diào) hell……

    使用 Promise 后,回調(diào) hell 扁平化

    const waitSecond = new Promise((resolve, reject) => {    setTimeout(resolve, 1000);});waitSecond.then( () => {    console.log('hello World after 1 second.');     // output this line after 1 second    return waitSecond;}).then( () => {    console.log('Hell World after 2 sceond.');    // output this line after 2second})

    并且ES8(ES2017)發(fā)布了更完美的async,await,直接讓異步寫得像同步一樣。

    缺點是當(dāng)思路落到復(fù)雜的業(yè)務(wù)邏輯上時,有時會錯過await,在運行時發(fā)現(xiàn)錯誤。

    10. let, const 替換 var

    let:通用變量,可以被覆蓋

    const:一旦聲明,其內(nèi)容不可修改。因為數(shù)組和對象都是指標(biāo),所以它們的內(nèi)容可以增加或減少, 但不改變其指標(biāo).

    早期,JavaScript的var作用域是全局的。

    也就是說,變量是在使用后聲明的,執(zhí)行的時候會自動提到頂層,后面會賦值。

    更容易受到污染。

    console.log(a); // undefinedvar a = 10;

    使用 let 或 const

    console.log(a); // ReferenceError: Cannot access 'a' before initializationlet a = 10;

    三、ES7 (ES2016)

    1.Array.prototype.includes()

    用于判斷數(shù)組是否包含指定值,如果是,則返回true;否則,返回假。

    和之前indexOf的用法一樣,可以認為是返回一個布爾值,語義上更加清晰。

    const arr = [1, 2, 3, 4, 5];// Check if there is the number 3 in the arrayarr.include(3); // true
    if (arr.include(3)) { ... }// ... Equivalent to the previous writing of indexOfarr.indexOf(3); // 2 (return its array position)// If you want to write it in the if, you must add `> -1`, which is not as clear as the include in ES7 in terms of semanticsif (arr.indexOf(3) > -1) { ... }

    2. 冪運算符

    console.log(2**10); // 1024// equal toconsole.log(Math.pow(2, 10)); // 1024

    四、ES8 (ES2017)

    1.async, await

    異步函數(shù)是使用 async 關(guān)鍵字聲明的函數(shù),并且允許在其中使用 await 關(guān)鍵字。async 和 await 關(guān)鍵字使異步的、基于 Promise 的行為能夠以更簡潔的方式編寫,避免了顯式配置 Promise 鏈的需要。

    async test() {    try {        const result = await otherAsyncFunction();        console.log(result); // output result    } catch(e) {        console.log(e); // Can catch errors if otherAsyncFunction() throws an error    }}

    2. Object.values()

    返回對象自身屬性的所有值,不包括繼承的值。

    const exampleObj = {a: 1, b: 2, c: 3, d:4};console.log(Object.value(exampleObj)); // [1, 2, 3, 4];
    // To do the same thing before, use the following notation. much verboseconst values = Object.keys(exampleObj).map(key => exampleObj[key]);

    3. Object.entries()

    返回可枚舉鍵,即傳入對象本身的值。

    const exampleObj = {a: 1, b: 2, c: 3, d:4};console.log(Object.entries(exampleObj)); // [["a", 1], ["b", 2], ["c", 3], ["d", 4]];
    // Usually used with forfor (const [key, value] of Object.entries(exampleObj)) { console.log(`key: ${key}, value: ${value}`);}// key: a, value: 1// key: b, value: 2// key: c, value: 3// key: d, value: 4

    4. 字符串 padStart() & padEnd()

    你可以在字符串的開頭或結(jié)尾添加其他內(nèi)容,并將其填充到指定的長度。

    過去,這些功能通常是通過通用的輔助工具包(如 lodash)引入的,并將它們放在一起。

    本機語法現(xiàn)在直接提供:

    String.padStart(fillingLength, FillingContent);// 如果要填充的內(nèi)容過多,超過了“填充長度”,會從最左邊填充到長度上限,超出的部分會被截斷

    最常用的情況應(yīng)該是金額,填寫指定長度,不足加0。

    // padStart'100'.padStart(5, 0); // 00100// If the content to be padded exceeds the "padding length". Then fill in from the left to the upper limit of the length'100'.padStart(5, '987'); // 98100
    // padEnd'100'.padEnd(5, 9); // 10099// If the content to be padded exceeds the "padding length". Then fill in from the right to the upper limit of the length'100'.padStart(5, '987'); // 10098

    5.尾隨逗號

    允許在函數(shù)參數(shù)列表末尾使用逗號

    [    "foo",+   "baz",    "bar",-   "baz",  ]

    6. Object.getOwnPropertyDescriptors()

    獲取你自己的描述符,一般的開發(fā)業(yè)務(wù)需求通常不會用到。

    const exampleObj = {a: 1, b: 2, c: 3, d:4};Object.getOwnPropertyDescriptors(exampleObj);// {a: {…}, b: {…}, c: {…}, d: {…}}// a: {value: 1, writable: true, enumerable: true, configurable: true}// b: {value: 2, writable: true, enumerable: true, configurable: true}// c: {value: 3, writable: true, enumerable: true, configurable: true}// d: {value: 4, writable: true, enumerable: true, configurable: true}// __proto__: Object

    7. 共享數(shù)組緩沖區(qū)

    SharedArrayBuffer 是一個固定長度的原始二進制數(shù)據(jù)緩沖區(qū),類似于 ArrayBuffer。

    可用于在共享內(nèi)存上創(chuàng)建數(shù)據(jù)。與 ArrayBuffer 不同,SharedArrayBuffer 不能分離。

    /** * @param length size,unit byte * @returns {SharedArrayBuffer} the default value is 0。 */const sab = new SharedArrayBuffer(length);

    8. Atomics object

    Atomics 對象,它提供了一組靜態(tài)方法來對 SharedArrayBuffer 執(zhí)行原子操作。

    原子的所有屬性和函數(shù)都是靜態(tài)的,就像數(shù)學(xué)一樣,出不來新的。

    如果一個多線程同時在同一個位置讀寫數(shù)據(jù),原子操作保證了正在操作的數(shù)據(jù)如預(yù)期的那樣:即在上一個子操作結(jié)束后執(zhí)行下一個,操作不中斷。

    可以說是針對Node.Js中多線程Server的開發(fā)而加強的功能,在前端開發(fā)中使用的機會相當(dāng)?shù)汀?/span>

    chrome 已經(jīng)提供了支持

    五、ES9 (ES2018)

    1.循環(huán)等待

    在異步函數(shù)中,有時需要在同步 for 循環(huán)中使用異步(非同步)函數(shù)。

    async function process(array) {  for (const i of array) {    await doSomething(i);  }}
    async function process(array) { array.forEach(async i => { await doSomething(i); });}

    上面的代碼不會像預(yù)期的那樣輸出期望的結(jié)果。

    for循環(huán)本身還是同步的,會在循環(huán)中的異步函數(shù)完成之前執(zhí)行整個for循環(huán),然后將里面的異步函數(shù)逐一執(zhí)行。

    ES9 增加了異步迭代器,允許 await 與 for 循環(huán)一起使用,逐步執(zhí)行異步操作。

    async function process(array) {  for await (const i of array) {    doSomething(i);  }}

    2.promise.finally()

    無論是成功(.then())還是失敗(.catch()),Promise 后面都會執(zhí)行的部分。

    function process() {  process1()  .then(process2)  .then(process3)  .catch(err => {    console.log(err);  })  .finally(() => {    console.log(`it must execut no matter success or fail`);  });}

    3. Rest, Spread

    在 ES2015 中,Rest 不定長度參數(shù)…,可以轉(zhuǎn)換成數(shù)組傳入。

    function restParams(p1, p2, ...p3) {    console.log(p1); // 1    console.log(p2); // 2    console.log(p3); // [3, 4, 5]}restParams(1, 2, 3, 4, 5);

    而傳播則與其他相反,將數(shù)組轉(zhuǎn)換為單獨的參數(shù)。

    例如,Math.max() 返回傳入數(shù)字中的最大值。

    const values = [19, 90, -2, 6, 25];console.log( Math.max(...values) ); // 90

    它還提供了對Objects進行解構(gòu)賦值的功能。

    const myObject = {  a: 1,  b: 2,  c: 3};const { a, ...r } = myObject;// a = 1// r = { b: 2, c: 3 }
    // Can also be used in function input parametersfunction restObjectInParam({ a, ...r }) { console.log(a); // 1 console.log(r); // {b: 2, c: 3}}
    restObjectInParam({ a: 1, b: 2, c: 3});

    4. 正則表達式組

    RegExp 可以返回匹配的數(shù)據(jù)包

    const regExpDate = /([0-9]{4})-([0-9]{2})-([0-9]{2})/;const match      = regExpDate.exec('2020-06-25');const year       = match[1]; // 2020const month      = match[2]; // 06const day        = match[3]; // 25

    5.正則表達式前瞻否定

    TBD

    6.正則表達式 dotAll

    . 表示匹配除輸入以外的任何符號,添加這些標(biāo)志后,允許匹配輸入。

    /hello.world/.test('hello\nworld');  // false/hello.world/s.test('hello\nworld'); // true

    六、ES10 (ES2019)

    1.更友好的 JSON.stringify

    如果輸入是 Unicode 但超出范圍,則 JSON.stringify 最初會返回格式錯誤的 Unicode 字符串。

    現(xiàn)在是第 3 階段的提案,使其成為有效的 Unicode 并以 UTF-8 呈現(xiàn)

    2. Array.prototype.flat() & Array.prototype.flatMap()

    展平陣列

    const arr1 = [1, 2, [3, 4]];arr1.flat(); // [1, 2, 3, 4]
    const arr2 = [1, 2, [3, 4, [5, 6]]];arr2.flat(); // [1, 2, 3, 4, [5, 6]]// Pass in a number in flat, representing the flattening deptharr2.flat(2); // [1, 2, 3, 4, 5, 6]

    flatMap(),相當(dāng)于reduce with concat,可以展平一個維度

    let arr = ["早安", "", "今天天氣不錯"]
    arr.map(s => s.split(""))// [["早", "安"], [""], ["今", "天", "天", "氣", "不", "錯"]]
    arr.flatMap(s => s.split(''));// ["早", "安", "", "今", "天", "天", "氣", "不", "錯"]

    3. String.prototype.trimStart() & String.prototype.trimEnd()

    trimStart() 方法從字符串的開頭刪除空格,trimLeft() 是此方法的別名。

    const greeting = ‘ Hello world! ‘;console.log(greeting);// expected output: “ Hello world! “;console.log(greeting.trimStart());// expected output: “Hello world! “;

    trimEnd() 方法從字符串末尾刪除空格,trimRight() 是此方法的別名。

    const greeting = '   Hello world!   ';console.log(greeting);// expected output: "   Hello world!   ";console.log(greeting.trimEnd());// expected output: "   Hello world!";

    4. Object.fromEntries()

    Object.fromEntries() 方法將鍵值對列表轉(zhuǎn)換為對象。

    const entries = new Map([  ['foo', 'bar'],  ['baz', 42]]);const obj = Object.fromEntries(entries);console.log(obj);// expected output: Object { foo: "bar", baz: 42 }

    5. String.prototype.matchAll

    matchAll() 方法返回將字符串與正則表達式匹配的所有結(jié)果的迭代器,包括捕獲組。

    const regexp = /t(e)(st(\d?))/g;const str = 'test1test2';const array = [...str.matchAll(regexp)];console.log(array[0]);// expected output: Array ["test1", "e", "st1", "1"]console.log(array[1]);// expected output: Array ["test2", "e", "st2", "2"]

    6.fixed catch 綁定

    在使用catch之前,不管有用與否,一定要傳入一個eparameter來表示接收到的錯誤。

    如果現(xiàn)在不用,可以省略。

    try {...} catch(e) {...}
    // If e is not used, it can be omittedtry {...} catch {...}

    7. BigInt(新數(shù)字類型)

    BigInt 值,有時也稱為 BigInt,是一個 bigint 原語,通過將 n 附加到整數(shù)文字的末尾,或通過調(diào)用 BigInt() 函數(shù)(沒有 new 運算符)并給它一個整數(shù)值或字符串來創(chuàng)建 價值。

    ES5:String, Number, Boolean, Null, Undefined

    ES6 新增:Symbol,到ES6就一共有6 種類型

    ES10 新增:BigInt,就達到 7 種類型

    const theBiggestInt = 9007199254740991n;
    const alsoHuge = BigInt(9007199254740991);// ? 9007199254740991n
    const hugeString = BigInt("9007199254740991");// ? 9007199254740991n
    const hugeHex = BigInt("0x1fffffffffffff");// ? 9007199254740991n
    const hugeBin = BigInt("0b11111111111111111111111111111111111111111111111111111");// ? 9007199254740991n

    七、ES11 (ES2020)

    1.Promise.allSettled()

    Promise.allSettled() 方法返回一個在所有給定的 Promise 都已實現(xiàn)或拒絕后實現(xiàn)的 Promise,并帶有一組對象,每個對象都描述了每個 Promise 的結(jié)果。

    它通常用于當(dāng)你有多個不依賴于彼此成功完成的異步任務(wù),或者你總是想知道每個 Promise 的結(jié)果時。

    相比之下,Promise.all() 返回的 Promise 可能更合適,如果任務(wù)相互依賴/如果你想立即拒絕其中任何一個拒絕。

    const promise1 = Promise.resolve(3);const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));const promises = [promise1, promise2];Promise.allSettled(promises).  then((results) => results.forEach((result) => console.log(result.status)));// expected output:// "fulfilled"// "rejected"

    2. 可選鏈接?

    在開發(fā)中,很容易遇到先判斷數(shù)據(jù)是否存在,判斷是否寫入。

    const isUserExist = user && user.info;if (isUserExist) {     username = user.info.name; }

    如果返回的數(shù)據(jù)為null或者用戶對象下沒有.intounder,則會拋出Uncaught TypeError: Cannot read property...。

    導(dǎo)致程序無法繼續(xù)執(zhí)行

    使用 ?,語法更簡單

    const username = user?.info?.name;

    如果存在,獲取name的值,如果不存在,賦值undefined

    與 || 一起使用,只需一行!

    const username = user?.name || 'guest';

    3. Nullish 合并運算符 ??

    在JavaScript中,遇到0、null、undefuded時會自動轉(zhuǎn)為false。

    但有時0其實是一個正常的值,只能容錯undefined和null

    /** * user = { *    level: 0 * } */const level = user.level || 'no level'; // output as no level instead of expected 0// to fix it, it must use if simple processingconst level = user.level !== undefined && user.level !== null ? user.level : 'no level';

    但是使用??,你可以保持簡潔

    const username = user.level ?? 'no level'; // output 0. if level is not available, it becomes 'no level'.

    4.Dynamic-import

    從字面上看,應(yīng)該很容易理解,就是在需要的時候加載相關(guān)的邏輯。

    el.onclick = () => {    import(`/js/current-logic.js`)    .then((module) => {        module.doSomthing();    })    .catch((err) => {        handleError(err);    })}

    5. GlobalThis

    全局 globalThis 屬性包含全局 this 值,類似于全局對象。

    過去的做法是:

    // https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/globalThisconst getGlobal = function () {   if (typeof self !== 'undefined') { return self; }   if (typeof window !== 'undefined') { return window; }   if (typeof global !== 'undefined') { return global; }   throw new Error('unable to locate global object'); }; 
    var globals = getGlobal();

    現(xiàn)在,我們可以這樣做:

    function canMakeHTTPRequest() {  return typeof globalThis.XMLHttpRequest === 'function';}console.log(canMakeHTTPRequest());// expected output (in a browser): true

    八、ES12 (ES2021)

    1.Promise.any()

    Promise.any() 接受一個可迭代的 Promise 對象。它返回一個單一的 Promise,只要 iterable 中的任何一個 Promise 完成,就會返回一個 Promise,并帶有已完成的 Promise 的值。

    如果可迭代的實現(xiàn)中沒有任何承諾(如果所有給定的承諾都被拒絕),則返回的承諾會被 AggregateError 拒絕,AggregateError 是 Error 的一個新子類,它將單個錯誤組合在一起。

    const p1 = new Promise((resolve) => {  setTimeout(() => {    resolve('p1 resolved value')  }, 1000)})const p2 = new Promise((resolve) => {  setTimeout(() => {    resolve('p2 resolved value')  }, 500)})const p3 = new Promise((resolve) => {  setTimeout(() => {    resolve('p3 resolved value')  }, 1800)})Promise.any([p1, p2, p3]).then(value=>{  console.log(value)}) // p2 resolved value

    2. 邏輯賦值運算符

    在開發(fā)過程中,我們可以使用 ES2020 中提出的邏輯運算符 ||、&& 和 ??(Nullish coalescing operator)來解決一些問題。

    而 ES2021 會提出 ||= , &&= , ??= ,概念類似于 += :

    let b = 2b += 1 // equal to b = b + 1let a = nulla ||= 'some random text'  // a become to'some random text'// equal a = a || 'some random text'let c = 'some random texts'c &&= null  // c become to null// equal to c = c && nulllet d = nulld ??= false  // d become to false// equal to d = d ?? false

    3. WeakRef

    WeakRef 對象包含對對象的弱引用,該對象稱為其目標(biāo)或引用對象。對對象的弱引用是不會阻止對象被垃圾收集器回收的引用。

    相反,普通(或強)引用將對象保存在內(nèi)存中,當(dāng)一個對象不再有任何強引用時,JavaScript 引擎的垃圾收集器可能會銷毀該對象并回收其內(nèi)存。

    如果發(fā)生這種情況,你將無法再從弱引用中獲取對象。

    此示例啟動一個顯示在 DOM 元素中的計數(shù)器,當(dāng)該元素不再存在時停止:

    class Counter {  constructor(element) {    // Remember a weak reference to the DOM element    this.ref = new WeakRef(element);    this.start();  }
    start() { if (this.timer) { return; }
    this.count = 0;
    const tick = () => { // Get the element from the weak reference, if it still exists const element = this.ref.deref(); if (element) { element.textContent = ++this.count; } else { // The element doesn't exist anymore console.log("The element is gone."); this.stop(); this.ref = null; } };
    tick(); this.timer = setInterval(tick, 1000); }
    stop() { if (this.timer) { clearInterval(this.timer); this.timer = 0; } }}
    const counter = new Counter(document.getElementById("counter"));setTimeout(() => { document.getElementById("counter").remove();}, 5000);

    到這里,今天要跟你分享的內(nèi)容就全部結(jié)束了,這些都是我的一些練習(xí)和學(xué)習(xí)筆記總結(jié),希望對你有用。

    寫在最后

    今天分享的內(nèi)容,如果覺得有用的話,請記得點贊我,關(guān)注我,并將這篇文章與你的開發(fā)者朋友一起來分享它。

    最后,感謝你的閱讀。

    如果你身邊還有想學(xué)習(xí)前端開發(fā)的朋友,也請將我們的公眾號分享給他,也許對他的學(xué)習(xí)有幫助。

    學(xué)習(xí)更多技能

    請點擊下方公眾號

    瀏覽 74
    點贊
    評論
    收藏
    分享

    手機掃一掃分享

    分享
    舉報
    評論
    圖片
    表情
    推薦
    點贊
    評論
    收藏
    分享

    手機掃一掃分享

    分享
    舉報
    <p id="m2nkj"><option id="m2nkj"><big id="m2nkj"></big></option></p>
    <strong id="m2nkj"></strong>
    <ruby id="m2nkj"></ruby>

    <var id="m2nkj"></var>
  • 欧美性爱69网 | 国产精品人妻无码一区牛牛影视 | 欧美黄色一区二区 | 肏屄中国一级黄色 | 日韩欧美高清视频 | 日韩毛片中文字幕 | 无码一区二区激情 | 天天弄天天日 | 亚洲第一免费播放区 | 五月丁香婷婷激情 |