国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频

細(xì)數(shù)這些年被困擾過(guò)的 TS 問(wèn)題

共 25582字,需瀏覽 52分鐘

 ·

2021-08-20 00:38

TypeScript 是一種由微軟開(kāi)發(fā)的自由和開(kāi)源的編程語(yǔ)言。它是 JavaScript 的一個(gè)超集,而且本質(zhì)上向這個(gè)語(yǔ)言添加了可選的靜態(tài)類型和基于類的面向?qū)ο缶幊獭?/span>

TypeScript 提供最新的和不斷發(fā)展的 JavaScript 特性,包括那些來(lái)自 2015 年的 ECMAScript 和未來(lái)的提案中的特性,比如異步功能和 Decorators,以幫助建立健壯的組件。

阿寶哥第一次使用 TypeScript 是在 Angular 2.x 項(xiàng)目中,那時(shí)候 TypeScript 還沒(méi)有進(jìn)入大眾的視野。然而現(xiàn)在學(xué)習(xí) TypeScript 的小伙伴越來(lái)越多了,本文阿寶哥將分享這些年在學(xué)習(xí) TypeScript 過(guò)程中,曾被困擾過(guò)的一些 TS 問(wèn)題,希望本文對(duì)學(xué)習(xí) TypeScript 的小伙伴能有一些幫助。

好的,下面我們來(lái)開(kāi)始介紹第一個(gè)問(wèn)題 —— 如何在 window 對(duì)象上顯式設(shè)置屬性。

一、如何在 window 對(duì)象上顯式設(shè)置屬性

對(duì)于使用過(guò) JavaScript 的開(kāi)發(fā)者來(lái)說(shuō),對(duì)于 window.MyNamespace = window.MyNamespace || {}; 這行代碼并不會(huì)陌生。為了避免開(kāi)發(fā)過(guò)程中出現(xiàn)沖突,我們一般會(huì)為某些功能設(shè)置獨(dú)立的命名空間。

然而,在 TS 中對(duì)于 window.MyNamespace = window.MyNamespace || {}; 這行代碼,TS 編譯器會(huì)提示以下異常信息:

Property 'MyNamespace' does not exist on type 'Window & typeof globalThis'.(2339)

以上異常信息是說(shuō)在 Window & typeof globalThis 交叉類型上不存在 MyNamespace 屬性。那么如何解決這個(gè)問(wèn)題呢?最簡(jiǎn)單的方式就是使用類型斷言:

(window as any).MyNamespace = {};

雖然使用 any 大法可以解決上述問(wèn)題,但更好的方式是擴(kuò)展 lib.dom.d.ts 文件中的 Window 接口來(lái)解決上述問(wèn)題,具體方式如下:

declare interface Window {
  MyNamespace: any;
}

window.MyNamespace = window.MyNamespace || {};

下面我們?cè)賮?lái)看一下 lib.dom.d.ts 文件中聲明的 Window 接口:

/**
 * A window containing a DOM document; the document property 
 * points to the DOM document loaded in that window. 
 */

interface Window extends EventTarget, AnimationFrameProvider, GlobalEventHandlers, 
  WindowEventHandlers, WindowLocalStorage, WindowOrWorkerGlobalScope, WindowSessionStorage {
    // 已省略大部分內(nèi)容
    readonly devicePixelRatio: number;
    readonly document: Document;
    readonly top: Window;
    readonly window: Window & typeof globalThis;
    addEventListener(typestring, listener: EventListenerOrEventListenerObject, 
      options?: boolean | AddEventListenerOptions): void;
    removeEventListener<K extends keyof WindowEventMap>(type: K, 
      listener: (this: Window, ev: WindowEventMap[K]) => any
      options?: boolean | EventListenerOptions): void;
    [index: number]: Window;
}

在上面我們聲明了兩個(gè)相同名稱的 Window 接口,這時(shí)并不會(huì)造成沖突。TypeScript 會(huì)自動(dòng)進(jìn)行接口合并,即把雙方的成員放到一個(gè)同名的接口中。

二、如何為對(duì)象動(dòng)態(tài)分配屬性

在 JavaScript 中,我們可以很容易地為對(duì)象動(dòng)態(tài)分配屬性,比如:

let developer = {};
developer.name = "semlinker";

以上代碼在 JavaScript 中可以正常運(yùn)行,但在 TypeScript 中,編譯器會(huì)提示以下異常信息:

Property 'name' does not exist on type '{}'.(2339)

{} 類型表示一個(gè)沒(méi)有包含成員的對(duì)象,所以該類型沒(méi)有包含 name 屬性。為了解決這個(gè)問(wèn)題,我們可以聲明一個(gè) LooseObject 類型:

interface LooseObject {
  [key: string]: any
}

該類型使用 索引簽名 的形式描述 LooseObject 類型可以接受 key 類型是字符串,值的類型是 any 類型的字段。有了 LooseObject 類型之后,我們就可以通過(guò)以下方式來(lái)解決上述問(wèn)題:

interface LooseObject {
  [key: string]: any
}

let developer: LooseObject = {};
developer.name = "semlinker";

對(duì)于 LooseObject 類型來(lái)說(shuō),它的約束是很寬松的。在一些應(yīng)用場(chǎng)景中,我們除了希望能支持動(dòng)態(tài)的屬性之外,也希望能夠聲明一些必選和可選的屬性。

比如對(duì)于一個(gè)表示開(kāi)發(fā)者的 Developer 接口來(lái)說(shuō),我們希望它的 name 屬性是必填,而 age 屬性是可選的,此外還支持動(dòng)態(tài)地設(shè)置字符串類型的屬性。針對(duì)這個(gè)需求我們可以這樣做:

interface Developer {
  name: string;
  age?: number;
  [key: string]: any
}

let developer: Developer = { name: "semlinker" };
developer.age = 30;
developer.city = "XiaMen";

其實(shí)除了使用 索引簽名 之外,我們也可以使用 TypeScript 內(nèi)置的工具類型 Record 來(lái)定義 Developer 接口:

// type Record<K extends string | number | symbol, T> = { [P in K]: T; }
interface Developer extends Record<string, any> {
  name: string;
  age?: number;
}

let developer: Developer = { name: "semlinker" };
developer.age = 30;
developer.city = "XiaMen";

三、如何理解泛型中的 <T>

對(duì)于剛接觸 TypeScript 泛型的讀者來(lái)說(shuō),首次看到 <T> 語(yǔ)法會(huì)感到陌生。其實(shí)它沒(méi)有什么特別,就像傳遞參數(shù)一樣,我們傳遞了我們想要用于特定函數(shù)調(diào)用的類型。

參考上面的圖片,當(dāng)我們調(diào)用 identity<Number>(1) ,Number 類型就像參數(shù) 1 一樣,它將在出現(xiàn) T 的任何位置填充該類型。圖中 <T> 內(nèi)部的 T 被稱為類型變量,它是我們希望傳遞給 identity 函數(shù)的類型占位符,同時(shí)它被分配給 value 參數(shù)用來(lái)代替它的類型:此時(shí) T 充當(dāng)?shù)氖穷愋停皇翘囟ǖ?Number 類型。

其中 T 代表 Type,在定義泛型時(shí)通常用作第一個(gè)類型變量名稱。但實(shí)際上 T 可以用任何有效名稱代替。除了 T 之外,以下是常見(jiàn)泛型變量代表的意思:

  • K(Key):表示對(duì)象中的鍵類型;
  • V(Value):表示對(duì)象中的值類型;
  • E(Element):表示元素類型。

其實(shí)并不是只能定義一個(gè)類型變量,我們可以引入希望定義的任何數(shù)量的類型變量。比如我們引入一個(gè)新的類型變量 U,用于擴(kuò)展我們定義的 identity 函數(shù):

function identity <TU>(value: T, message: U) : T {
  console.log(message);
  return value;
}

console.log(identity<Numberstring>(68"Semlinker"));

除了為類型變量顯式設(shè)定值之外,一種更常見(jiàn)的做法是使編譯器自動(dòng)選擇這些類型,從而使代碼更簡(jiǎn)潔。我們可以完全省略尖括號(hào),比如:

function identity <TU>(value: T, message: U) : T {
  console.log(message);
  return value;
}

console.log(identity(68"Semlinker"));

對(duì)于上述代碼,編譯器足夠聰明,能夠知道我們的參數(shù)類型,并將它們賦值給 T 和 U,而不需要開(kāi)發(fā)人員顯式指定它們。

??  繼續(xù)閱讀一文讀懂 TypeScript 泛型及應(yīng)用

四、如何理解裝飾器的作用

在 TypeScript 中裝飾器分為類裝飾器、屬性裝飾器、方法裝飾器和參數(shù)裝飾器四大類。裝飾器的本質(zhì)是一個(gè)函數(shù),通過(guò)裝飾器我們可以方便地定義與對(duì)象相關(guān)的元數(shù)據(jù)。

比如在 ionic-native 項(xiàng)目中,它使用 Plugin 裝飾器來(lái)定義 IonicNative 中 Device 插件的相關(guān)信息:

@Plugin({
  pluginName: 'Device',
  plugin: 'cordova-plugin-device',
  pluginRef: 'device',
  repo: 'https://github.com/apache/cordova-plugin-device',
  platforms: ['Android''Browser''iOS''macOS''Windows'],
})
@Injectable()
export class Device extends IonicNativePlugin {}

在以上代碼中 Plugin 函數(shù)被稱為裝飾器工廠,調(diào)用該函數(shù)之后會(huì)返回類裝飾器,用于裝飾 Device 類。Plugin 工廠函數(shù)的定義如下:

// https://github.com/ionic-team/ionic-native/blob/v3.x/src/%40ionic-native/core/decorators.ts
export function Plugin(config: PluginConfig): ClassDecorator {
  return function(cls: any{
    // 把config對(duì)象中屬性,作為靜態(tài)屬性添加到cls類上
    for (let prop in config) {
      cls[prop] = config[prop];
    }

    cls['installed'] = function(printWarning?: boolean{
      return !!getPlugin(config.pluginRef);
    };
    // 省略其他內(nèi)容
    return cls;
  };
}

通過(guò)觀察 Plugin 工廠函數(shù)的方法簽名,我們可以知道調(diào)用該函數(shù)之后會(huì)返回 ClassDecorator 類型的對(duì)象,其中 ClassDecorator 類型的聲明如下所示:

declare type ClassDecorator = <TFunction extends Function>(target: TFunction
  =>
 TFunction | void;

類裝飾器顧名思義,就是用來(lái)裝飾類的。它接收一個(gè)參數(shù) —— target: TFunction,表示被裝飾器的類。介紹完上述內(nèi)容之后,我們來(lái)看另一個(gè)問(wèn)題 @Plugin({...}) 中的 @ 符號(hào)有什么用?

其實(shí) @Plugin({...}) 中的 @ 符號(hào)只是語(yǔ)法糖,為什么說(shuō)是語(yǔ)法糖呢?這里我們來(lái)看一下編譯生成的 ES5 代碼:

var __decorate = (this && this.__decorate) || function (decorators, target, key, desc{
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};

var Device = /** @class */ (function (_super{
    __extends(Device, _super);
    function Device({
        return _super !== null && _super.apply(thisarguments) || this;
    }
    Device = __decorate([
        Plugin({
            pluginName'Device',
            plugin'cordova-plugin-device',
            pluginRef'device',
            repo'https://github.com/apache/cordova-plugin-device',
            platforms: ['Android''Browser''iOS''macOS''Windows'],
        }),
        Injectable()
    ], Device);
    return Device;
}(IonicNativePlugin));

通過(guò)生成的代碼可知,@Plugin({...})@Injectable() 最終會(huì)被轉(zhuǎn)換成普通的方法調(diào)用,它們的調(diào)用結(jié)果最終會(huì)以數(shù)組的形式作為參數(shù)傳遞給 __decorate 函數(shù),而在 __decorate 函數(shù)內(nèi)部會(huì)以 Device 類作為參數(shù)調(diào)用各自的類型裝飾器,從而擴(kuò)展對(duì)應(yīng)的功能。

此外,如果你有使用過(guò) Angular,相信你對(duì)以下代碼并不會(huì)陌生。

const API_URL = new InjectionToken('apiUrl');

@Injectable()
export class HttpService {
  constructor(
    private httpClient: HttpClient,
    @Inject(API_URL) private apiUrl: string
  
) {}
}

Injectable 類裝飾器修飾的 HttpService 類中,我們通過(guò)構(gòu)造注入的方式注入了用于處理 HTTP 請(qǐng)求的 HttpClient 依賴對(duì)象。而通過(guò) Inject 參數(shù)裝飾器注入了 API_URL 對(duì)應(yīng)的對(duì)象,這種方式我們稱之為依賴注入(Dependency Injection)。

關(guān)于什么是依賴注入,在 TS 中如何實(shí)現(xiàn)依賴注入功能,出于篇幅考慮,這里阿寶哥就不繼續(xù)展開(kāi)了。感興趣的小伙伴可以閱讀 “了不起的 IoC 與 DI” 這篇文章。

??  繼續(xù)閱讀:覺(jué)得裝飾器有點(diǎn)難?那就進(jìn)來(lái)看看唄

五、如何理解函數(shù)重載的作用

5.1 可愛(ài)又可恨的聯(lián)合類型

由于 JavaScript 是一個(gè)動(dòng)態(tài)語(yǔ)言,我們通常會(huì)使用不同類型的參數(shù)來(lái)調(diào)用同一個(gè)函數(shù),該函數(shù)會(huì)根據(jù)不同的參數(shù)而返回不同的類型的調(diào)用結(jié)果:

function add(x, y{
  return x + y;
}

add(12); // 3
add("1""2"); //"12"

由于 TypeScript 是 JavaScript 的超集,因此以上的代碼可以直接在 TypeScript 中使用,但當(dāng) TypeScript 編譯器開(kāi)啟 noImplicitAny 的配置項(xiàng)時(shí),以上代碼會(huì)提示以下錯(cuò)誤信息:

Parameter 'x' implicitly has an 'any' type.
Parameter 'y' implicitly has an 'any' type.

該信息告訴我們參數(shù) x 和參數(shù) y 隱式具有 any 類型。為了解決這個(gè)問(wèn)題,我們可以為參數(shù)設(shè)置一個(gè)類型。因?yàn)槲覀兿M?add 函數(shù)同時(shí)支持 string 和 number 類型,因此我們可以定義一個(gè) string | number 聯(lián)合類型,同時(shí)我們?yōu)樵撀?lián)合類型取個(gè)別名:

type Combinable = string | number;

在定義完 Combinable 聯(lián)合類型后,我們來(lái)更新一下 add 函數(shù):

function add(a: Combinable, b: Combinable{
  if (typeof a === 'string' || typeof b === 'string') {
    return a.toString() + b.toString();
  }
  return a + b;
}

add 函數(shù)的參數(shù)顯式設(shè)置類型之后,之前錯(cuò)誤的提示消息就消失了。那么此時(shí)的 add 函數(shù)就完美了么,我們來(lái)實(shí)際測(cè)試一下:

const result = add('semlinker'' kakuqo');
result.split(' ');

在上面代碼中,我們分別使用 'semlinker'' kakuqo' 這兩個(gè)字符串作為參數(shù)調(diào)用 add 函數(shù),并把調(diào)用結(jié)果保存到一個(gè)名為 result 的變量上,這時(shí)候我們想當(dāng)然的認(rèn)為此時(shí) result 的變量的類型為 string,所以我們就可以正常調(diào)用字符串對(duì)象上的 split 方法。但這時(shí) TypeScript 編譯器又出現(xiàn)以下錯(cuò)誤信息了:

Property 'split' does not exist on type 'Combinable'.
Property 'split' does not exist on type 'number'.

很明顯 Combinablenumber 類型的對(duì)象上并不存在 split 屬性。問(wèn)題又來(lái)了,那如何解決呢?這時(shí)我們就可以利用 TypeScript 提供的函數(shù)重載。

5.2 函數(shù)重載

函數(shù)重載或方法重載是使用相同名稱和不同參數(shù)數(shù)量或類型創(chuàng)建多個(gè)方法的一種能力。

function add(a: number, b: number): number;
function add(a: string, b: string): string;
function add(a: string, b: number): string;
function add(a: number, b: string): string;
function add(a: Combinable, b: Combinable{
  // type Combinable = string | number;
  if (typeof a === 'string' || typeof b === 'string') {
    return a.toString() + b.toString();
  }
  return a + b;
}

在以上代碼中,我們?yōu)?add 函數(shù)提供了多個(gè)函數(shù)類型定義,從而實(shí)現(xiàn)函數(shù)的重載。在 TypeScript 中除了可以重載普通函數(shù)之外,我們還可以重載類中的成員方法。

方法重載是指在同一個(gè)類中方法同名,參數(shù)不同(參數(shù)類型不同、參數(shù)個(gè)數(shù)不同或參數(shù)個(gè)數(shù)相同時(shí)參數(shù)的先后順序不同),調(diào)用時(shí)根據(jù)實(shí)參的形式,選擇與它匹配的方法執(zhí)行操作的一種技術(shù)。所以類中成員方法滿足重載的條件是:在同一個(gè)類中,方法名相同且參數(shù)列表不同。下面我們來(lái)舉一個(gè)成員方法重載的例子:

class Calculator {
  add(a: number, b: number): number;
  add(a: string, b: string): string;
  add(a: string, b: number): string;
  add(a: number, b: string): string;
  add(a: Combinable, b: Combinable) {
  if (typeof a === 'string' || typeof b === 'string') {
    return a.toString() + b.toString();
  }
    return a + b;
  }
}

const calculator = new Calculator();
const result = calculator.add('Semlinker'' Kakuqo');

這里需要注意的是,當(dāng) TypeScript 編譯器處理函數(shù)重載時(shí),它會(huì)查找重載列表,嘗試使用第一個(gè)重載定義。如果匹配的話就使用這個(gè)。因此,在定義重載的時(shí)候,一定要把最精確的定義放在最前面。另外在 Calculator 類中,add(a: Combinable, b: Combinable){ } 并不是重載列表的一部分,因此對(duì)于 add 成員方法來(lái)說(shuō),我們只定義了四個(gè)重載方法。

??  繼續(xù)閱讀:是時(shí)候表演真正的技術(shù)了 - TS 分身之術(shù)

六、interfaces 與 type 之間有什么區(qū)別

6.1 Objects/Functions

接口和類型別名都可以用來(lái)描述對(duì)象的形狀或函數(shù)簽名:

接口

interface Point {
  x: number;
  y: number;
}

interface SetPoint {
  (x: number, y: number): void;
}

類型別名

type Point = {
  x: number;
  y: number;
};

type SetPoint = (x: number, y: number) => void;

6.2 Other Types

與接口類型不一樣,類型別名可以用于一些其他類型,比如原始類型、聯(lián)合類型和元組:

// primitive
type Name = string;

// object
type PartialPointX = { x: number; };
type PartialPointY = { y: number; };

// union
type PartialPoint = PartialPointX | PartialPointY;

// tuple
type Data = [numberstring];

6.3 Extend

接口和類型別名都能夠被擴(kuò)展,但語(yǔ)法有所不同。此外,接口和類型別名不是互斥的。接口可以擴(kuò)展類型別名,而反過(guò)來(lái)是不行的。

Interface extends interface

interface PartialPointX { x: number; }
interface Point extends PartialPointX { 
  y: number
}

Type alias extends type alias

type PartialPointX = { x: number; };
type Point = PartialPointX & { y: number; };

Interface extends type alias

type PartialPointX = { x: number; };
interface Point extends PartialPointX { y: number; }

Type alias extends interface

interface PartialPointX { x: number; }
type Point = PartialPointX & { y: number; };

6.4 Implements

類可以以相同的方式實(shí)現(xiàn)接口或類型別名,但類不能實(shí)現(xiàn)使用類型別名定義的聯(lián)合類型:

interface Point {
  x: number;
  y: number;
}

class SomePoint implements Point {
  x = 1;
  y = 2;
}

type Point2 = {
  x: number;
  y: number;
};

class SomePoint2 implements Point2 {
  x = 1;
  y = 2;
}

type PartialPoint = { x: number; } | { y: number; };

// A class can only implement an object type or 
// intersection of object types with statically known members.
class SomePartialPoint implements PartialPoint { // Error
  x = 1;
  y = 2;
}

6.5 Declaration merging

與類型別名不同,接口可以定義多次,會(huì)被自動(dòng)合并為單個(gè)接口。

interface Point { x: number; }
interface Point { y: number; }

const point: Point = { x: 1, y: 2 };

七、object, Object 和 {} 之間有什么區(qū)別

7.1 object 類型

object 類型是:TypeScript 2.2 引入的新類型,它用于表示非原始類型。

// node_modules/typescript/lib/lib.es5.d.ts
interface ObjectConstructor {
  create(o: object | null): any;
  // ...
}

const proto = {};

Object.create(proto);     // OK
Object.create(null);      // OK
Object.create(undefined); // Error
Object.create(1337);      // Error
Object.create(true);      // Error
Object.create("oops");    // Error

7.2 Object 類型

Object 類型:它是所有 Object 類的實(shí)例的類型,它由以下兩個(gè)接口來(lái)定義:

  • Object 接口定義了 Object.prototype 原型對(duì)象上的屬性;
// node_modules/typescript/lib/lib.es5.d.ts
interface Object {
  constructor: Function;
  toString(): string;
  toLocaleString(): string;
  valueOf(): Object;
  hasOwnProperty(v: PropertyKey): boolean;
  isPrototypeOf(v: Object): boolean;
  propertyIsEnumerable(v: PropertyKey): boolean;
}
  • ObjectConstructor 接口定義了 Object 類的屬性。
// node_modules/typescript/lib/lib.es5.d.ts
interface ObjectConstructor {
  /** Invocation via `new` */
  new(value?: any): Object;
  /** Invocation via function calls */
  (value?: any): any;
  readonly prototype: Object;
  getPrototypeOf(o: any): any;
  // ···
}

declare var Object: ObjectConstructor;

Object 類的所有實(shí)例都繼承了 Object 接口中的所有屬性。

7.3 {} 類型

{} 類型描述了一個(gè)沒(méi)有成員的對(duì)象。當(dāng)你試圖訪問(wèn)這樣一個(gè)對(duì)象的任意屬性時(shí),TypeScript 會(huì)產(chǎn)生一個(gè)編譯時(shí)錯(cuò)誤。

// Type {}
const obj = {};

// Error: Property 'prop' does not exist on type '{}'.
obj.prop = "semlinker";

但是,你仍然可以使用在 Object 類型上定義的所有屬性和方法,這些屬性和方法可通過(guò) JavaScript 的原型鏈隱式地使用:

// Type {}
const obj = {};

// "[object Object]"
obj.toString();

??  繼續(xù)閱讀:一文讀懂 TS 中 Object, object, {} 類型之間的區(qū)別

八、數(shù)字枚舉與字符串枚舉之間有什么區(qū)別

8.1 數(shù)字枚舉

在 JavaScript 中布爾類型的變量含有有限范圍的值,即 truefalse。而在 TypeScript 中利用枚舉,你也可以自定義相似的類型:

enum NoYes {
  No,
  Yes,
}

NoYes 被稱為枚舉 NoYes 的成員。每個(gè)枚舉成員都有一個(gè) name 和一個(gè) value。數(shù)字枚舉成員值的默認(rèn)類型是 number 類型。也就是說(shuō),每個(gè)成員的值都是一個(gè)數(shù)字:

enum NoYes {
  No,
  Yes,
}

assert.equal(NoYes.No, 0);
assert.equal(NoYes.Yes, 1);

除了讓 TypeScript 為我們指定枚舉成員的值之外,我們還可以手動(dòng)賦值:

enum NoYes {
  No = 0,
  Yes = 1,
}

這種通過(guò)等號(hào)的顯式賦值稱為 initializer。如果枚舉中某個(gè)成員的值使用顯式方式賦值,但后續(xù)成員未顯示賦值, TypeScript 會(huì)基于當(dāng)前成員的值加 1 作為后續(xù)成員的值。

8.2 字符串枚舉

除了數(shù)字枚舉,我們還可以使用字符串作為枚舉成員值:

enum NoYes {
  No = 'No',
  Yes = 'Yes',
}

assert.equal(NoYes.No, 'No');
assert.equal(NoYes.Yes, 'Yes');

8.3 數(shù)字枚舉 vs 字符串枚舉

數(shù)字枚舉與字符串枚舉有什么區(qū)別呢?這里我們來(lái)分別看一下數(shù)字枚舉和字符串枚舉編譯的結(jié)果:

數(shù)字枚舉編譯結(jié)果

"use strict";
var NoYes;
(function (NoYes{
   NoYes[NoYes["No"] = 0] = "No";
   NoYes[NoYes["Yes"] = 1] = "Yes";
})(NoYes || (NoYes = {}));

字符串枚舉編譯結(jié)果

"use strict";
var NoYes;
(function (NoYes{
   NoYes["No"] = "No";
   NoYes["Yes"] = "Yes";
})(NoYes || (NoYes = {}));

通過(guò)觀察以上結(jié)果,我們知道數(shù)值枚舉除了支持 從成員名稱到成員值 的普通映射之外,它還支持 從成員值到成員名稱 的反向映射。另外,對(duì)于純字符串枚舉,我們不能省略任何初始化程序。而數(shù)字枚舉如果沒(méi)有顯式設(shè)置值時(shí),則會(huì)使用默認(rèn)值進(jìn)行初始化。

8.4 為數(shù)字枚舉分配越界值

講到數(shù)字枚舉,這里我們?cè)賮?lái)看個(gè)問(wèn)題:

const enum Fonum {
  a = 1,
  b = 2
}

let value: Fonum = 12// Ok

相信很多讀者看到 let value: Fonum = 12; 這一行,TS 編譯器并未提示任何錯(cuò)誤會(huì)感到驚訝。很明顯數(shù)字 12 并不是 Fonum 枚舉的成員。 為什么會(huì)這樣呢?我們來(lái)看一下 TypeScript issues 26362 中 DanielRosenwasser 大佬的回答:

The behavior is motivated by bitwise operations. There are times when SomeFlag.Foo | SomeFlag.Bar is intended to produce another SomeFlag. Instead you end up with number, and you don't want to have to cast back to SomeFlag.

該行為是由按位運(yùn)算引起的。有時(shí) SomeFlag.Foo | SomeFlag.Bar 用于生成另一個(gè) SomeFlag。相反,你最終得到的是數(shù)字,并且你不想強(qiáng)制回退到 SomeFlag。

了解完上述內(nèi)容,我們?cè)賮?lái)看一下 let value: Fonum = 12; 這個(gè)語(yǔ)句,該語(yǔ)句 TS 編譯器不會(huì)報(bào)錯(cuò),是因?yàn)閿?shù)字 12 是可以通過(guò) Fonum 已有的枚舉成員計(jì)算而得。

let value: Fonum = 
  Fonum.a << Fonum.b << Fonum.a |  Fonum.a << Fonum.b; // 12


??  繼續(xù)閱讀:5000 多字,讓你一文掌握 TS 枚舉

九、使用 # 定義的私有字段與 private 修飾符定義字段有什么區(qū)別

在 TypeScript 3.8 版本就開(kāi)始支持 ECMAScript 私有字段,使用方式如下:

class Person {
  #name: string;

  constructor(name: string) {
    this.#name = name;
  }

  greet() {
    console.log(`Hello, my name is ${this.#name}!`);
  }
}

let semlinker = new Person("Semlinker");

semlinker.#name;
//     ~~~~~
// Property '#name' is not accessible outside class 'Person'
// because it has a private identifier.

與常規(guī)屬性(甚至使用 private 修飾符聲明的屬性)不同,私有字段要牢記以下規(guī)則:

  • 私有字段以 # 字符開(kāi)頭,有時(shí)我們稱之為私有名稱;
  • 每個(gè)私有字段名稱都唯一地限定于其包含的類;
  • 不能在私有字段上使用 TypeScript 可訪問(wèn)性修飾符(如 public 或 private);
  • 私有字段不能在包含的類之外訪問(wèn),甚至不能被檢測(cè)到。

說(shuō)到這里使用 # 定義的私有字段與 private 修飾符定義字段有什么區(qū)別呢?現(xiàn)在我們先來(lái)看一個(gè) private 的示例:

class Person {
  constructor(private name: string){}
}

let person = new Person("Semlinker");
console.log(person.name);

在上面代碼中,我們創(chuàng)建了一個(gè) Person 類,該類中使用 private 修飾符定義了一個(gè)私有屬性 name,接著使用該類創(chuàng)建一個(gè) person 對(duì)象,然后通過(guò) person.name 來(lái)訪問(wèn) person 對(duì)象的私有屬性,這時(shí) TypeScript 編譯器會(huì)提示以下異常:

Property 'name' is private and only accessible within class 'Person'.(2341)

那如何解決這個(gè)異常呢?當(dāng)然你可以使用類型斷言把 person 轉(zhuǎn)為 any 類型:

console.log((person as any).name);

通過(guò)這種方式雖然解決了 TypeScript 編譯器的異常提示,但是在運(yùn)行時(shí)我們還是可以訪問(wèn)到 Person 類內(nèi)部的私有屬性,為什么會(huì)這樣呢?我們來(lái)看一下編譯生成的 ES5 代碼,也許你就知道答案了:

var Person = /** @class */ (function ({
    function Person(name{
      this.name = name;
    }
    return Person;
}());

var person = new Person("Semlinker");
console.log(person.name);

這時(shí)相信有些小伙伴會(huì)好奇,在 TypeScript 3.8 以上版本通過(guò) # 號(hào)定義的私有字段編譯后會(huì)生成什么代碼:

class Person {
  #name: string;

  constructor(name: string) {
    this.#name = name;
  }

  greet() {
    console.log(`Hello, my name is ${this.#name}!`);
  }
}

以上代碼目標(biāo)設(shè)置為 ES2015,會(huì)編譯生成以下代碼:

"use strict";
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) 
  || function (receiver, privateMap, value{
    if (!privateMap.has(receiver)) {
      throw new TypeError("attempted to set private field on non-instance");
    }
    privateMap.set(receiver, value);
    return value;
};

var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) 
  || function (receiver, privateMap{
    if (!privateMap.has(receiver)) {
      throw new TypeError("attempted to get private field on non-instance");
    }
    return privateMap.get(receiver);
};

var _name;
class Person {
    constructor(name) {
      _name.set(thisvoid 0);
      __classPrivateFieldSet(this, _name, name);
    }
    greet() {
      console.log(`Hello, my name is ${__classPrivateFieldGet(this, _name)}!`);
    }
}
_name = new WeakMap();

通過(guò)觀察上述代碼,使用 # 號(hào)定義的 ECMAScript 私有字段,會(huì)通過(guò) WeakMap 對(duì)象來(lái)存儲(chǔ),同時(shí)編譯器會(huì)生成 __classPrivateFieldSet__classPrivateFieldGet 這兩個(gè)方法用于設(shè)置值和獲取值。

??  繼續(xù)閱讀:你不知道的 WeakMap

以上提到的這些問(wèn)題,相信一些小伙伴們?cè)趯W(xué)習(xí) TS 過(guò)程中也遇到了。如果有表述不清楚的地方,歡迎你們給我留言或直接與我交流。之后,阿寶哥還會(huì)繼續(xù)補(bǔ)充和完善這一方面的內(nèi)容,感興趣的小伙伴可以一起參與喲。

十、參考資源

  • how-do-you-explicitly-set-a-new-property-on-window-in-typescript
  • how-do-i-dynamically-assign-properties-to-an-object-in-typescript
  • typescript-interfaces-vs-types

瀏覽 39
點(diǎn)贊
評(píng)論
收藏
分享

手機(jī)掃一掃分享

分享
舉報(bào)
評(píng)論
圖片
表情
推薦
點(diǎn)贊
評(píng)論
收藏
分享

手機(jī)掃一掃分享

分享
舉報(bào)

感谢您访问我们的网站,您可能还对以下资源感兴趣:

国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频 欧美三级无码| 91九色91蝌蚪91窝成人| 日韩视频久久| 亚洲精品高清视频| 爱爱天堂| 天天爽爽爽爽爽成人片| 性爱免费视频| 人妻互换一二三区免费| 人妻精品一区二区| 骚五月| 中文字幕乱码中文乱码91| 伊人大香蕉网站| av免费观看网站| 日本一级片在线播放| www黄片| 国产在线不卡| 91色在线观看| 97人妻天天摸天天爽天天| 日韩av小电影| 日本黄色电影在线观看| 无码av高清| 一本色道久久综合狠狠躁| 午夜免费性爱视频| 怡春院中文字幕| 婷婷久久久| 婷婷视频在线| 2017天天干| 一级国产欧美成人A片| 欧美射精视频| 成人毛片18| 一级黄片免费| 高清毛片AAAAAAAAA郊外| 18+免费网站| 国产欧美综合在线三区| 三级视频在线观看| 偷拍三区| 精品无码一区二区三| 国产精品综合激情| 91豆花成人网站| 在线亚洲免费| 九九精品视频在线观看| 国产操b视频| 天天爽天天爽夜夜爽毛片| 久久99精品国产.久久久久久| 日韩操逼AV| 成人色视| 久久99精品久久久久| 日韩精品人妻中文字幕| 琪琪色在线视频| 亚洲日本中文字幕在线| 日色色色| 五月天久久久久久| 亚州加勒比无码| 日韩无码中文字幕| 国产精品久久久久久久久免费无码 | 久久久久久久久黄色| 亚洲狼人久久久精品| 亚洲精品成人无码熟妇在线| 蜜臀久久99精品久久一区二区| 大屌av| 国产十欧洲十美国+亚洲一二三区在线午夜 | 北条麻妃视频在线播放| 麻豆人妻换人妻好紧| 四虎A片| 国产精品99久久免费黑人人妻| 北条麻妃在线播放一区| 国产免费精彩视频| 午夜精品18码视频国产17c| 三级无码| 驲韩在线视频免费观看| 操逼无码| 色欲国产精品欧美在线密| 亚洲精品字幕| 操噜噜噜噜噜插| 高清无码免费视频| 黄色视频| 2025精品精品视频| 强奸校花到高潮| 色秘乱码一区二区三区| 佳佳女王footjob超级爽| 黄色天堂天天看| 中文字幕不卡AV在线观看| 黄色在线欣赏| 日本色色网站免费| 四川少妇搡bbbb搡bbbb| www.日韩系列| 人妻体体内射精一区二区| 人人人人干| 能看的操逼网站| 国产精品黑人ThePorn| 国产在线观看黄| 一级a一级a爱片兔兔软件| 久久婷婷青青| 日日操天天| 最新亚洲中文字幕| 翔田千里无码免费播放| 高清无码不卡视频| 国产深喉视频| 国产一在线| 久久久久99精品成人片三人毛片 | 99爱爱| 成人爽a毛片一区二区免费| 亚州精品人妻一二三区| 欧美日韩性爱视频| 麻豆视频在线观看| 黄色一级网站| 日韩欧美在线观看| 日本一区二区三| 91re| 高潮91PORN蝌蚪九色| 操逼人妻| 欧美亚洲国产视频| 91香蕉视频免费在线观看| 在线观看操逼视频| 五月丁香亭亭| www欧美日韩| 亚洲A视频| 黄色www| 中文无码AV| 玩弄大乳乳妾高潮乳喷视频| 性爱AV在线观看| 操美女一区二区| 精品少妇无码视频| 秋霞午夜福利影院| 人人操超碰在线观看| 日本一本在线| 人妻黄色视频| 欧美成人午夜视频| 中国一级A片| 77777免费观看电视剧推荐爱的教育| 色天堂在线观看| 懂色av粉嫩AV蜜臀AV| 久久久久久无码视频| 爱爱天堂| 特级444www| 午夜福利100理论片| 免费黄色一级电影| 69精品无码成人久久久久久| 色444| 日韩电影中文字幕| 国产45页| 天天插综合| 国产91在线看| 69人妻人人澡人人爽久久| 日日操日日| 骚逼操| 99内射| 亚洲中文字幕在线播放| 无码不卡视频在线| av手机天堂网| 中文字幕免费MV第一季歌词 | 亚洲国产高清无码| 青青在线| 成人视频高清无码| 先锋影音成人资源| 少妇厨房愉情理伦BD在线观看| 日一日射一射| 国产一级免费| 欧美成人网站在线观看| 永久免费看A人片无码精| 亚洲天堂福利| 亚洲xx网| 国产做受91一片二片老头| 日本精品在线视频| 爱视频福利| 日本韩国叼嘿片| 成人性在线| 久久AV电影| 亚洲免费成人网| 免费A网站| 特级毛片| Al激情欧美| 日日综合网| 在线观看日韩视频| 男人在线天堂| 高清免费无码视频| 天天射天天干| 五月婷婷俺也去| 狠狠狠狠狠狠干| 91视频www| 亚洲精品视频在线播放| 成人国产精品秘在线看| 婷婷男人天堂| 午夜福利视频3000| 无码区一区二区三区| 无码一区二区免费| 国产亚洲视频完整在线观看| 乱伦AV网| 69精品在线| 国产成人无码区亚洲A片356p | 日本狠狠干| 国产精品国产精品国产专区不| 一级片在线观看视频| 久久亚洲福利视频| 竹菊av一区二区三区四区五区 | 东京热综合影院| 五月丁香婷婷开心| av手机天堂| 成人亚洲A片V一区二区三区蜜月| 一级免费黄片| 色婷婷视频一区二区| 欧美v在线观看| 初尝人妻滑进去了莹莹视频| 五月激情网站| 激情小视频国产在线播放| 五月天久久综合| 黄网在线播放| 91亚洲精品在线| 日韩aaa| 免费观看黄色一级片| 美女免费AV| 中文字幕观看在线| 91人人澡| 欧一美一婬一伦一区二区三区自慰国| 日韩一区二区不卡| 国产区精品| 黄色大片AV在线| 欧一美一婬一伦一区二区三区自慰国| 熟女人妻在线观看| 国产成人AV网站| 人妻japanesewoman| 成人丁香五月天| 狼人香蕉网| 成人免费看AA片| 尤物一区二区| 男人操女人免费网站| 亚洲人妻无码视频| 在线不卡视频| 91无码高清视频| 99re6热在线精品视频| www.亚洲成人| 久久人妻无码| 五月丁香六月激情综合| 亚州在线视频| 无码中文字幕| A级视频免费观看| 农村老太HD肉HD| 大香蕉中文在线| 久草中文在线视频| 久久婷香| 动漫3d啪啪成人h动漫| 日本欧洲三级| 亚洲性无码| 91做爱| 99青青草| 人人操超碰在线观看| 国产婷婷色一区二区在线观看| 在线免费观看黄色视频| 久草高清视频| 午夜黄色小视频| 肏屄视频在线观看| 亚洲成人h| 国产原创精品| 天天色图| 激情视频小说| AV在线免费观看网址| 国产视频一区二区三区四区| 超碰97人妻| 巜痴漢電車~凌脔版2| sesese| 国产丰满大乳无码免费播放| 色拍拍视频| 91视频网站| 日本国产黄色| 丰满人妻一区二区三区不卡二| 亚洲福利女神成人福利| 伊人大香蕉视频在线观看| 男人色天堂网| 五月色综合网| www.日韩一区| 特级西西WWW888| 亚洲AV无码成人精品久久久| 色天使视频| 亚洲人人操| 欧美足交视频| 日韩中文字幕在线观看视频| 最新版本日本亚洲色| www.xxx国产| 四川女人毛多水多A片| 天天爽爽爽爽爽成人片| 亚洲肏屄网| 亚洲激情网站| 日本少妇BBw| 国产一级女婬乱免费看| 老妇性BBWBBWBBWBBW| 一区视频免费观看| 波多野结衣无码AV在线| 中国极品少妇XXX| 中文无码第一页| 日韩免费| 欧美久久一区| 日韩免费网站| 中文字幕人成人乱| 激情五月天在线观看| 亚洲午夜福利| 91亚洲国产成人久久精品网站 | 亚洲成人一区二区在线观看| 日本成人电影一区二区三区| 国精产品一区二区三区黑人和中国 | 久久久精品网站| 无码中文av| 日本天堂网在线观看| 午夜精品电影| 久草黄色电影| 国产黄色视频在线看| 高清无码在线看| 亚洲中文免费观看| 97成人人妻一区二区三区| 免费无码成人| 亚洲人妻无码一区| 欧美一二三区黄色免费视屏| H片免费在线观看| 中文字幕乱妇无码Av在线| 无码一区二区区| 中文无码在线视频| 国产成人精品国内自产拍免费看| 亚洲免费观看高清完整版在va线 | 日韩在线中文字幕| 三级黄色免费网站| 91成人亚洲| 影音先锋91久久网| 国产成人毛片| www.jiujiujiu| 草草在线视频| 最好看2019中文在线播放电影| 国产精品日韩无码| 亚洲AV无码成人网站国产网站| 18禁av在线| 中文字幕国产| 欧美婬乱片A片AAA毛片地址| 黄片视频免费看| 先锋成人av| 青青伊人网| 九月丁香婷婷| 91偷拍视频| 翔田千里无码免费播放| 成人国产综合| 豆花视频无码| 日韩一二三区| 在线视频播放| 一本色道久久综合亚洲精品久久| 无码中文综合成熟精品AV电影| 欧美日韩精品一区二区| 思思热在线视频播放| 97精品人人妻人人| 插菊花综合网亚洲| 日韩成人一区二区| 操逼色| 成人无码交配视频国产网站| 亚洲高清视屏| 国产精品久久毛片A片| 久久久婷婷五月亚洲国产精品| 91av无码| 一级性生活视频| 日韩激情网站| 少妇熟女视频一区二区三区| 色吟AV| 久久久综合网| 国产精品成人无码a无码| 亚欧综合在线| 亚洲AV观看| 69成人国产| 欧美性猛交XXXX乱大交3| PORNY九色视频9l自拍| 天堂无码在线| 日韩A毛片| 精品视频在线免费观看| 91大神shunv| 精品欧美一区二区三区| 自拍超碰在线| 日韩三级| 安微妇搡BBBB搡BBBB| 人人干人人操人人爱| 亚洲无码视频一区二区| 嫖中国站街老熟女HD| 91视频内射| 开心五月色婷婷综合开心网| 岛国无码在线| 骚骚网| 无码视频免费| 色综合加勒比| 成人国产精品在线观看| 亚洲高清无码在线视频| 免费肏屄| 成人一级视频| 西西WWW888大胆无码| www.日韩| 久久大屌| 任你爽在线视频| 人妻无码久久| 青青操天天干| 一区二区三区在线观看视频| 亚洲男女免费视频| 天堂亚洲AV无码精品成人| 91碰碰| 日韩高清无码成人| 在线免费观看AV片| 无码波多野结衣| 中文字幕成人电影| 四川少妇bbbbbbbbb| 免费在线观看中文字幕| 日韩黄色无码视频| 青娱乐亚洲视频在线| 久久影音先锋| 韩国人妻无码| 国产丝袜AV| 人人搞人人摸| 国产一级二级三级久久久| 日韩爱爱| 强奸乱伦五月天| 99亚洲欲妇| 草久在线视频| 亚洲欧美v在线视频| 中文字幕无码视频| 在线观看污网站| aaa精品视频| 爱爱91| 人人超碰人人| 亚洲日韩免费在线观看| AV片在线观看| 影音先锋成人在线视频| 免费无码视频| 99伊人网| 大屌在线| 丁香五月天婷婷| 亚洲五月天婷婷| 国产成人三级在线播放| 亚洲日韩视频在线观看| 亚洲AV播放| 丁香激情视频| 天天干天天看| 国产成人无码Av片在线公司| 欧美日韩A片欧美日| 国产精品av在线| 激情网站在线| 正在播放吴梦梦淫行| 国产在线高潮| 日韩欧美大片在线观看| 天天爽夜夜爽| 人妻丰满熟妇av无码区| 色色五月丁香| 人人狠狠综合婷婷| 翔田千里一区二区三区| 伊人久久无码| 操女人逼AV| www.17c嫩嫩草色蜜桃网站| 好逼天天有| 色色色色色欧美| 性V天堂| 这里只有精品视频在线| 国产精品久久久久久久免牛肉蒲| 国产精品自拍小视频| 国产黄片一区二区| 欧洲毛片基地c区| 日韩成人一区| 九九韩剧网最新电视剧免费观看| 日韩精品成人AV| 翔田千里无码XXXXXX| 亚洲aⅴ| 国产欧美在线免费观看| 国产av影院| 狠狠干五月天| 精品一区二区免费视频| 久久伊人大香蕉| 亚洲国产免费| 日韩精品视频免费在线观看 | 俺也要操| 国产成人综合自拍| 色婷| 日本有码在线| 大香蕉久久久久久久| 日韩三级毛片| 黑巨茎大战欧美白妞小说| 亚洲深夜福利| 91精品婷婷国产| 在线视频日韩| 欧美老女人性爱视频| 日本欧美成人片AAAA| 狼友在线视频| 中文字幕高清在线| 五月天婷婷影院影院| 91九色麻豆| 中文字幕免费在线| 嫩草视频在线观看| 欧美日在线观看| 三级片在线观看网站| 国产一区二区在线视频| 亚洲人成色777777无码| 欧美AⅤ视频| 一级黄色AV片| 久久精品小视频| 欧美级毛片一进一出夜本色| 亚洲综合一区二区三区| 蕉蕉视| 无码人妻丰满熟妇| 久久久久无码国产精品不卡| 91久久人澡人妻人人澡人人爽| 天天都色| 蝌蚪窝在线观看| www.日本色| 久久电影精品| 欧美黄色网视频| 日韩成人免费| 九九热国产视频| 国产女人高潮毛片| 欧美日韩亚洲一区二区三区| 日比视频| 黄网站免费在线观看| 国产黄色视频在线看| 久久久在线视频| 午色婷婷国产无码| 成人做爰黄A片免费看陈冠| 日韩在线播放视频| 天天日少妇| 久久六月天| 免费一级A片| 日本少妇无码| 麻豆AV无码| 国产91在线一区| 性满足BBwBBWBBw| 台湾无码| 超碰操逼| 大陆一级片| 欧美在线视频网| 激情青青草| 欧美熟妇精品一二三区| 免费看黃色AAAAAA片| 青草青在线视频| 宅男噜噜噜66一区二区| 97超碰在线视| 国产P片内射天涯海角| 日韩福利片| www.色悠悠| 日韩一区在线播放| 人成在线观看| 欧一美一伦一A片| 女生自慰在线观看| 免费V片| 国产综合在线播放| 无码欧美成人AAAA三区在线| 欧美一级高清片免费一级a| 日本无码久久嗯啊流水| 99re在线观看| 中文字幕-区二区三区四区视频中国| 黄色高清无码视频| 青青草视频偷拍| 色色网站视频| 国产一区二区00000视频| 亚洲在线看| 91久久久久久| 四川少妇BBBB| 日本无码网站| 黄色综合网站| 日韩黄色A片| 超碰乱交av在线| 日韩欧美高清视频| 青青草伊人网| 精品国产欧美| 伊人黄色电影| 可以看的黄色视频| 色五月婷婷视频| 肥臀AV在线| 欧美精产国品一二三区| 91做爱| 怡红院欧美| 尤物在线免费视频| 国产成人精品无码片子的价格| 西西人体BBBBBB| 51XX嘿嘿午夜| av中文在线| 91乱子伦国产乱子伦| 成人三级片在线播放| 国产高清色| 内射婷婷| 夜夜嗨Av禁果Av粉嫩AV懂色Av | 人人色人人爱| 无码视频在线观看免费| 天天插天天狠天天透| 人妻精品久久久久中文字幕69| 另类视频在线| 91精品视频在线免费观看| 8050午| 亚洲去干网| 免费黄色网址啊不卡| 日韩高清在线| 亚洲精品国产AV| 亚洲成人综合在线| 午夜天堂精品久久| 自拍偷拍15p| 亚洲国产成人AV| 色婷婷色婷婷| 91精品少妇高潮一区二区三区不卡 | 在线免费观看黄色电影| 奇米色五月| 国产精品一区二区不卡| 夜夜夜叫天天天做| 中文字幕AV一区| 北条麻妃青青久久| 亚洲永久天堂| 亚洲a在线视频| 天天综合字幕一区二区| 影音先锋中文字幕资源| 欧美日日| 国产一级在线| 毛片国产| 久热精品视频在线观看| 国产AV一区二区三区精品| 在线视频免费观看| 欧美一区二区三区成人片下载| 在线激情网站| 欧美日韩在线视频免费观看| 欧美亚洲成人在线观看| 国产一级a免一级a免费| 五月天婷婷在线视频| 少妇AAA级久久久无码精品片| 色99在线视频| 中文字幕日本电影| 精品无码一区二区三区四区久久久软件 | 日韩在线免费观看视频| 国产精品无码怀孕软件| 日本午夜福利电影| 激情开心五月天| 国产灬性灬淫灬欲水灬| 色综合天天综合网国产成人网 | 污污污污污www网站免费观看 | 精品人妻一区二区免费蜜桃| 台湾精品一区二区三区| 97人妻人人| 小黄片免费看| 日韩日逼网站| 婷婷五月六月| 国产亚洲欧美日韩高清| 911国产在线| 西西444WWW无码大胆在线观看| 这里视频很精彩免费观看电视剧最新| 国产二区视频| 欧美撸一撸| 国产粉嫩小泬白浆18p| 欧美乱轮| 亚洲乱码国产乱码精品天美传媒 | 在线观看亚洲| 中文字幕无码在线观看| 久久久三级片| 蜜桃91精品秘入口| 亚洲操逼视频| 亚洲无码自拍| 日韩无码网| 麻豆性爱| 亚洲免费网站| 亚洲婷婷三级成人网| 日韩免费视频| 天堂在线最新资源| 国产嫩草久久久一二三久久免费观看| 欧美成人图片视频在线| gogogo视频在线观看黑人| 狼友视频第二页| 日韩三级片av| 精品国产一区二区三区性色AV| 中国1级毛片| 亚洲成人怡红院| 亚洲精品图片| 亚洲色情在线播放| 东京热网站在线观看| 中文字幕天天在线| 欧美日韩一级黄色片| 2024男人天堂| 亚洲五月天色| 日韩在线91| 亚洲少妇人妻| 青青草大香蕉伊人| 精品白浆| 亚洲少妇无码| 一级片成人| 91视频免费播放| 一级a片免费观看| 夜色福利视频| 在线观看亚洲天堂| 免费人妻视频| 午夜精品秘一区二区三区| 天天干天天插| 日本三级片在线| 婷婷深爱五月丁香网| 东京热无码高清| 五月天AV网站| 欧美一级特黄A片免费观看| 欧美AAAAAAAA| 亚洲日韩欧美色图| 在线看片av| 国产丝袜av| 久久久久久久无码| 国产日韩在线视频| 18岁毛片| 欧美精品综合| 蜜桃av秘无码一区三区四| 麻豆一级片| 四虎2025在线51| 成人av影院| 在线不卡无码| 亚州性爱| 国产人妖AV| 欧美99在线| 国产人妻人伦精品1国产丝袜| 麻豆一级片| 韩国三级HD中文字幕2019年| 日本无码视频在线观看毒| 2017天天射| 日韩在线国产| 成熟的国模冰莲[2]| 91久久精品无码一区| 欧美成人精品欧美一级| 大黑人荫蒂BBBBBBBBB| 国产AⅤ爽aV久久久久成人| 亚洲精品AⅤ一区二| 日本无码一区二区| 黄色大片久草| 五月天无码av| 日韩综合区| 多啪啪免费视频| 九九九无码| 蜜桃Av噜噜一区二区三| 五十路无码| 先锋影音在线资源| 免费看性蜜桃| 91丨PORNY丨在线中文| 95四川乱子伦视频国产| 亚洲AV无码乱码国产精品黑人| 成人自拍在线| 国产三级AV在线| a片在线视频| 国产熟妇码视频| 亚洲黄色电影在线观看| 亚洲国产一区二区三区四区| 亚洲无码你懂的| 青青草网址| 三级片亚洲| 视频一区二区三区在线观看| 丁香五月AV| 亚洲婷婷五月| 国产精品伦理| 97超碰网| 制服丝袜在线视频| 欧美a片在线观看| 亚洲无码精品在线观看| 豆花成人社区,视频| 色欲国产精品欧美在线密| 亚洲AV无码成人精品久久久| 精品无码AV一区二区三区| 夫妻-ThePorn| 不卡视频一区二区| 日皮视频免费| 亚洲操逼视频| 毛片黄片| 屁屁影院CCYYCOM发布地| 熟女国产| 97视频在线观看免费| 特级西西人体大胆无码| 土耳其电影《爱与罚》| 欧美特黄AAA| 四虎在线免费视频| 久草手机视频在线观看| 去干网欧美| 最好看的2019中文在线大全电影| 日韩AV无码免费| 国产性生活视频| 欧美AAA片| 国产在线观看无码免费视频| 日韩在线中文| 这里只有精品91| 嘿咻嘿咻动态图| 婷婷五月天大香蕉| 成人动漫一区二区| 男女午夜福利| 妓女不卡| 国产熟女AV| 中文字幕A片| 影音先锋在线视频| 亚洲人妻AV| 天天干天天撸影视| 黄色电影AV| 亚洲AV无码精品国产| 亚洲精品成人av无码| 亚洲AV无码成人精品| 最新日韩在线| 人人妻日日摸狠狠躁视频| 免费观看黄色视频网站| 天天插夜夜操| 日韩精品在线视频| 国产精品一区二区黑人巨大| www.豆花福利视频| 爱爱成人视频| 国产精品久久久久野外| 色老板在线视频| 国产黄片在线播放| 日韩AV无码一区二区三区| 午夜激情AV| 中国老太卖婬HD播放| 成人免费高清| 美女扣穴| 五月天国产精品| 欧美一级a| 色噜噜一区二区| 亚洲家庭乱伦| 免费a片视频| 91探花秘在线播放| 日韩av成人| AV无码一区二区| 一级a一级a免费观看视频Al明星 | 国产精品在线观看| 亚洲免费av在线| 久久婷婷五月综合伊人| av资源在线播放| 国产高清av| 操逼手机视频| 国产操b视频| 日韩欧美成人电影| 欧美成人片免费看| 人人干超碰| 成全在线观看高清的| 爱搞逼综合网| 中国人妻HDbute熟睡| 欧美群交videotv群交| 亚洲无码一级片| 亚洲无码自拍| 天天久久毛片| 日韩人妻码一区二区三区| 大香蕉伊人综合| 永久免费不卡在线观看黄网站| 国产一区二三区| 91小视频在线观看| 亚洲欧美日韩在线| 日韩精品观看| 四色永久成人网站| 一区不卡| 成人三级片视频| 欧美久久大香蕉| 久久视频免费观看| 亚洲第一香蕉视频| jizz免费在线观看| 91麻豆影院| 暗呦罗莉精品一区二区| 无码精品在线观看| 亚洲成人观看| 青青草AV| 少妇成人网| 麻豆传媒在线播放| 中文字幕在线观看网站| 男人天堂网AV| 日韩91在线| 无码群交东京热| 成年人免费黄色视频| 特级欧美AAAAAA| 91蝌蚪丨人妻丨丝袜| 四川妇搡BBBB搡BBBB| www.丁香五月| 亚洲精品福利| 久久久www成人免费毛片| 久久婷婷国产综合| 亚洲无码免费在线| 久久久久三级| 国产美女在线播放| 日韩无码一二三| 亚洲性爱综合| 免费十无码| 欧美色交| 亚洲色男人天堂| 欧美内射网站| 中文字幕无码AV| 黄色片亚洲| 色婷婷一区二区三区久久午夜 | 夜夜躁狠狠躁日日躁av| A视频免费| 亚洲高清无码视频在线| 99热在线免费观看| 黄色小视频在线| 免费操| 激情男人网| 国产AⅤ无码一区二区| 国产免费黄色片| 人妻无码中文久久久久专区| 99草在线视频| 人妻少妇无码| 亚洲色视频在线| 一道本无码在线播放| 波多野结衣AV无码| 日韩极品在线观看| 成年人免费视频网站| 中文字幕操逼网站| 老太老熟女城中层露脸60| 99成人国产精品视频| 欧美,日韩,中文字幕| 色色播| 91黄色片| 亚洲不卡一区二区三区| 欧美成人午夜| 国产AV无遮挡| 欧美黄色精品| 91操操| 操逼人妻| 91豆花成人网站| 成人无码小电影|