精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

JavaScript 裝飾器進入 stage 3,是時候了解了!

開發 前端
裝飾器在未了解之前,給人一種神秘的感覺,了解之后會發現它的語法并沒有那么復雜。它的一個優點是在不改變原有代碼的基礎之上允許我們來擴展一些新功能。裝飾器只適用于類,不支持函數。函數相對類來說,更容易做一些修飾,例如我們可以使用高階函數做一些包裝。

在一些優秀的開源框架,如 Angular、Nest.js、Midway 中會看到一種常見的寫法 @符號 + 方法名,做為一個只有 JavaScript 經驗的開發者第一次看到這種寫法還是感覺挺新奇的。

一個 @符號開頭 + 方法名,這種寫法正是 JavaScript 中的裝飾器 Decorators,它附加在我們定義的類、類方法、類字段、類訪問器、類自動訪問器上,在不改變原對象基礎上,為我們的程序增強一些功能,例如邏輯復用、代碼解耦。

如下所示 @executionTime 是我們實現的裝飾器函數,它會記錄被修飾方法的執行耗時,下文中我們會進行詳細的介紹。

class Person {
@executionTime
run() {}
}

通過本文你將學到如下內容

圖片

裝飾器動態

關于 JavaScript 裝飾器,已經提案很多年了,盡管提案還未進入最后階段,得益于 TypeScript 和 babel,我們可以在一些框架中提前使用到該技術。 先了解下裝飾器的最新動態,及在 TypeScript、babel 中的支持程度。

一個好消息是 2022-03 JavaScript 裝飾器提案終于進入到 stage 3 了,這已經是到了候選階段了,該階段會接收使用者的反饋并對提案完善,離最終的 stage 4 最近的一個階段了。查看進入到 TC39 提案的一些語法,參考這里閱讀更多 ECMAScript proposals。

一個提案進入到 stage 3 之后,TypeScript 就會去實現它。裝飾器是一個特殊的存在,目前 TypeScript 中的裝飾器實現還是基于第一版裝飾器的提案(這在早期對 TypeScript 也是一個賣點了),和現在 stage 3 中的提案存在很大的差別。

做為用戶可能會擔心,會不會出現不兼容的情況?兼容肯定是要的,舊版也不會立馬廢棄,現在是通過 --experimentalDecorators?、--emitDecoratorMetadata 兩個配置開啟裝飾器,stage 3 的提案離最終已經很近了,要么默認開啟,要么在增加一個新的配置開啟,對使用者來說也許不會有太大的差異,對于庫的開發者 目前 TS 裝飾器和 JS 最新的裝飾器提案實現已經不是一回事了,有很多問題需要考慮。

在可預見的未來,TypeScript 下個版本 5.0 大概率會實現新版裝飾器,參考 TypeScript 接下來的 5.0 版本迭代計劃,里面提到了 “實現更新后的 JavaScript 裝飾器提案”。

  • TypeScript 5.0 Iteration Plan #51362
  • Implement the updated JS decorators proposal #48885

babel 也一直在跟進 JavaScript 裝飾器提案,最新的 stage 3 版本也已實現,算是支持的比較好的了,通過 @babel/plugin-proposal-decorators 插件提供支持,裝飾器不同階段的提案 babel 都有實現,如下所示:

  • 2022-03:在 2022 年 3 月的 TC39 會議上就 Stage 3 達成共識的提案版本。閱讀更多相關信息tc39/proposal-decorators@8ca65c046d。
  • 2021-12:2021 年 12 月提交給 TC39 的提案版本。閱讀更多相關信息 tc39/proposal-decorators@d6c056fa06。
  • 2018-09:最初提升到第 2 階段的提案版本,于 2018 年 9 月提交給 TC39。閱讀更多相關信息tc39/proposal-decorators@7fa580b40f。
  • legacy:最初的第 1 階段提案,閱讀更多相關信息 wycats/javascript-decorators@e1bf8d41bf。

下文用到的所有的代碼會用 babel 編譯,接下來讓我們先搭建一個支持裝飾器的運行環境。

搭建裝飾器運行環境

babel 7.19.0 版本已支持 stage 3 裝飾器,安裝的 babel 大于此即可。

創建一個項目 decorators-demo

$ mkdir decorators-demo
$ cd decorators-demo
$ npm init

安裝 babel 依賴

npm i @babel/core @babel/cli @babel/preset-env @babel/plugin-proposal-decorators -D

創建一個名為 .babelrc 的新文件配置 babel

{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "current"
}
}
]
],
"plugins": [
["@babel/plugin-proposal-decorators", { "version": "2022-03" }] // 這個地方要配置,因為當前默認的版本不是最新的
]
}

編輯 package.json scripts 命令

"scripts": {
"build": "babel index.js -d dist",
"start": "npm run build && node dist/index.js"
}

類裝飾器

類裝飾器修飾的是定義的類本身,我們可以為它添加屬性、方法。類裝飾器類型簽名如下所示,第一個參數 value 就是被修飾的類。

類型簽名如下所示:

type ClassDecorator = (value: Function, context: {
kind: "class";
name: string | undefined;
addInitializer(initializer: () void): void;
}) => Function | void;

為類擴展一個新方法

例如,再不改變原始代碼的情況下,借助外部組件使用類裝飾器為 Person 類擴展一個方法 run。

function addRunMethod(value, { kind, name }) {
if (kind === "class") {
return class extends value {
constructor(...args) {
super(...args);
}
run() {
console.log(`Add a run method for ${this.name}`);
}
}
}
}

@addRunMethod
class Person {
constructor(name) {
this.name = name
}
}

const p1 = new Person('Tom')
p1.run()
const p2 = new Person('Jack')
p2.run()

以上我們是通過繼承被修飾的類并返回一個新的子類方式來擴展一個新方法。我們定義的類裝飾器函數 addRunMethod 第一個參數既然是被修飾的類本身,因此我們還可以通過原型方式來擴展一個新的方法或屬性。

function addRunMethod(value, { kind }) {
if (kind === "class") {
value.prototype.run = function () {
console.log(`Add a run method for ${this.name}`);
}
}
}

類方法裝飾器

類方法裝飾器接收一個被修飾的方法做為第一個參數,并可以選擇返回一個新方法替換原始的方法。類型簽名如下所示:

type ClassMethodDecorator = (value: Function, context: {
kind: "method";
name: string | symbol;
access: { get(): unknown };
static: boolean;
private: boolean;
addInitializer(initializer: () => void): void;
}) => Function | void;

下面從一個記錄方法執行耗時的例子,做個不用裝飾器與用裝飾器的前后效果對比。日常開發工作中我們可能會有類似的需求:“記錄一個方法的執行時間,便于后續做些性能優化”。

示例:方法的計算耗時實現

下面定義了一個 Person 類,有一個 run(跑步) 方法,如果已經吃過飯了,他就有更多的力氣,跑的就會快些,否則就會跑的慢些。sleep 方法是為了輔助做些延遲測試。

const sleep = ms new Promise(resolve setTimeout(() resolve(1), ms));
class Person {
async run(isEat) {
const start = Date.now();
if (isEat) {
await sleep(1000 * 1);
console.log(`execution time: ${Date.now() - start}`);
return `I can run fast.`;
}

await sleep(1000 * 5);
console.log(`execution time: ${Date.now() - start}`);
return `I can't run any faster.`;
}
}

const p = new Person();
console.log(await p.run(true))

上面代碼暴露出兩個問題:

  • 代碼耦合:計算方法執行耗時邏輯與業務代碼耦合,如果測試沒問題之后,想要移除這部分計算執行耗時的代碼邏輯,是不是就很難?
  • 重復性代碼:一個方法內,代碼 7 行、12 行,計算最后耗時部分是完全重復的邏輯,如果還有一個別的方法是不是也要在寫一遍?

示例:使用裝飾器計算耗時

接下來使用類方法裝飾器改寫以上示例,類方法裝飾器第一個參數為被裝飾的函數,可以返回一個新函數來代替被裝飾的方法, 類型簽名如下所示:

type ClassMethodDecorator = (value: Function, context: {
kind: "method";
name: string | symbol;
access: { get(): unknown };
static: boolean;
private: boolean;
addInitializer(initializer: () void): void;
}) => Function | void;

以下聲明一個 @executionTime? 裝飾器函數,該函數包裝原始函數,并在調用前后記錄函數執行耗時。

現在的代碼邏輯看起來是不是清晰了很多?通過裝飾器函數擴展了原有的功能,但并沒有修改原始函數內容,如果哪天想去掉計算函數執行耗時這段邏輯,也容易的多了。

const sleep = ms new Promise(resolve setTimeout(() resolve(1), ms));
function executionTime(value, context) {
const { kind, name } = context;
if (kind === 'method') {
return async function (...args) { // 返回一個新方法,代替被裝飾的方法
const start = Date.now();
const result = await value.apply(this, args);
console.log(`CALL method(${name}) execution time: ${Date.now() - start}`);
return result;
};
}
}

class Person {
@executionTime
async run(isEat) {
if (isEat) {
await sleep(1000 * 1); // 1 minute
return `I can run fast.`;
}

await sleep(1000 * 5); // 5 minute
return `I can't run any faster.`;
}
}

const p = new Person();
console.log(await p.run(true))

注意,類的構造函數不支持裝飾器,盡管構造函數看起來像方法,但實際上不是方法。

示例:實現 @bind 解決 this 問題

下面代碼直接執行 p.run() 是沒問題的,但是將 p.run 提取為一個方法再執行,此時函數內的 this 執行就發生變化了,會被指向為 undefined,單獨運行 run() 方法后就會出現 TypeError: Cannot read properties of undefined (reading '#name') 錯誤。

class Person {
#name
constructor(name) {
this.#name = name;
}

async run() {
console.log(`My name is ${this.#name}`);
}
}

const p = new Person('Tom');
const run = p.run;
run()

裝飾器上下文對象上提供了一個 [添加初始化邏輯 addInitializer()](https://github.com/tc39/proposal-decorators#adding-initialization-logic-with-addinitializer) 方法,可以調用此方法將初始化函數與類或類元素相關聯,該方法在類實例化時會觸發,允許用戶在初始化時添加一些額外的邏輯。

例如,在這里我們可以聲明一個 @bind? 裝飾器在 addInitializer() 方法觸發時將類方法綁定到類實例,解決 this 綁定問題。

function bind(value, context) {
const { kind, name, addInitializer } = context;
if (kind === 'method') {
addInitializer(function () {
this[name] = value.bind(this);
});
}
}

class Person {
...

@bind
async run() {
console.log(`My name is ${this.#name}`);
}
}

示例:實現 @deprecated 提醒廢棄 API

對于某些在今后版本會被移除的 API,可以通過定義一個 @deprecated 的裝飾器,用于 API 將要廢棄的消息提醒。

const DEFAULT_MSG = 'This function will be removed in future versions.';
function deprecated(value, context) {
const { kind, name } = context;
if (kind === 'method') {
return function (...args) {
console.warn(`DEPRECATION ${name}: ${DEFAULT_MSG}`);
const result = value.apply(this, args);
return result;
};
}
}

class Person {
@deprecated
hello() {
console.log(`Hello world!`);
}
}

const p = new Person()
p.hello()

類訪問器裝飾器

類訪問器裝飾器與類方法裝飾器相似,區別地方在于上下文 context 對象的 kind 屬性為 getter、setter。

類型簽名如下所示:

type ClassGetterDecorator = (value: Function, context: {
kind: "getter" | "setter";
name: string | symbol;
access: { get(): unknown } | { set(value: unknown): void };
static: boolean;
private: boolean;
addInitializer(initializer: () => void): void;
}) => Function | void;

示例:實現 @logged 裝飾器

下例,實現一個 @logged 裝飾器 追蹤函數被調用的前后記錄,細看是不是同上面我們自定義的類方法裝飾器 @executionTime 很相似。

function logged(value, context) {
const { kind, name } = context;
if (kind === 'method' || kind === 'getter' || kind === 'setter') {
return function (...args) { // 返回一個新方法,代替被裝飾的方法
console.log(`starting ${name} with arguments ${args.join(", ")}`);
const result = value.apply(this, args);
console.log(`ending ${name}`);
return result;
};
}
}

class Person {
#name
constructor(name) {
this.#name = name;
}
@logged
get name() {
return this.#name;
}
@logged
set name(name) {
this.#name = name;
}
}

const p = new Person('Tom')
p.name = 'Jack'
p.name

類自動訪問裝飾器

讓我們先拋開裝飾器的概念,了解下 accessor 是什么?

類新成員:自動訪問器

類自動訪問器(Auto-Accessors)是 ECMAScript 將要推出的一個新功能,目前 TC39 提案為 stage 1。通過 ??accessor?? 關鍵詞在類屬性前定義。

class Person {
accessor name = 'Tom';
}

類自動訪問器相當于在類原型上定義了 getter、setter,大致等價于以下行為:

class Person {
#name = 'Tom';
get name() {
return this.#name;
}
set name(name) {
this.#name = name;
}
}

自動訪問器裝飾器

自動訪問器裝飾器接收的第一個參數 value 包含了在類原型上定義的訪問器對象 get、set,第二參數 context 對象上的 kind 屬性為 accessor。

自動訪問器裝飾器允許攔截對屬性的訪問,在進行一些包裝之后,返回一個新的 **get**、**set**? 方法,還支持返回一個 **init** 函數,用于更改初始值

類型簽名如下所示:

type ClassAutoAccessorDecorator = (
value: {
get: () unknown;
set(value: unknown) => void;
},
context: {
kind: "accessor";
name: string | symbol;
access: { get(): unknown, set(value: unknown): void };
static: boolean;
private: boolean;
addInitializer(initializer: () => void): void;
}
) => {
get?: () => unknown;
set?: (value: unknown) => void;
init?: (initialValue: unknown) => unknown;
} | void;

示例:實現 @readOnly

實現一個 @readOnly 裝飾器,確保被裝飾的屬性在第一次初始化后可以變為只讀的,如果未被初始化不允許訪問該屬性,給一個錯誤提示。

const UNINITIALIZED = Symbol('UNINITIALIZED');
function readOnly(value, context) {
const { get, set } = value;
const { name, kind } = context;
if (kind === 'accessor') {
return {
init(initialValue) {
return initialValue || UNINITIALIZED;
},
get() {
const value = get.call(this);
if (value === UNINITIALIZED) {
throw new TypeError(
`Accessor ${name} hasn’t been initialized yet`
);
}
return value;
},
set(newValue) {
const oldValue = get.call(this);
if (oldValue !== UNINITIALIZED) {
throw new TypeError(
`Accessor ${name} can only be set once`
);
}
set.call(this, newValue);
},
};
}
}

class Person {
@readOnly
accessor name = 'Tom';
}

const p = new Person()
console.log(p.name);
// p.name = 'Jack' // TypeError: Accessor name can only be set once

類字段裝飾器

類字段裝飾器接收到的第一個參數 value 為 undefined,我們不能更改字段的名稱。通過返回函數,我們可以接收字段的初始值并返回一個新的初始值。

類型簽名如下:

type ClassFieldDecorator = (value: undefined, context: {
kind: "field";
name: string | symbol;
access: { get(): unknown, set(value: unknown): void };
static: boolean;
private: boolean;
}) => (initialValue: unknown) => unknown | void;

示例:將字段初始值翻倍

聲明一個 @multiples() 裝飾器,接收一個倍數,將字段初始值翻倍處理并返回。

function multiples(mutiple) {
return (value, { kind, name }) => {
if (kind === 'field') {
return initialValue initialValue * mutiple;
}
}
}
class Person {
@multiples(3)
count = 2;
}
const p = new Person();
console.log(p.count); // 6

示例:依賴注入示例

Logger 是我們的基礎類,Person 類似于我們的業務類。以下代碼耦合的一點是 Person 與 Logger 產生了直接依賴,對于 Person 類只需要使用 Logger 實例,不需要把 Logger 實例化也放到 Person 類中。接下來我們要解決的是如何將兩個依賴模塊之間的初始化信息解耦。

class Logger {
info(...args) {
console.log(...args);
}
}

class Person {
logger = new Logger();

run() {
this.logger.info('Hi!', 'I am running.')
}
}
const p = new Person();
p.run();

依賴注入是將 “依賴” 注入給調用方,而不是讓調用方直接獲得依賴,在程序運行過程中由專門的組件負責 “依賴” 的實例化。

接下來,使用裝飾器和依賴注冊表實現依賴注入。

const assert = require('assert');
const { registry, inject } = createRegistry();

@registry.register('logger')
class Logger {
info(...args) {
console.log(new Date().toLocaleString(), ...args);
}
}

class Person {
@inject logger;
run() {
this.logger.info('Hi!', 'I am running.')
}
}

const p = new Person();
p.run();
assert.equal(p.logger, registry.getInstance('logger'));

下面是核心方法 createRegistry() 的實現,參考了 JavaScript metaprogramming with the 2022-03 decorators API 的一個示例,下面主要用到了類裝飾器、類字段裝飾器。

function createRegistry() {
const classMap = new Map();
const instancesMap = new Map();
const registry = {
register(registerName) {
return (value, { kind }) => {
if (kind === 'class') {
classMap.set(registerName, value)
}
}
},
getInstance(name) {
if (instancesMap.has(name)) {
return instancesMap.get(name);
}

const TargetClass = classMap.get(name);
if (!TargetClass) {
throw new Error(`Unregistered dependencies with register name: ${name}`);
}
const instance = new TargetClass();
instancesMap.set(name, instance);
return instance;
},
}

return {
registry,

inject: (_value, {kind, name}) => {
if (kind === 'field') {
return () registry.getInstance(name);
}
}
};
}

總結

裝飾器在未了解之前,給人一種神秘的感覺,了解之后會發現它的語法并沒有那么復雜。它的一個優點是在不改變原有代碼的基礎之上允許我們來擴展一些新功能。

裝飾器只適用于類,不支持函數。函數相對類來說,更容易做一些修飾,例如我們可以使用高階函數做一些包裝。

裝飾器可以應用于,類、類字段、類方法、類訪問器、類自動訪問器(這是類的一個新成員)。掌握了裝飾器的使用之后,再去看像 Nest.js、Angular 等這些框架時對于 @expression 這種語法,不會再陌生了。

在了解了裝飾器后,下一步讓我們在詳細了解下什么是 IoC(控制反轉)、DI(依賴注入)。

責任編輯:武曉燕 來源: 編程界
相關推薦

2025-02-17 08:18:27

C#TypeScriptJavaScript

2021-01-12 18:39:24

開源軟件OSS開發

2023-10-19 15:25:40

2023-11-06 13:08:45

2023-11-06 17:37:17

技術架構任務隊列

2021-06-03 09:18:25

裝飾器模式包裝

2025-11-10 09:21:24

2020-04-14 12:12:20

JavaScriptIIFE函數

2020-01-18 14:34:40

5G技術通信

2019-05-07 10:03:47

Linux系統發行版

2024-02-19 08:40:22

2023-12-14 12:55:41

Pythondel語句

2010-08-29 21:09:57

DHCP協議

2023-06-26 07:32:43

Kubernetes容器

2024-03-20 08:31:40

KotlinExtension計算

2023-05-09 09:00:20

版本Canary框架

2023-11-27 00:48:46

displayvisibility

2023-09-27 16:29:55

開發團隊信息

2024-01-03 08:08:51

Pulsar版本數據

2023-11-29 13:51:00

點贊
收藏

51CTO技術棧公眾號

一区二区三区毛片免费| 福利在线免费视频| 麻豆91精品视频| www.精品av.com| 亚洲欧美久久久久| sm国产在线调教视频| 国产精品亚洲第一区在线暖暖韩国| 久久综合九色九九| 久久久久亚洲av无码网站| 日韩av官网| gogogo免费视频观看亚洲一| 69av在线播放| 夫妇露脸对白88av| 国产精品亲子伦av一区二区三区| 成人免费在线播放视频| 电影午夜精品一区二区三区| www.99re7.com| 丝袜连裤袜欧美激情日韩| 91黄色激情网站| 青春草在线视频免费观看| 国产精品乱码久久久| 国内精品99| 亚洲欧洲日产国码av系列天堂| 国产高清视频网站| brazzers在线观看| 欧美激情一区二区在线| 亚洲最大av网| 一级片在线观看免费| 日本不卡免费一区| 精品91自产拍在线观看一区| 国产真实乱子伦| gogogogo高清视频在线| 久久久不卡网国产精品一区| 91香蕉电影院| 日本中文字幕第一页| 亚洲色图二区| 亚洲视频视频在线| 国产吃瓜黑料一区二区| 丁香久久综合| 精品日本高清在线播放| 欧美少妇一级片| 九色视频在线播放| 成人免费av在线| 奇米影视亚洲狠狠色| 国产a免费视频| 成人久久综合| 亚洲精品综合精品自拍| 永久免费看片在线观看| 2019年精品视频自拍| 午夜成人免费电影| 欧洲精品视频在线| 日本中文字幕在线观看| 91丨九色丨蝌蚪丨老版| 97超级碰碰| 一本色道久久综合精品婷婷| 欧美在线综合| 97超视频免费观看| 青青草原免费观看| 久久影院一区| 国产亚洲精品va在线观看| 国产精品无码自拍| 精品视频在线一区| 在线播放一区二区三区| 国产精品后入内射日本在线观看| 午夜伦理在线视频| 亚洲乱码国产乱码精品精的特点| 香蕉久久夜色| 在线视频婷婷| 国产精品久久久久久久第一福利| 日本一区二区三不卡| 五月婷婷深深爱| 99久久综合99久久综合网站| 成人免费视频观看视频| 亚洲精选一区二区三区| 国产精品一二三区在线| 91久久爱成人| www.国产黄色| 国产成人精品影院| 国产精品一区二区三区不卡 | 91精品视频免费在线观看| 久久久夜夜夜| 日韩免费在线视频| 最新在线中文字幕| 麻豆一区二区在线| 成人写真福利网| 国产女无套免费视频| 久久国产成人午夜av影院| 国产精品香蕉国产| 99久久久无码国产精品免费| 国产综合色在线| 超碰97在线资源| 蜜臀久久99精品久久久| kk眼镜猥琐国模调教系列一区二区| 国产日韩一区欧美| 国产在线一二| 国产精品九色蝌蚪自拍| 亚洲第一页在线视频| 黄色成人在线| 性做久久久久久久久| 亚洲欧洲日产国码无码久久99| 黑人巨大精品| 欧美精品丝袜中出| 久久精品一卡二卡| 久久超级碰碰| 中文字幕亚洲欧美| 99精品中文字幕| 狠狠噜噜久久| 国产suv精品一区二区三区88区| 亚洲综合精品国产一区二区三区| 国产伦精品一区二区三区免费迷 | 国产香蕉一区二区三区| 蜜臀av在线| 欧美系列亚洲系列| www.成年人| 日韩电影不卡一区| 日韩在线视频导航| 九九热国产视频| 日韩高清在线观看| 91免费看国产| 青青免费在线视频| 亚洲精品五月天| 99热成人精品热久久66| 四虎国产精品永久在线国在线| 欧美va日韩va| 香蕉久久久久久久| 在线亚洲免费| 444亚洲人体| 成a人v在线播放| 亚洲国产精品视频| www.久久av.com| 精品国产午夜肉伦伦影院| 国产一区二区三区四区福利| 久久一级黄色片| 美女网站视频久久| 美脚丝袜一区二区三区在线观看| 超碰在线无需免费| 欧美色图天堂网| 永久免费未满蜜桃| 五月天久久网站| 国产a∨精品一区二区三区不卡| 免费国产羞羞网站视频| 国产欧美视频一区二区| 欧美 日韩 亚洲 一区| 日韩在线激情| 一区二区三区无码高清视频| 精品91久久久| 成人性生交大片免费看中文网站 | www.国产精品一区| 久久精品视频在线播放| 精品乱码一区内射人妻无码| 99re亚洲国产精品| 草草视频在线免费观看| 一二区成人影院电影网| 日韩精品免费视频| 亚洲精品午夜久久久久久久| 久久99热99| 亚洲欧美精品在线观看| 电影久久久久久| 亚洲香蕉在线观看| 久久精品视频1| wwww国产精品欧美| 日本国产在线播放| 久久精品色综合| 久久久久国产精品免费网站| 99热这里是精品| 亚洲欧美另类小说视频| 色一情一区二区三区| 日韩欧美三级| 国产日韩欧美一二三区| 午夜在线免费观看视频| 欧美性极品少妇| 国产日韩精品中文字无码| 日韩不卡一区二区三区| 欧美一级片免费观看| 成人福利视频| 亚洲人成77777在线观看网| 人妻丰满熟妇av无码区| 久久精品欧美日韩| 五月婷婷六月合| 日韩综合网站| 亚洲在线免费看| 影音先锋在线播放| 日韩一区二区精品在线观看| 午夜精品一区二区三区视频| 国产一区在线视频| 日韩精品久久一区二区| 一区二区三区视频播放| 久久久综合免费视频| 婷婷久久久久久| 在线亚洲免费视频| 老牛影视av老牛影视av| 肉色丝袜一区二区| 青青草国产精品| 色999久久久精品人人澡69| 伦伦影院午夜日韩欧美限制| 精品二区在线观看| 欧美日韩另类在线| 精品人伦一区二区| 国产在线精品免费av| 男女猛烈激情xx00免费视频| 日韩最新在线| 国产日韩精品一区二区| 超碰免费公开在线| 亚洲成人国产精品| 看黄色一级大片| 亚洲男同性恋视频| 人妻无码一区二区三区| 亚洲免费在线| 在线观看精品视频| 欧美电影完整版在线观看| 国产成人福利视频| 丝袜美腿av在线| 国产午夜精品理论片a级探花| 中文字幕+乱码+中文| 一区二区不卡在线播放 | 91精品久久久久久久91蜜桃| 国产在线观看免费视频今夜| 亚洲国产精品黑人久久久| 在线观看网站黄| 久久久国产亚洲精品| 中文字幕在线观看一区二区三区| 涩爱av色老久久精品偷偷鲁| 91高潮精品免费porn| 亚洲s色大片| 日韩精品丝袜在线| 国产女人18毛片18精品| 欧美性xxxxxxx| 欧美片一区二区| 国产精品色哟哟| 最近中文字幕无免费| 蜜桃视频在线观看一区二区| 久久av综合网| 91精品国产调教在线观看| 欧美一区二区三区精美影视| 91蝌蚪精品视频| 成人精品久久av网站| 中文在线免费视频| 欧美国产第一页| 欧美一区二区三区| 揄拍成人国产精品视频| 无码国产色欲xxxx视频| 6080亚洲精品一区二区| 中国a一片一级一片| 亚洲午夜精品在线| 欧美 日韩 国产 一区二区三区| 久久精品一级爱片| 欧美大片免费播放器| 国产丶欧美丶日本不卡视频| 自拍偷拍21p| 水野朝阳av一区二区三区| 缅甸午夜性猛交xxxx| 欧美激情偷拍| 国产成年人在线观看| 水蜜桃精品av一区二区| 亚洲精品一品区二品区三品区| 九色成人国产蝌蚪91| 成人国产一区二区| 欧美经典影片视频网站| 国产在线播放不卡| 国产精品亚洲成在人线| 国产精品扒开腿做爽爽爽视频| 国产黄大片在线观看| 久久久久久18| xxxx在线视频| 九九精品视频在线观看| 国产传媒在线播放| 久久亚洲精品小早川怜子66| 欧美jizzhd69巨大| 久久久精品999| 在线观看免费版| 色婷婷**av毛片一区| 97视频精彩视频在线观看| 一区二区欧美激情| 精品亚洲综合| 亚洲码在线观看| 免费资源在线观看| 伊人伊成久久人综合网站| 成人av一区| 北条麻妃一区二区三区中文字幕| 欧美激情免费| 色综合天天狠天天透天天伊人 | 91在线视频播放| 午夜一区二区三区免费| 久久精品夜色噜噜亚洲a∨| 亚洲 小说 欧美 激情 另类| 久久精品免费在线观看| 少妇愉情理伦三级| 成人欧美一区二区三区小说| 免费在线一区二区三区| 亚洲精品视频在线看| 国产一级在线播放| 色婷婷综合激情| 91tv国产成人福利| 亚洲精品国产福利| 亚洲精品传媒| 97超碰国产精品女人人人爽| 国内精品伊人| 久久99国产精品99久久| 日韩欧美不卡| 欧美韩国日本在线| 国产一区二区免费在线| 中文字幕免费视频| 亚洲午夜电影网| 91国内精品视频| 亚洲毛茸茸少妇高潮呻吟| 欧美成人hd| 国产精品扒开腿做爽爽爽视频| 成功精品影院| 中文字幕中文字幕在线中心一区| 宅男噜噜噜66国产日韩在线观看| 免费网站在线观看黄| 国产日韩欧美精品一区| 男人与禽猛交狂配| 精品久久在线播放| 国产黄a三级三级看三级| 中文字幕久热精品视频在线| 97超碰在线免费| 91久久大香伊蕉在人线| 日韩精品欧美激情一区二区| 大j8黑人w巨大888a片| 国产乱码一区二区三区| 国产黄a三级三级| 一本一本久久a久久精品综合麻豆| www.麻豆av| 久热国产精品视频| 国产精品高潮久久| 日韩成人av电影在线| 亚洲一区二区毛片| 久久久久亚洲无码| 亚洲综合清纯丝袜自拍| 96亚洲精品久久久蜜桃| 在线观看中文字幕亚洲| 中文av在线全新| 玛丽玛丽电影原版免费观看1977| 亚洲承认在线| 久久性爱视频网站| 亚洲制服欧美中文字幕中文字幕| 国产乱叫456在线| 日韩中文字幕在线| 久久久久黄色| 水蜜桃亚洲精品| 日韩和的一区二区| 成人午夜剧场视频网站| 午夜视频一区二区| 欧美一级淫片aaaaaa| 久久久久久尹人网香蕉| 亚洲国产视频二区| 国产专区在线视频| 粉嫩蜜臀av国产精品网站| 欧美人妻精品一区二区三区 | 天天综合网久久| 国产精品素人一区二区| 色老头在线视频| 一本色道久久88综合日韩精品| 欧洲成人一区| 亚洲精美视频| 国产一区二区三区久久悠悠色av| 国产黄色的视频| 亚洲国产成人av在线| 综合日韩av| 视频一区在线免费观看| 久久精品免费看| 青青青在线视频| 亚洲精品国产精品自产a区红杏吧| 蜜桃av.网站在线观看| 欧美日韩精品久久久免费观看| 久久黄色影院| 黄色香蕉视频在线观看| 欧美一区二区播放| 69av成人| 四虎影视永久免费在线观看一区二区三区| av岛国在线| caoporen国产精品| 亚洲三级影院| 国产三级av在线播放| 欧美日韩极品在线观看一区| 国产日产一区二区| 国产精品一区二区欧美| 老牛影视一区二区三区| 精品手机在线视频| 日韩欧美一区电影| 亚洲欧美韩国| 一区精品视频| 成人网在线免费视频| 无码人妻精品一区二区| 久久激情视频久久| 国产三级精品三级在线观看国产| 日日碰狠狠丁香久燥| 综合电影一区二区三区 | 欧美色片在线观看| 不卡中文字幕在线| 99精品桃花视频在线观看| 中文字幕精品一区二| 欧美福利视频在线| av影片在线一区| 日本精品一二三区| 欧美视频一区二区三区四区| 色呦呦在线看| 五月婷婷一区| 99re这里只有精品首页|