<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## 注釋 使用 JSDoc 我們使用[JSDoc](http://code.google.com/p/jsdoc-toolkit/)中的注釋風格. 行內注釋使用 // 變量 的形式. 另外, 我們也遵循[C++ 代碼注釋風格](http://docs.kissyui.com/docs/html/styleguide/google/cppguide.xml#Comments). 這也就是說你需要: * 版權和著作權的信息, * 文件注釋中應該寫明該文件的基本信息(如, 這段代碼的功能摘要, 如何使用, 與哪些東西相關), 來告訴那些不熟悉代碼的讀者. * 類, 函數, 變量和必要的注釋, * 期望在哪些瀏覽器中執行, * 正確的大小寫, 標點和拼寫. 為了避免出現句子片段, 請以合適的大/小寫單詞開頭, 并以合適的標點符號結束這個句子. 現在假設維護這段代碼的是一位初學者. 這可能正好是這樣的! 目前很多編譯器可從 JSDoc 中提取類型信息, 來對代碼進行驗證, 刪除和壓縮. 因此, 你很有必要去熟悉正確完整的 JSDoc . ### 頂層/文件注釋 頂層注釋用于告訴不熟悉這段代碼的讀者這個文件中包含哪些東西. 應該提供文件的大體內容, 它的作者, 依賴關系和兼容性信息. 如下: ``` // Copyright 2009 Google Inc. All Rights Reserved. /** * @fileoverview Description of file, its uses and information * about its dependencies. * @author user@google.com (Firstname Lastname) */ ``` ### 類注釋 每個類的定義都要附帶一份注釋, 描述類的功能和用法.也需要說明構造器參數. 如果該類繼承自其它類, 應該使用 `@extends` 標記. 如果該類是對接口的實現, 應該使用 `@implements` 標記. ``` /** * Class making something fun and easy. * @param {string} arg1 An argument that makes this more interesting. * @param {Array.<number>} arg2 List of numbers to be processed. * @constructor * @extends {goog.Disposable} */ project.MyClass = function(arg1, arg2) { // ... }; goog.inherits(project.MyClass, goog.Disposable); ``` ### 方法與函數的注釋 提供參數的說明. 使用完整的句子, 并用第三人稱來書寫方法說明. ``` /** * Converts text to some completely different text. * @param {string} arg1 An argument that makes this more interesting. * @return {string} Some return value. */ project.MyClass.prototype.someMethod = function(arg1) { // ... }; /** * Operates on an instance of MyClass and returns something. * @param {project.MyClass} obj Instance of MyClass which leads to a long * comment that needs to be wrapped to two lines. * @return {boolean} Whether something occured. */ function PR_someMethod(obj) { // ... } ``` 對于一些簡單的, 不帶參數的 getters, 說明可以忽略. ``` /** * @return {Element} The element for the component. */ goog.ui.Component.prototype.getElement = function() { return this.element_; }; ``` ### 屬性注釋 也需要對屬性進行注釋. ``` /** * Maximum number of things per pane. * @type {number} */ project.MyClass.prototype.someProperty = 4; ``` ### 類型轉換的注釋 有時, 類型檢查不能很準確地推斷出表達式的類型, 所以應該給它添加類型標記注釋來明確之, 并且必須在表達式和類型標簽外面包裹括號. ``` /** @type {number} */ (x) (/** @type {number} */ x) ``` ### JSDoc 縮進 如果你在 `@param`, `@return`, `@supported`, `@this` 或 `@deprecated` 中斷行, 需要像在代碼中一樣, 使用4個空格作為一個縮進層次. ``` /** * Illustrates line wrapping for long param/return descriptions. * @param {string} foo This is a param with a description too long to fit in * one line. * @return {number} This returns something that has a description too long to * fit in one line. */ project.MyClass.prototype.method = function(foo) { return 5; }; ``` 不要在 `@fileoverview` 標記中進行縮進. 雖然不建議, 但也可對說明文字進行適當的排版對齊. 不過, 這樣帶來一些負面影響, 就是當你每次修改變量名時, 都得重新排版說明文字以保持和變量名對齊. ``` /** * This is NOT the preferred indentation method. * @param {string} foo This is a param with a description too long to fit in * one line. * @return {number} This returns something that has a description too long to * fit in one line. */ project.MyClass.prototype.method = function(foo) { return 5; }; ``` ### 枚舉 ``` /** * Enum for tri-state values. * @enum {number} */ project.TriState = { TRUE: 1, FALSE: -1, MAYBE: 0 }; ``` 注意一下, 枚舉也具有有效[類型](#JavaScript_Types), 所以可以當成參數類型來用. ``` /** * Sets project state. * @param {project.TriState} state New project state. */ project.setState = function(state) { // ... }; ``` ### Typedefs 有時類型會很復雜. 比如下面的函數, 接收 Element 參數: ``` /** * @param {string} tagName * @param {(string|Element|Text|Array.<Element>|Array.<Text>)} contents * @return {Element} */ goog.createElement = function(tagName, contents) { ... }; ``` 你可以使用 `@typedef` 標記來定義個常用的類型表達式. ``` /** * @param {string} tagName * @param {goog.ElementContent} contents * @return {Element} */ goog.createElement = function(tagName, contents) { ... }; ``` ### JSDoc 標記表 #### `@param` 模板 & 例子: ``` @param {Type} 變量名 描述 ``` _如:_ ``` /** * Queries a Baz for items. * @param {number} groupNum Subgroup id to query. * @param {string|number|null} term An itemName, * or itemId, or null to search everything. */ goog.Baz.prototype.query = function(groupNum, term) { // ... }; ``` 描述:給方法, 函數, 構造器中的參數添加說明. 類型檢測支持:完全支持. #### `@return` 模板 & 例子: ``` @return {Type} 描述 ``` _如:_ ``` /** * @return {string} The hex ID of the last item. */ goog.Baz.prototype.getLastId = function() { // ... return id; }; ``` 描述:給方法, 函數的返回值添加說明. 在描述布爾型參數時, 用 “Whether the component is visible” 這種描述優于 “True if the component is visible, false otherwise”. 如果函數沒有返回值, 就不需要添加`@return`標記. 類型檢測支持:完全支持. #### `@author` 模板 & 例子: ``` @author username@google.com (first last) ``` _如:_ ``` /** * @fileoverview Utilities for handling textareas. * @author kuth@google.com (Uthur Pendragon) */ ``` 描述:表明文件的作者,通常僅會在`@fileoverview`注釋中使用到它. 類型檢測支持:不需要. #### `@see` 模板 & 例子: ``` @see Link ``` _如:_ ``` /** * Adds a single item, recklessly. * @see #addSafely * @see goog.Collect * @see goog.RecklessAdder#add ... ``` 描述:給出引用鏈接, 用于進一步查看函數/方法的相關細節. 類型檢測支持:不需要. #### `@fileoverview` 模板 & 例子: ``` @fileoverview 描述 ``` _如:_ ``` /** * @fileoverview Utilities for doing things that require this very long * but not indented comment. * @author kuth@google.com (Uthur Pendragon) */ ``` 描述:文件通覽. 類型檢測支持:不需要. #### `@constructor` 模板 & 例子: ``` @constructor ``` _如:_ ``` /** * A rectangle. * @constructor */ function GM_Rect() { ... } ``` 描述:指明類中的構造器. 類型檢測支持:會檢查. 如果省略了, 編譯器將禁止實例化. #### `@interface` 模板 & 例子: ``` @interface ``` _如:_ ``` /** * A shape. * @interface */ function Shape() {}; Shape.prototype.draw = function() {}; /** * A polygon. * @interface * @extends {Shape} */ function Polygon() {}; Polygon.prototype.getSides = function() {}; ``` 描述:指明這個函數是一個接口. 類型檢測支持:會檢查. 如果實例化一個接口, 編譯器會警告. #### `@type` 模板 & 例子: ``` @type Type @type {Type} ``` _如:_ ``` /** * The message hex ID. * @type {string} */ var hexId = hexId; ``` 描述:標識變量, 屬性或表達式的類型. 大多數類型是不需要加大括號的, 但為了保持一致, 建議統一加大括號. | 類型檢測支持:會檢查 #### `@extends` 模板 & 例子: ``` @extends Type @extends {Type} ``` _如:_ ``` /** * Immutable empty node list. * @constructor * @extends goog.ds.BasicNodeList */ goog.ds.EmptyNodeList = function() { ... }; ``` 描述:與 @constructor 一起使用, 用來表明該類是擴展自其它類的. 類型外的大括號可寫可不寫. 類型檢測支持:會檢查 #### `@implements` 模板 & 例子: ``` @implements Type @implements {Type} ``` _如:_ ``` /** * A shape. * @interface */ function Shape() {}; Shape.prototype.draw = function() {}; /** * @constructor * @implements {Shape} */ function Square() {}; Square.prototype.draw = function() { ... }; ``` 描述:與 @constructor 一起使用, 用來表明該類實現自一個接口. 類型外的大括號可寫可不寫. 類型檢測支持:會檢查. 如果接口不完整, 編譯器會警告. #### `@lends` 模板 & 例子: ``` @lends objectName @lends {objectName} ``` _如:_ ``` goog.object.extend( Button.prototype, /** @lends {Button.prototype} */ { isButton: function() { return true; } }); ``` 描述:表示把對象的鍵看成是其他對象的屬性. 該標記只能出現在對象語法中. 注意, 括號中的名稱和其他標記中的類型名稱不一樣, 它是一個對象名, 以”借過來”的屬性名命名. 如, @type {Foo} 表示 “Foo 的一個實例”, but @lends {Foo} 表示 “Foo 構造器”. 更多有關此標記的內容見[JSDoc Toolkit docs](http://code.google.com/p/jsdoc-toolkit/wiki/TagLends). 類型檢測支持:會檢查 #### `@private` 模板 & 例子: ``` @private ``` _如:_ ``` /** * Handlers that are listening to this logger. * @type Array.<Function> * @private */ this.handlers_ = []; ``` 描述:指明那些以下劃線結尾的方法和屬性是 [私有](#Visibility__private_and_protected_fields_)的. 不推薦使用后綴下劃線, 而應改用 @private. 類型檢測支持:需要指定標志來開啟. #### `@protected` 模板 & 例子: ``` @protected ``` _如:_ ``` /** * Sets the component's root element to the given element. Considered * protected and final. * @param {Element} element Root element for the component. * @protected */ goog.ui.Component.prototype.setElementInternal = function(element) { // ... }; ``` 描述:指明接下來的方法和屬性是[被保護](#Visibility__private_and_protected_fields_)的. 被保護的方法和屬性的命名不需要以下劃線結尾, 和普通變量名沒區別. | 類型檢測支持:需要指定標志來開啟. #### `@this` 模板 & 例子: ``` @this Type @this {Type} ``` _如:_ ``` pinto.chat.RosterWidget.extern('getRosterElement', /** * Returns the roster widget element. * @this pinto.chat.RosterWidget * @return {Element} */ function() { return this.getWrappedComponent_().getElement(); }); ``` 描述:指明調用這個方法時, 需要在哪個上下文中. 當 this 指向的不是原型方法的函數時必須使用這個標記. 類型檢測支持:會檢查 #### `@supported` 模板 & 例子: ``` @supported 描述 ``` _如:_ ``` /** * @fileoverview Event Manager * Provides an abstracted interface to the * browsers' event systems. * @supported So far tested in IE6 and FF1.5 */ ``` 描述:在文件概述中用到, 表明支持哪些瀏覽器. 類型檢測支持:不需要. #### `@enum` 模板 & 例子: ``` @enum {Type} ``` _如:_ ``` /** * Enum for tri-state values. * @enum {number} */ project.TriState = { TRUE: 1, FALSE: -1, MAYBE: 0 }; ``` 描述:用于枚舉類型. 類型檢測支持:完全支持. 如果省略, 會認為是整型. #### `@deprecated` 模板 & 例子: ``` @deprecated 描述 ``` _如:_ ``` /** * Determines whether a node is a field. * @return {boolean} True if the contents of * the element are editable, but the element * itself is not. * @deprecated Use isField(). */ BN_EditUtil.isTopEditableField = function(node) { // ... }; ``` 描述:告訴其他開發人員, 此方法, 函數已經過時, 不要再使用. 同時也會給出替代方法或函數. 類型檢測支持:不需要 #### `@override` 模板 & 例子: ``` @override ``` _如:_ ``` /** * @return {string} Human-readable representation of project.SubClass. * @override */ project.SubClass.prototype.toString() { // ... }; ``` 描述:指明子類的方法和屬性是故意隱藏了父類的方法和屬性. 如果子類的方法和屬性沒有自己的文檔, 就會繼承父類的. 類型檢測支持:會檢查 #### `@inheritDoc` 模板 & 例子: ``` @inheritDoc ``` _如:_ ``` /** @inheritDoc */ project.SubClass.prototype.toString() { // ... }; ``` 描述:指明子類的方法和屬性是故意隱藏了父類的方法和屬性, 它們具有相同的文檔. 注意: 使用@inheritDoc 意味著也同時使用了 @override. | 類型檢測支持:會檢查 #### `@code` 模板 & 例子: ``` {@code …} ``` _如:_ ``` /** * Moves to the next position in the selection. * Throws {@code goog.iter.StopIteration} when it * passes the end of the range. * @return {Node} The node at the next position. */ goog.dom.RangeIterator.prototype.next = function() { // ... }; ``` 描述:說明這是一段代碼, 讓它能在生成的文檔中正確的格式化. 類型檢測支持:不適用. #### `@license` or `@preserve` 模板 & 例子: ``` @license ``` 描述: _如:_ ``` /** * @preserve Copyright 2009 SomeThirdParty. * Here is the full license text and copyright * notice for this file. Note that the notice can span several * lines and is only terminated by the closing star and slash: */ ``` 描述:所有被標記為 @license 或 @preserve 的, 會被編譯器保留不做任何修改而直接輸出到最終文擋中. 這個標記讓一些重要的信息(如法律許可或版權信息)原樣保留, 同樣, 文本中的換行也會被保留. | 類型檢測支持:不需要. #### `@noalias` 模板 & 例子: ``` @noalias ``` _如:_ ``` /** @noalias */ function Range() {} ``` 描述:在外部文件中使用, 告訴編譯器不要為這個變量或函數重命名. 類型檢測支持:不需要. #### `@define` 模板 & 例子: ``` @define {Type} 描述 ``` _如:_ ``` /** @define {boolean} */ var TR_FLAGS_ENABLE_DEBUG = true; /** @define {boolean} */ goog.userAgent.ASSUME_IE = false; ``` 描述:表示該變量可在編譯時被編譯器重新賦值. 在上面例子中, BUILD 文件中指定了 ``` –define=’goog.userAgent.ASSUME_IE=true’ ``` 這個編譯之后, 常量 goog.userAgent.ASSUME_IE 將被全部直接替換為 true. 類型檢測支持:不需要. #### `@export` 模板 & 例子: ``` @export ``` _如:_ ``` /** @export */ foo.MyPublicClass.prototype.myPublicMethod = function() { // ... }; ``` 描述: 上面的例子代碼, 當編譯器運行時指定 –generate_exports 標志, 會生成下面的代碼: ``` goog.exportSymbol('foo.MyPublicClass.prototype.myPublicMethod', foo.MyPublicClass.prototype.myPublicMethod); ``` 編譯后, 將源代碼中的名字原樣導出. 使用 @export 標記時, 應該 1. 包含 //javascript/closure/base.js, 或者 2. 在代碼庫中自定義 goog.exportSymbol 和 goog.exportProperty 兩個方法, 并保證有相同的調用方式. 類型檢測支持:不需要. #### `@const` 模板 & 例子: ``` @const ``` _如:_ ``` /** @const */ var MY_BEER = 'stout'; /** * My namespace's favorite kind of beer. * @const * @type {string} */ mynamespace.MY_BEER = 'stout'; /** @const */ MyClass.MY_BEER = 'stout'; ``` 描述: 聲明變量為只讀, 直接寫在一行上. 如果其他代碼中重寫該變量值, 編譯器會警告. 常量應全部用大寫字符, 不過使用這個標記, 可以幫你消除命名上依賴. 雖然 jsdoc.org 上列出的 @final 標記作用等價于 @const , 但不建議使用. @const 與 JS1.5 中的 const 關鍵字一致. 注意, 編譯器不禁止修改常量對象的屬性(這與 C++ 中的常量定義不一樣). 如果可以準確推測出常量類型的話,那么類型申明可以忽略. 如果指定了類型, 應該也寫在同一行上. 變量的額外注釋可寫可不寫. 類型檢測支持:支持. #### `@nosideeffects` 模板 & 例子: ``` @nosideeffects ``` _如:_ ``` /** @nosideeffects */ function noSideEffectsFn1() { // ... }; /** @nosideeffects */ var noSideEffectsFn2 = function() { // ... }; /** @nosideeffects */ a.prototype.noSideEffectsFn3 = function() { // ... }; ``` 描述:用于對函數或構造器聲明, 說明調用此函數不會有副作用. 編譯器遇到此標記時, 如果調用函數的返回值沒有其他地方使用到, 則會將這個函數整個刪除. 類型檢測支持:不需要檢查. #### `@typedef` 模板 & 例子: ``` @typedef ``` _如:_ ``` /** @typedef {(string|number)} */ goog.NumberLike; /** @param {goog.NumberLike} x A number or a string. */ goog.readNumber = function(x) { ... } ``` 描述:這個標記用于給一個復雜的類型取一個別名. 類型檢測支持:會檢查 #### `@externs` 模板 & 例子: ``` @externs ``` _如:_ ``` /** * @fileoverview This is an externs file. * @externs */ var document; ``` 描述: 指明一個外部文件. 類型檢測支持:不會檢查 在第三方代碼中, 你還會見到其他一些 JSDoc 標記. 這些標記在[JSDoc Toolkit Tag Reference](http://code.google.com/p/jsdoc-toolkit/wiki/TagReference)都有介紹到, 但在 Google 的代碼中, 目前不推薦使用. 你可以認為這些是將來會用到的 “保留” 名. 它們包含: * @augments * @argument * @borrows * @class * @constant * @constructs * @default * @event * @example * @field * @function * @ignore * @inner * @link * @memberOf * @name * @namespace * @property * @public * @requires * @returns * @since * @static * @version ### JSDoc 中的 HTML 類似于 JavaDoc, JSDoc 支持許多 HTML 標簽, 如 `<code>`, `<pre>`, `<strong>`, `<ul>`, `<ol>`, `<li>`, `<a>`, 等等. 這就是說 JSDoc 不會完全依照純文本中書寫的格式. 所以, 不要在 JSDoc 中, 使用空白字符來做格式化: ``` /** * Computes weight based on three factors: * items sent * items received * last timestamp */ ``` 上面的注釋, 出來的結果是: ``` Computes weight based on three factors: items sent items received items received ``` 應該這樣寫: ``` /** * Computes weight based on three factors: * <ul> * <li>items sent * <li>items received * <li>last timestamp * </ul> */ ``` 另外, 也不要包含任何 HTML 或類 HTML 標簽, 除非你就想讓它們解析成 HTML 標簽. ``` /** * Changes <b> tags to tags. */ ``` 出來的結果是: ``` Changes tags to tags. ``` 另外, 也應該在源代碼文件中讓其他人更可讀, 所以不要過于使用 HTML 標簽: ``` /** * Changes &lt;b&gt; tags to &lt;span&gt; tags. */ ``` 上面的代碼中, 其他人就很難知道你想干嘛, 直接改成下面的樣子就清楚多了: ``` /** * Changes 'b' tags to 'span' tags. */ ``` ### 編譯 推薦使用 建議您去使用 JS 編譯器, 如 [Closure Compiler](http://code.google.com/closure/compiler/). ### Tips and Tricks JavaScript 小技巧 True 和 False 布爾表達式 下面的布爾表達式都返回 false: * `null` * `undefined` * `''` 空字符串 * `0` 數字0 但小心下面的, 可都返回 true: * `'0'` 字符串0 * `[]` 空數組 * `{}` 空對象 下面段比較糟糕的代碼: ``` while (x != null) { ``` 你可以直接寫成下面的形式(只要你希望 x 不是 0 和空字符串, 和 false): 如果你想檢查字符串是否為 null 或空: ``` if (y != null && y != '') { ``` 但這樣會更好: 注意: 還有很多需要注意的地方, 如: * `Boolean('0') == true` `'0' != true` * `0 != null` `0 == []` `0 == false` * `Boolean(null) == false` `null != true` `null != false` * `Boolean(undefined) == false` `undefined != true` `undefined != false` * `Boolean([]) == true` `[] != true` `[] == false` * `Boolean({}) == true` `{} != true` `{} != false` ### 條件(三元)操作符 (?:) 三元操作符用于替代下面的代碼: ``` if (val != 0) { return foo(); } else { return bar(); } ``` 你可以寫成: 在生成 HTML 代碼時也是很有用的: ``` var html = '<input type="checkbox"' + (isChecked ? ' checked' : '') + (isEnabled ? '' : ' disabled') + ' name="foo">'; ``` ### `&&` 和 `||` 二元布爾操作符是可短路的, 只有在必要時才會計算到最后一項. “||” 被稱作為 ‘default’ 操作符, 因為可以這樣: ``` /** @param {*=} opt_win */ function foo(opt_win) { var win; if (opt_win) { win = opt_win; } else { win = window; } // ... } ``` 你可以使用它來簡化上面的代碼: ``` /** @param {*=} opt_win */ function foo(opt_win) { var win = opt_win || window; // ... } ``` “&&” 也可簡短代碼.比如: ``` if (node) { if (node.kids) { if (node.kids[index]) { foo(node.kids[index]); } } } ``` 你可以像這樣來使用: ``` if (node && node.kids && node.kids[index]) { foo(node.kids[index]); } ``` 或者: ``` var kid = node && node.kids && node.kids[index]; if (kid) { foo(kid); } ``` 不過這樣就有點兒過頭了: ``` node && node.kids && node.kids[index] && foo(node.kids[index]); ``` ### 使用 join() 來創建字符串 通常是這樣使用的: ``` function listHtml(items) { var html = ''; for (var i = 0; i < items.length; ++i) { if (i > 0) { html += ', '; } html += itemHtml(items[i]); } html += ''; return html; } ``` 但這樣在 IE 下非常慢, 可以用下面的方式: ``` function listHtml(items) { var html = []; for (var i = 0; i < items.length; ++i) { html[i] = itemHtml(items[i]); } return '' + html.join(', ') + ''; } ``` 你也可以是用數組作為字符串構造器, 然后通過 `myArray.join('')` 轉換成字符串. 不過由于賦值操作快于數組的 `push()`, 所以盡量使用賦值操作. ### 遍歷 Node List Node lists 是通過給節點迭代器加一個過濾器來實現的. 這表示獲取他的屬性, 如 length 的時間復雜度為 O(n), 通過 length 來遍歷整個列表需要 O(n^2). ``` var paragraphs = document.getElementsByTagName('p'); for (var i = 0; i < paragraphs.length; i++) { doSomething(paragraphs[i]); } ``` 這樣做會更好: ``` var paragraphs = document.getElementsByTagName('p'); for (var i = 0, paragraph; paragraph = paragraphs[i]; i++) { doSomething(paragraph); } ``` 這種方法對所有的 collections 和數組(只要數組不包含 falsy 值) 都適用. 在上面的例子中, 也可以通過 firstChild 和 nextSibling 來遍歷孩子節點. ``` var parentNode = document.getElementById('foo'); for (var child = parentNode.firstChild; child; child = child.nextSibling) { doSomething(child); } ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看