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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

“睡服”面试官系列第十五篇之对象的扩展(建议收藏学习)

發(fā)布時間:2023/12/10 编程问答 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 “睡服”面试官系列第十五篇之对象的扩展(建议收藏学习) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

1. 屬性的簡潔表示法

2. 屬性名表達式

3. 方法的 name 屬性

4. Object.is()

5. Object.assign()

5.1基本用法

5.2注意點

5.21.淺拷貝

5.2.2同名屬性的替換

5.2.3數(shù)組的處理

5.2.4取值函數(shù)的處理?

5.3常見用途

5.3.1為對象添加屬性

5.3.2為對象添加方法

5.3.3克隆對象

?5.3.4合并多個對象

5.3.5為屬性指定默認值

6. 屬性的可枚舉性和遍歷

6.1可枚舉性

6.2屬性的遍歷

7. Object.getOwnPropertyDescriptors()

8. __proto__ 屬性,Object.setPrototypeOf(),Object.getPrototypeOf()

8.1__proto__ 屬性

8.2Object.setPrototypeOf()

8.3Object.getPrototypeOf()

9. super 關鍵字

10. Object.keys(),Object.values(),Object.entries()

10.1Object.keys()

10.2Object.values()

10.3Object.entries

11. 對象的擴展運算符

11.1解構賦值

11.2擴展運算符

12. Null 傳導運算符

總結

“睡服“面試官系列之各系列目錄匯總(建議學習收藏)


1. 屬性的簡潔表示法

ES6 允許直接寫入變量和函數(shù),作為對象的屬性和方法。這樣的書寫更加簡潔

const foo = 'bar'; const baz = {foo}; baz // {foo: "bar"} // 等同于 const baz = {foo: foo};

上面代碼表明,ES6 允許在對象之中,直接寫變量。這時,屬性名為變量名, 屬性值為變量的值。下面是另一個例子。

function f(x, y) { return {x, y}; } // 等同于 function f(x, y) { return {x: x, y: y}; } f(1, 2) // Object {x: 1, y: 2}

除了屬性簡寫,方法也可以簡寫。

const o = { method() { return "Hello!"; } }; // 等同于 const o = { method: function() { return "Hello!"; } };

下面是一個實際的例子

let birth = '2000/01/01'; const Person = { name: '張三', //等同于birth: birth birth, // 等同于hello: function ()... hello() { console.log('我的名字是', this.name); } };

這種寫法用于函數(shù)的返回值,將會非常方便。

function getPoint() { const x = 1; const y = 10; return {x, y}; } getPoint() // {x:1, y:10}

CommonJS 模塊輸出一組變量,就非常合適使用簡潔寫法。

let ms = {}; function getItem (key) { return key in ms ? ms[key] : null; } function setItem (key, value) { ms[key] = value; } function clear () { ms = {}; } module.exports = { getItem, setItem, clear }; // 等同于 module.exports = { getItem: getItem, setItem: setItem, clear: clear };

屬性的賦值器(setter)和取值器(getter),事實上也是采用這種寫法

const cart = { _wheels: 4, get wheels () { return this._wheels; }, set wheels (value) { if (value < this._wheels) { throw new Error('數(shù)值太小了!'); } this._wheels = value; } }

注意,簡潔寫法的屬性名總是字符串,這會導致一些看上去比較奇怪的結果

const obj = { class () {} }; // 等同于 var obj = { 'class': function() {} };

上面代碼中, class 是字符串,所以不會因為它屬于關鍵字,而導致語法解析報錯。
如果某個方法的值是一個 Generator 函數(shù),前面需要加上星號。

const obj = { * m() { yield 'hello world'; } };

2. 屬性名表達式

JavaScript 定義對象的屬性,有兩種方法

// 方法一 obj.foo = true; // 方法二 obj['a' + 'bc'] = 123;

上面代碼的方法一是直接用標識符作為屬性名,方法二是用表達式作為屬性名,這時要將表達式放在方括號之內。
但是,如果使用字面量方式定義對象(使用大括號),在 ES5 中只能使用方法一(標識符)定義屬性

var obj = { foo: true, abc: 123 };

ES6 允許字面量定義對象時,用方法二(表達式)作為對象的屬性名,即把表達式放在方括號內。

let propKey = 'foo'; let obj = { [propKey]: true, ['a' + 'bc']: 123 };

下面是另一個例子。

let lastWord = 'last word'; const a = { 'first word': 'hello', [lastWord]: 'world' }; a['first word'] // "hello" a[lastWord] // "world" a['last word'] // "world"

表達式還可以用于定義方法名。

let obj = { ['h' + 'ello']() { return 'hi'; } }; obj.hello() // hi

注意,屬性名表達式與簡潔表示法,不能同時使用,會報錯。

// 報錯 const foo = 'bar'; const bar = 'abc'; const baz = { [foo] }; // 正確 const foo = 'bar'; const baz = { [foo]: 'abc'};

注意,屬性名表達式如果是一個對象,默認情況下會自動將對象轉為字符串 [object Object] ,這一點要特別小心

const keyA = {a: 1}; const keyB = {b: 2}; const myObject = { [keyA]: 'valueA', [keyB]: 'valueB' }; myObject // Object {[object Object]: "valueB"}

上面代碼中, [keyA] 和 [keyB] 得到的都是 [object Object] ,所以 [keyB] 會把 [keyA] 覆蓋掉,而 myObject 最后只有一個 [object Object] 屬性。

3. 方法的 name 屬性

函數(shù)的 name 屬性,返回函數(shù)名。對象方法也是函數(shù),因此也有 name 屬性。

const person = { sayName() { console.log('hello!'); }, }; person.sayName.name // "sayName"

上面代碼中,方法的 name 屬性返回函數(shù)名(即方法名)。
如果對象的方法使用了取值函數(shù)( getter )和存值函數(shù)( setter ),則 name 屬性不是在該方法上面,而是該方法的屬性的描述對象的 get 和 set 屬性上
面,返回值是方法名前加上 get 和 set 。

const obj = { get foo() {}, set foo(x) {} }; obj.foo.name // TypeError: Cannot read property 'name' of undefined const descriptor = Object.getOwnPropertyDescriptor(obj, 'foo'); descriptor.get.name // "get foo" descriptor.set.name // "set foo"

有兩種特殊情況: bind 方法創(chuàng)造的函數(shù), name 屬性返回 bound 加上原函數(shù)的名字; Function 構造函數(shù)創(chuàng)造的函數(shù), name 屬性返回 anonymous?

(new Function()).name // "anonymous" var doSomething = function() { // ... }; doSomething.bind().name // "bound doSomething"

如果對象的方法是一個 Symbol 值,那么 name 屬性返回的是這個 Symbol 值的描述。

const key1 = Symbol('description'); const key2 = Symbol(); let obj = { [key1]() {}, [key2]() {}, }; obj[key1].name // "[description]" obj[key2].name // ""

上面代碼中, key1 對應的 Symbol 值有描述, key2 沒有。

4. Object.is()

ES5 比較兩個值是否相等,只有兩個運算符:相等運算符( == )和嚴格相等運算符( === )。它們都有缺點,前者會自動轉換數(shù)據類型,后者的 NaN 不等
于自身,以及 +0 等于 -0 。JavaScript 缺乏一種運算,在所有環(huán)境中,只要兩個值是一樣的,它們就應該相等。
ES6 提出“Same-value equality”(同值相等)算法,用來解決這個問題。 Object.is 就是部署這個算法的新方法。它用來比較兩個值是否嚴格相等,與
嚴格比較運算符(===)的行為基本一致。

Object.is('foo', 'foo') // true Object.is({}, {}) // false

不同之處只有兩個:一是 +0 不等于 -0 ,二是 NaN 等于自身。

+0 === -0 //true NaN === NaN // false Object.is(+0, -0) // false Object.is(NaN, NaN) // true

ES5 可以通過下面的代碼,部署 Object.is 。

Object.defineProperty(Object, 'is', { value: function(x, y) { if (x === y) { // 針對+0 不等于 -0的情況 return x !== 0 || 1 / x === 1 / y; } // 針對NaN的情況 return x !== x && y !== y; }, configurable: true, enumerable: false, writable: true });

5. Object.assign()

5.1基本用法

Object.assign 方法用于對象的合并,將源對象(source)的所有可枚舉屬性,復制到目標對象(target)

const target = { a: 1 }; const source1 = { b: 2 }; const source2 = { c: 3 }; Object.assign(target, source1, source2); target // {a:1, b:2, c:3}

Object.assign 方法的第一個參數(shù)是目標對象,后面的參數(shù)都是源對象。
注意,如果目標對象與源對象有同名屬性,或多個源對象有同名屬性,則后面的屬性會覆蓋前面的屬性。

const target = { a: 1, b: 1 }; const source1 = { b: 2, c: 2 }; const source2 = { c: 3 }; Object.assign(target, source1, source2); target // {a:1, b:2, c:3}

如果只有一個參數(shù), Object.assign 會直接返回該參數(shù)

const obj = {a: 1}; Object.assign(obj) === obj // true

如果該參數(shù)不是對象,則會先轉成對象,然后返回。

typeof Object.assign(2) // "object"

由于 undefined 和 null 無法轉成對象,所以如果它們作為參數(shù),就會報錯。

Object.assign(undefined) // 報錯 Object.assign(null) // 報錯

如果非對象參數(shù)出現(xiàn)在源對象的位置(即非首參數(shù)),那么處理規(guī)則有所不同。首先,這些參數(shù)都會轉成對象,如果無法轉成對象,就會跳過。這意味
著,如果 undefined 和 null 不在首參數(shù),就不會報錯。

let obj = {a: 1}; Object.assign(obj, undefined) === obj // true Object.assign(obj, null) === obj // true

其他類型的值(即數(shù)值、字符串和布爾值)不在首參數(shù),也不會報錯。但是,除了字符串會以數(shù)組形式,拷貝入目標對象,其他值都不會產生效果

const v1 = 'abc'; const v2 = true; const v3 = 10; const obj = Object.assign({}, v1, v2, v3); console.log(obj); // { "0": "a", "1": "b", "2": "c" }

上面代碼中, v1 、 v2 、 v3 分別是字符串、布爾值和數(shù)值,結果只有字符串合入目標對象(以字符數(shù)組的形式),數(shù)值和布爾值都會被忽略。這是因為只
有字符串的包裝對象,會產生可枚舉屬性。

Object(true) // {[[PrimitiveValue]]: true} Object(10) // {[[PrimitiveValue]]: 10} Object('abc') // {0: "a", 1: "b", 2: "c", length: 3, [[PrimitiveValue]]: "abc"}

上面代碼中,布爾值、數(shù)值、字符串分別轉成對應的包裝對象,可以看到它們的原始值都在包裝對象的內部屬性 [[PrimitiveValue]] 上面,這個屬性是不
會被 Object.assign 拷貝的。只有字符串的包裝對象,會產生可枚舉的實義屬性,那些屬性則會被拷貝。
Object.assign 拷貝的屬性是有限制的,只拷貝源對象的自身屬性(不拷貝繼承屬性),也不拷貝不可枚舉的屬性( enumerable: false )

Object.assign({b: 'c'}, Object.defineProperty({}, 'invisible', { enumerable: false, value: 'hello' }) ) // { b: 'c' }

上面代碼中, Object.assign 要拷貝的對象只有一個不可枚舉屬性 invisible ,這個屬性并沒有被拷貝進去。

屬性名為 Symbol 值的屬性,也會被 Object.assign 拷貝

Object.assign({ a: 'b' }, { [Symbol('c')]: 'd' }) // { a: 'b', Symbol(c): 'd' }

5.2注意點

5.21.淺拷貝

Object.assign 方法實行的是淺拷貝,而不是深拷貝。也就是說,如果源對象某個屬性的值是對象,那么目標對象拷貝得到的是這個對象的引用

const obj1 = {a: {b: 1}}; const obj2 = Object.assign({}, obj1); obj1.a.b = 2; obj2.a.b // 2

上面代碼中,源對象 obj1 的 a 屬性的值是一個對象, Object.assign 拷貝得到的是這個對象的引用。這個對象的任何變化,都會反映到目標對象上面。

5.2.2同名屬性的替換

對于這種嵌套的對象,一旦遇到同名屬性, Object.assign 的處理方法是替換,而不是添加。

const target = { a: { b: 'c', d: 'e' } } const source = { a: { b: 'hello' } } Object.assign(target, source) // { a: { b: 'hello' } }

上面代碼中, target 對象的 a 屬性被 source 對象的 a 屬性整個替換掉了,而不會得到 { a: { b: 'hello', d: 'e' } } 的結果。這通常不是開發(fā)者想要
的,需要特別小心。
一些函數(shù)庫提供 Object.assign 的定制版本(比如 Lodash 的 _.defaultsDeep 方法),可以得到深拷貝的合并

5.2.3數(shù)組的處理

Object.assign 可以用來處理數(shù)組,但是會把數(shù)組視為對象。

Object.assign([1, 2, 3], [4, 5]) // [4, 5, 3]

上面代碼中, Object.assign 把數(shù)組視為屬性名為 0、1、2 的對象,因此源數(shù)組的 0 號屬性 4 覆蓋了目標數(shù)組的 0 號屬性 1?

5.2.4取值函數(shù)的處理?

Object.assign 只能進行值的復制,如果要復制的值是一個取值函數(shù),那么將求值后再復制。

const source = { get foo() { return 1 } }; const target = {}; Object.assign(target, source) // { foo: 1 }

上面代碼中, source 對象的 foo 屬性是一個取值函數(shù), Object.assign 不會復制這個取值函數(shù),只會拿到值以后,將這個值復制過去

5.3常見用途

Object.assign 方法有很多用處。

5.3.1為對象添加屬性

class Point { constructor(x, y) { Object.assign(this, {x, y}); } }

上面方法通過 Object.assign 方法,將 x 屬性和 y 屬性添加到 Point 類的對象實例。

5.3.2為對象添加方法

Object.assign(SomeClass.prototype, { someMethod(arg1, arg2) { ··· }, anotherMethod() { ··· } }); // 等同于下面的寫法 SomeClass.prototype.someMethod = function (arg1, arg2) { ··· }; SomeClass.prototype.anotherMethod = function () { ··· };

上面代碼使用了對象屬性的簡潔表示法,直接將兩個函數(shù)放在大括號中,再使用 assign 方法添加到 SomeClass.prototype 之中。

5.3.3克隆對象

function clone(origin) { return Object.assign({}, origin); }

上面代碼將原始對象拷貝到一個空對象,就得到了原始對象的克隆。
不過,采用這種方法克隆,只能克隆原始對象自身的值,不能克隆它繼承的值。如果想要保持繼承鏈,可以采用下面的代碼。

function clone(origin) { let originProto = Object.getPrototypeOf(origin); return Object.assign(Object.create(originProto), origin); }

?5.3.4合并多個對象

將多個對象合并到某個對象。

const merge = (target, ...sources) => Object.assign(target, ...sources);

如果希望合并后返回一個新對象,可以改寫上面函數(shù),對一個空對象合并。

const merge = (...sources) => Object.assign({}, ...sources);

5.3.5為屬性指定默認值

]

const DEFAULTS = { logLevel: 0, outputFormat: 'html' }; function processContent(options) { options = Object.assign({}, DEFAULTS, options); console.log(options); // ... }

上面代碼中, DEFAULTS 對象是默認值, options 對象是用戶提供的參數(shù)。 Object.assign 方法將 DEFAULTS 和 options 合并成一個新對象,如果兩者有同
名屬性,則 option 的屬性值會覆蓋 DEFAULTS 的屬性值。
注意,由于存在淺拷貝的問題, DEFAULTS 對象和 options 對象的所有屬性的值,最好都是簡單類型,不要指向另一個對象。否則, DEFAULTS 對象的該屬
性很可能不起作用。

const DEFAULTS = { url: { host: 'example.com', port: 7070 }, }; processContent({ url: {port: 8000} }) // { // url: {port: 8000} // }

上面代碼的原意是將 url.port 改成 8000, url.host 不變。實際結果卻是 options.url 覆蓋掉 DEFAULTS.url ,所以 url.host 就不存在了。

6. 屬性的可枚舉性和遍歷

6.1可枚舉性

對象的每個屬性都有一個描述對象(Descriptor),用來控制該屬性的行為。 Object.getOwnPropertyDescriptor 方法可以獲取該屬性的描述對象。

let obj = { foo: 123 }; Object.getOwnPropertyDescriptor(obj, 'foo') // { // value: 123, // writable: true, // enumerable: true, // configurable: true // }

描述對象的 enumerable 屬性,稱為”可枚舉性“,如果該屬性為 false ,就表示某些操作會忽略當前屬性。
目前,有四個操作會忽略 enumerable 為 false 的屬性。
for...in 循環(huán):只遍歷對象自身的和繼承的可枚舉的屬性。
Object.keys() :返回對象自身的所有可枚舉的屬性的鍵名。
JSON.stringify() :只串行化對象自身的可枚舉的屬性。
Object.assign() : 忽略 enumerable 為 false 的屬性,只拷貝對象自身的可枚舉的屬性。
這四個操作之中,前三個是 ES5 就有的,最后一個 Object.assign() 是 ES6 新增的。其中,只有 for...in 會返回繼承的屬性,其他三個方法都會忽略
繼承的屬性,只處理對象自身的屬性。實際上,引入“可枚舉”( enumerable )這個概念的最初目的,就是讓某些屬性可以規(guī)避掉 for...in 操作,不然所
有內部屬性和方法都會被遍歷到。比如,對象原型的 toString 方法,以及數(shù)組的 length 屬性,就通過“可枚舉性”,從而避免被 for...in 遍歷到。

Object.getOwnPropertyDescriptor(Object.prototype, 'toString').enumerable // false Object.getOwnPropertyDescriptor([], 'length').enumerable // false

上面代碼中, toString 和 length 屬性的 enumerable 都是 false ,因此 for...in 不會遍歷到這兩個繼承自原型的屬性。
另外,ES6 規(guī)定,所有 Class 的原型的方法都是不可枚舉的。

Object.getOwnPropertyDescriptor(class {foo() {}}.prototype, 'foo').enumerable // false

總的來說,操作中引入繼承的屬性會讓問題復雜化,大多數(shù)時候,我們只關心對象自身的屬性。所以,盡量不要用 for...in 循環(huán),而用 Object.keys() 代
替。

6.2屬性的遍歷

ES6 一共有 5 種方法可以遍歷對象的屬性。
(1)for...in
for...in 循環(huán)遍歷對象自身的和繼承的可枚舉屬性(不含 Symbol 屬性)。
(2)Object.keys(obj)
Object.keys 返回一個數(shù)組,包括對象自身的(不含繼承的)所有可枚舉屬性(不含 Symbol 屬性)的鍵名。
(3)Object.getOwnPropertyNames(obj)

Object.getOwnPropertyNames 返回一個數(shù)組,包含對象自身的所有屬性(不含 Symbol 屬性,但是包括不可枚舉屬性)的鍵名。
(4)Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols 返回一個數(shù)組,包含對象自身的所有 Symbol 屬性的鍵名。
(5)Reflect.ownKeys(obj)
Reflect.ownKeys 返回一個數(shù)組,包含對象自身的所有鍵名,不管鍵名是 Symbol 或字符串,也不管是否可枚舉。
以上的 5 種方法遍歷對象的鍵名,都遵守同樣的屬性遍歷的次序規(guī)則。
首先遍歷所有數(shù)值鍵,按照數(shù)值升序排列。
其次遍歷所有字符串鍵,按照加入時間升序排列。
最后遍歷所有 Symbol 鍵,按照加入時間升序排列。

Reflect.ownKeys({ [Symbol()]:0, b:0, 10:0, 2:0, a:0 }) // ['2', '10', 'b', 'a', Symbol()]

上面代碼中, Reflect.ownKeys 方法返回一個數(shù)組,包含了參數(shù)對象的所有屬性。這個數(shù)組的屬性次序是這樣的,首先是數(shù)值屬性 2 和 10 ,其次是字符串
屬性 b 和 a ,最后是 Symbol 屬性。

7. Object.getOwnPropertyDescriptors()

前面說過, Object.getOwnPropertyDescriptor 方法會返回某個對象屬性的描述對象(descriptor)。ES2017 引入了
Object.getOwnPropertyDescriptors 方法,返回指定對象所有自身屬性(非繼承屬性)的描述對象。

const obj = { foo: 123, get bar() { return 'abc' } }; Object.getOwnPropertyDescriptors(obj) // { foo: // { value: 123, // writable: true, // enumerable: true, // configurable: true }, // bar: // { get: [Function: bar], // set: undefined, // enumerable: true, // configurable: true } }

上面代碼中, Object.getOwnPropertyDescriptors 方法返回一個對象,所有原對象的屬性名都是該對象的屬性名,對應的屬性值就是該屬性的描述對象。
該方法的實現(xiàn)非常容易。

function getOwnPropertyDescriptors(obj) { const result = {}; for (let key of Reflect.ownKeys(obj)) { result[key] = Object.getOwnPropertyDescriptor(obj, key); } return result; }

該方法的引入目的,主要是為了解決 Object.assign() 無法正確拷貝 get 屬性和 set 屬性的問題。

const source = { set foo(value) { console.log(value); } }; const target1 = {}; Object.assign(target1, source); Object.getOwnPropertyDescriptor(target1, 'foo') // { value: undefined, // writable: true, // enumerable: true, // configurable: true }

上面代碼中, source 對象的 foo 屬性的值是一個賦值函數(shù), Object.assign 方法將這個屬性拷貝給 target1 對象,結果該屬性的值變成了 undefined 。這
是因為 Object.assign 方法總是拷貝一個屬性的值,而不會拷貝它背后的賦值方法或取值方法。
這時, Object.getOwnPropertyDescriptors 方法配合 Object.defineProperties 方法,就可以實現(xiàn)正確拷貝。

const source = { set foo(value) { console.log(value); } }; const target2 = {}; Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source)); Object.getOwnPropertyDescriptor(target2, 'foo') // { get: undefined, // set: [Function: foo], // enumerable: true, // configurable: true }

上面代碼中,兩個對象合并的邏輯可以寫成一個函數(shù)。

const shallowMerge = (target, source) => Object.defineProperties( target, Object.getOwnPropertyDescriptors(source) );

Object.getOwnPropertyDescriptors 方法的另一個用處,是配合 Object.create 方法,將對象屬性克隆到一個新對象。這屬于淺拷貝。

const clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj)); // 或者 const shallowClone = (obj) => Object.create( Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj) );

上面代碼會克隆對象 obj 。
另外, Object.getOwnPropertyDescriptors 方法可以實現(xiàn)一個對象繼承另一個對象。以前,繼承另一個對象,常常寫成下面這樣

const obj = { __proto__: prot, foo: 123, };

ES6 規(guī)定 __proto__ 只有瀏覽器要部署,其他環(huán)境不用部署。如果去除 __proto__ ,上面代碼就要改成下面這樣。

const obj = Object.create(prot); obj.foo = 123; // 或者 const obj = Object.assign( Object.create(prot), { foo: 123, } );

有了 Object.getOwnPropertyDescriptors ,我們就有了另一種寫法

const obj = Object.create( prot, Object.getOwnPropertyDescriptors({ foo: 123, }) );

Object.getOwnPropertyDescriptors 也可以用來實現(xiàn) Mixin(混入)模式

let mix = (object) => ({ with: (...mixins) => mixins.reduce( (c, mixin) => Object.create( c, Object.getOwnPropertyDescriptors(mixin) ), object) }); // multiple mixins example let a = {a: 'a'}; let b = {b: 'b'}; let c = {c: 'c'}; let d = mix(c).with(a, b); d.c // "c" d.b // "b" d.a // "a"

上面代碼返回一個新的對象 d ,代表了對象 a 和 b 被混入了對象 c 的操作。
出于完整性的考慮, Object.getOwnPropertyDescriptors 進入標準以后,以后還會新增 Reflect.getOwnPropertyDescriptors 方法。

8. __proto__ 屬性,Object.setPrototypeOf(),Object.getPrototypeOf()

JavaScript 語言的對象繼承是通過原型鏈實現(xiàn)的。ES6 提供了更多原型對象的操作方法

8.1__proto__ 屬性

__proto__ 屬性(前后各兩個下劃線),用來讀取或設置當前對象的 prototype 對象。目前,所有瀏覽器(包括 IE11)都部署了這個屬性。

// es6 的寫法 const obj = { method: function() { ... } }; obj.__proto__ = someOtherObj; // es5 的寫法 var obj = Object.create(someOtherObj); obj.method = function() { ... };

該屬性沒有寫入 ES6 的正文,而是寫入了附錄,原因是 __proto__ 前后的雙下劃線,說明它本質上是一個內部屬性,而不是一個正式的對外的 API,只是
由于瀏覽器廣泛支持,才被加入了 ES6。標準明確規(guī)定,只有瀏覽器必須部署這個屬性,其他運行環(huán)境不一定需要部署,而且新的代碼最好認為這個屬性
是不存在的。因此,無論從語義的角度,還是從兼容性的角度,都不要使用這個屬性,而是使用下面的 Object.setPrototypeOf() (寫操作)、
Object.getPrototypeOf() (讀操作)、 Object.create() (生成操作)代替。
實現(xiàn)上, __proto__ 調用的是 Object.prototype.__proto__ ,具體實現(xiàn)如下

Object.defineProperty(Object.prototype, '__proto__', { get() { let _thisObj = Object(this); return Object.getPrototypeOf(_thisObj); }, set(proto) { if (this === undefined || this === null) { throw new TypeError(); } if (!isObject(this)) { return undefined; } if (!isObject(proto)) { return undefined; } let status = Reflect.setPrototypeOf(this, proto); if (!status) { throw new TypeError(); } }, }); function isObject(value) { return Object(value) === value; }

如果一個對象本身部署了 __proto__ 屬性,該屬性的值就是對象的原型

Object.getPrototypeOf({ __proto__: null }) // null

8.2Object.setPrototypeOf()

Object.setPrototypeOf 方法的作用與 __proto__ 相同,用來設置一個對象的 prototype 對象,返回參數(shù)對象本身。它是 ES6 正式推薦的設置原型對象
的方法。

// 格式 Object.setPrototypeOf(object, prototype) // 用法 const o = Object.setPrototypeOf({}, null);

該方法等同于下面的函數(shù)。

function (obj, proto) { obj.__proto__ = proto; return obj; }

下面是一個例子

let proto = {}; let obj = { x: 10 }; Object.setPrototypeOf(obj, proto); proto.y = 20; proto.z = 40; obj.x // 10 obj.y // 20 obj.z // 40

上面代碼將 proto 對象設為 obj 對象的原型,所以從 obj 對象可以讀取 proto 對象的屬性。
如果第一個參數(shù)不是對象,會自動轉為對象。但是由于返回的還是第一個參數(shù),所以這個操作不會產生任何效果。

Object.setPrototypeOf(1, {}) === 1 // true Object.setPrototypeOf('foo', {}) === 'foo' // true Object.setPrototypeOf(true, {}) === true // true

由于 undefined 和 null 無法轉為對象,所以如果第一個參數(shù)是 undefined 或 null ,就會報錯。

Object.setPrototypeOf(undefined, {}) // TypeError: Object.setPrototypeOf called on null or undefined Object.setPrototypeOf(null, {}) // TypeError: Object.setPrototypeOf called on null or undefined

8.3Object.getPrototypeOf()

該方法與 Object.setPrototypeOf 方法配套,用于讀取一個對象的原型對象。

Object.getPrototypeOf(obj);

下面是一個例子。

function Rectangle() { // ... } const rec = new Rectangle(); Object.getPrototypeOf(rec) === Rectangle.prototype // true Object.setPrototypeOf(rec, Object.prototype); Object.getPrototypeOf(rec) === Rectangle.prototype // false

如果參數(shù)不是對象,會被自動轉為對象

// 等同于 Object.getPrototypeOf(Number(1)) Object.getPrototypeOf(1) // Number {[[PrimitiveValue]]: 0} // 等同于 Object.getPrototypeOf(String('foo')) Object.getPrototypeOf('foo') // String {length: 0, [[PrimitiveValue]]: ""} // 等同于 Object.getPrototypeOf(Boolean(true)) Object.getPrototypeOf(true) // Boolean {[[PrimitiveValue]]: false} Object.getPrototypeOf(1) === Number.prototype // true Object.getPrototypeOf('foo') === String.prototype // true Object.getPrototypeOf(true) === Boolean.prototype // true

如果參數(shù)是 undefined 或 null ,它們無法轉為對象,所以會報錯

Object.getPrototypeOf(null) // TypeError: Cannot convert undefined or null to object Object.getPrototypeOf(undefined) // TypeError: Cannot convert undefined or null to object

9. super 關鍵字

我們知道, this 關鍵字總是指向函數(shù)所在的當前對象,ES6 又新增了另一個類似的關鍵字 super ,指向當前對象的原型對象。

const proto = { foo: 'hello' }; const obj = { find() { return super.foo; } }; Object.setPrototypeOf(obj, proto); obj.find() // "hello"

上面代碼中,對象 obj 的 find 方法之中,通過 super.foo 引用了原型對象 proto 的 foo 屬性。
注意, super 關鍵字表示原型對象時,只能用在對象的方法之中,用在其他地方都會報錯。

// 報錯 const obj = { foo: super.foo } // 報錯 const obj = { foo: () => super.foo } // 報錯 const obj = { foo: function () { return super.foo } }

上面三種 super 的用法都會報錯,因為對于 JavaScript 引擎來說,這里的 super 都沒有用在對象的方法之中。第一種寫法是 super 用在屬性里面,第二
種和第三種寫法是 super 用在一個函數(shù)里面,然后賦值給 foo 屬性。目前,只有對象方法的簡寫法可以讓 JavaScript 引擎確認,定義的是對象的方法。
JavaScript 引擎內部, super.foo 等同于 Object.getPrototypeOf(this).foo (屬性)或 Object.getPrototypeOf(this).foo.call(this) (方法)

const proto = { x: 'hello', foo() { console.log(this.x); }, }; const obj = { x: 'world', foo() { super.foo(); } } Object.setPrototypeOf(obj, proto); obj.foo() // "world"

?上面代碼中, super.foo 指向原型對象 proto 的 foo 方法,但是綁定的 this 卻還是當前對象 obj ,因此輸出的就是 world

10. Object.keys(),Object.values(),Object.entries()

10.1Object.keys()

ES5 引入了 Object.keys 方法,返回一個數(shù)組,成員是參數(shù)對象自身的(不含繼承的)所有可遍歷(enumerable)屬性的鍵名。

var obj = { foo: 'bar', baz: 42 }; Object.keys(obj) // ["foo", "baz"]

ES2017 引入了跟 Object.keys 配套的 Object.values 和 Object.entries ,作為遍歷一個對象的補充手段,供 for...of 循環(huán)使用。

let {keys, values, entries} = Object; let obj = { a: 1, b: 2, c: 3 }; for (let key of keys(obj)) { console.log(key); // 'a', 'b', 'c' } for (let value of values(obj)) { console.log(value); // 1, 2, 3 } for (let [key, value] of entries(obj)) { console.log([key, value]); // ['a', 1], ['b', 2], ['c', 3]

10.2Object.values()

Object.values 方法返回一個數(shù)組,成員是參數(shù)對象自身的(不含繼承的)所有可遍歷(enumerable)屬性的鍵值

const obj = { foo: 'bar', baz: 42 }; Object.values(obj) // ["bar", 42]

返回數(shù)組的成員順序,與本章的《屬性的遍歷》部分介紹的排列規(guī)則一致。

const obj = { 100: 'a', 2: 'b', 7: 'c' }; Object.values(obj) // ["b", "c", "a"]

上面代碼中,屬性名為數(shù)值的屬性,是按照數(shù)值大小,從小到大遍歷的,因此返回的順序是 b 、 c 、 a 。
Object.values 只返回對象自身的可遍歷屬性

const obj = Object.create({}, {p: {value: 42}}); Object.values(obj) // []

上面代碼中, Object.create 方法的第二個參數(shù)添加的對象屬性(屬性 p ),如果不顯式聲明,默認是不可遍歷的,因為 p 的屬性描述對象的 enumerable
默認是 false , Object.values 不會返回這個屬性。只要把 enumerable 改成 true , Object.values 就會返回屬性 p 的值。

const obj = Object.create({}, {p: { value: 42, enumerable: true } }); Object.values(obj) // [42]

Object.values 會過濾屬性名為 Symbol 值的屬性。

Object.values({ [Symbol()]: 123, foo: 'abc' }); // ['abc']

如果 Object.values 方法的參數(shù)是一個字符串,會返回各個字符組成的一個數(shù)組。

Object.values('foo') // ['f', 'o', 'o']

上面代碼中,字符串會先轉成一個類似數(shù)組的對象。字符串的每個字符,就是該對象的一個屬性。因此, Object.values 返回每個屬性的鍵值,就是各個
字符組成的一個數(shù)組。
如果參數(shù)不是對象, Object.values 會先將其轉為對象。由于數(shù)值和布爾值的包裝對象,都不會為實例添加非繼承的屬性。所以, Object.values 會返回
空數(shù)組。

Object.values(42) // [] Object.values(true) // []

10.3Object.entries

Object.entries 方法返回一個數(shù)組,成員是參數(shù)對象自身的(不含繼承的)所有可遍歷(enumerable)屬性的鍵值對數(shù)組。

const obj = { foo: 'bar', baz: 42 }; Object.entries(obj) // [ ["foo", "bar"], ["baz", 42] ]

除了返回值不一樣,該方法的行為與 Object.values 基本一致。
如果原對象的屬性名是一個 Symbol 值,該屬性會被忽略。

Object.entries({ [Symbol()]: 123, foo: 'abc' }); // [ [ 'foo', 'abc' ] ]

上面代碼中,原對象有兩個屬性, Object.entries 只輸出屬性名非 Symbol 值的屬性。將來可能會有 Reflect.ownEntries() 方法,返回對象自身的所有
屬性。
Object.entries 的基本用途是遍歷對象的屬性

let obj = { one: 1, two: 2 }; for (let [k, v] of Object.entries(obj)) { console.log( `${JSON.stringify(k)}: ${JSON.stringify(v)}` ); } // "one": 1 // "two": 2

Object.entries 方法的另一個用處是,將對象轉為真正的 Map 結構。

const obj = { foo: 'bar', baz: 42 }; const map = new Map(Object.entries(obj)); map // Map { foo: "bar", baz: 42 }

自己實現(xiàn) Object.entries 方法,非常簡單。

// Generator函數(shù)的版本 function* entries(obj) { for (let key of Object.keys(obj)) { yield [key, obj[key]]; } } // 非Generator函數(shù)的版本 function entries(obj) { let arr = []; for (let key of Object.keys(obj)) { arr.push([key, obj[key]]); } return arr; }

11. 對象的擴展運算符

擴展運算符( ... )。

const [a, ...b] = [1, 2, 3]; a // 1 b // [2, 3]

ES2017 將這個運算符引入了對象。

11.1解構賦值

對象的解構賦值用于從一個對象取值,相當于將所有可遍歷的、但尚未被讀取的屬性,分配到指定的對象上面。所有的鍵和它們的值,都會拷貝到新對象
上面。

let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }; x // 1 y // 2 z // { a: 3, b: 4 }

上面代碼中,變量 z 是解構賦值所在的對象。它獲取等號右邊的所有尚未讀取的鍵( a 和 b ),將它們連同值一起拷貝過來。
由于解構賦值要求等號右邊是一個對象,所以如果等號右邊是 undefined 或 null ,就會報錯,因為它們無法轉為對象

let { x, y, ...z } = null; // 運行時錯誤 let { x, y, ...z } = undefined; // 運行時錯誤

解構賦值必須是最后一個參數(shù),否則會報錯。

let { ...x, y, z } = obj; // 句法錯誤 let { x, ...y, ...z } = obj; // 句法錯誤

上面代碼中,解構賦值不是最后一個參數(shù),所以會報錯。
注意,解構賦值的拷貝是淺拷貝,即如果一個鍵的值是復合類型的值(數(shù)組、對象、函數(shù))、那么解構賦值拷貝的是這個值的引用,而不是這個值的副
本。

let obj = { a: { b: 1 } }; let { ...x } = obj; obj.a.b = 2; x.a.b // 2

上面代碼中, x 是解構賦值所在的對象,拷貝了對象 obj 的 a 屬性。 a 屬性引用了一個對象,修改這個對象的值,會影響到解構賦值對它的引用。
另外,擴展運算符的解構賦值,不能復制繼承自原型對象的屬性。

let o1 = { a: 1 }; let o2 = { b: 2 }; o2.__proto__ = o1; let { ...o3 } = o2; o3 // { b: 2 } o3.a // undefined

上面代碼中,對象 o3 復制了 o2 ,但是只復制了 o2 自身的屬性,沒有復制它的原型對象 o1 的屬性。
下面是另一個例子。

const o = Object.create({ x: 1, y: 2 }); o.z = 3; let { x, ...{ y, z } } = o; x // 1 y // undefined z // 3

上面代碼中,變量 x 是單純的解構賦值,所以可以讀取對象 o 繼承的屬性;變量 y 和 z 是擴展運算符的解構賦值,只能讀取對象 o 自身的屬性,所以變量 z
可以賦值成功,變量 y 取不到值

解構賦值的一個用處,是擴展某個函數(shù)的參數(shù),引入其他操作。

function baseFunction({ a, b }) { // ... } function wrapperFunction({ x, y, ...restConfig }) { // 使用x和y參數(shù)進行操作 // 其余參數(shù)傳給原始函數(shù) return baseFunction(restConfig); }

上面代碼中,原始函數(shù) baseFunction 接受 a 和 b 作為參數(shù),函數(shù) wrapperFunction 在 baseFunction 的基礎上進行了擴展,能夠接受多余的參數(shù),并且保
留原始函數(shù)的行為。

11.2擴展運算符

擴展運算符( ... )用于取出參數(shù)對象的所有可遍歷屬性,拷貝到當前對象之中。

let z = { a: 3, b: 4 }; let n = { ...z }; n // { a: 3, b: 4 }

這等同于使用 Object.assign 方法。

let aClone = { ...a }; // 等同于 let aClone = Object.assign({}, a);

上面的例子只是拷貝了對象實例的屬性,如果想完整克隆一個對象,還拷貝對象原型的屬性,可以采用下面的寫法。

// 寫法一 const clone1 = { __proto__: Object.getPrototypeOf(obj), ...obj }; // 寫法二 const clone2 = Object.assign( Object.create(Object.getPrototypeOf(obj)), obj ); // 寫法三 const clone3 = Object.create( Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj) )

上面代碼中,寫法一的 __proto__ 屬性在非瀏覽器的環(huán)境不一定部署,因此推薦使用寫法二和寫法三。
擴展運算符可以用于合并兩個對象
?

let ab = { ...a, ...b }; // 等同于 let ab = Object.assign({}, a, b);

如果用戶自定義的屬性,放在擴展運算符后面,則擴展運算符內部的同名屬性會被覆蓋掉。

let aWithOverrides = { ...a, x: 1, y: 2 }; // 等同于 let aWithOverrides = { ...a, ...{ x: 1, y: 2 } }; // 等同于 let x = 1, y = 2, aWithOverrides = { ...a, x, y }; // 等同于 let aWithOverrides = Object.assign({}, a, { x: 1, y: 2 });

上面代碼中, a 對象的 x 屬性和 y 屬性,拷貝到新對象后會被覆蓋掉。
這用來修改現(xiàn)有對象部分的屬性就很方便了

let newVersion = { ...previousVersion, name: 'New Name' // Override the name property };

上面代碼中, newVersion 對象自定義了 name 屬性,其他屬性全部復制自 previousVersion 對象。

如果把自定義屬性放在擴展運算符前面,就變成了設置新對象的默認屬性值

let aWithDefaults = { x: 1, y: 2, ...a }; // 等同于 let aWithDefaults = Object.assign({}, { x: 1, y: 2 }, a); // 等同于 let aWithDefaults = Object.assign({ x: 1, y: 2 }, a);

與數(shù)組的擴展運算符一樣,對象的擴展運算符后面可以跟表達式

const obj = { ...(x > 1 ? {a: 1} : {}), b: 2, };

如果擴展運算符后面是一個空對象,則沒有任何效果。

{...{}, a: 1} // { a: 1 }

如果擴展運算符的參數(shù)是 null 或 undefined ,這兩個值會被忽略,不會報錯

let emptyObject = { ...null, ...undefined }; // 不報錯

擴展運算符的參數(shù)對象之中,如果有取值函數(shù) get ,這個函數(shù)是會執(zhí)行的

// 并不會拋出錯誤,因為 x 屬性只是被定義,但沒執(zhí)行 let aWithXGetter = { ...a, get x() { throw new Error('not throw yet'); } }; // 會拋出錯誤,因為 x 屬性被執(zhí)行了 let runtimeError = { ...a, ...{ get x() { throw new Error('throw now'); } } };

12. Null 傳導運算符

編程實務中,如果讀取對象內部的某個屬性,往往需要判斷一下該對象是否存在。比如,要讀取 message.body.user.firstName ,安全的寫法是寫成下面
這樣。

const firstName = (message && message.body && message.body.user && message.body.user.firstName) || 'default';

這樣的層層判斷非常麻煩,因此現(xiàn)在有一個提案,引入了“Null 傳導運算符”(null propagation operator) ?. ,簡化上面的寫法。

const firstName = message?.body?.user?.firstName || 'default'

上面代碼有三個 ?. 運算符,只要其中一個返回 null 或 undefined ,就不再往下運算,而是返回 undefined 。
“Null 傳導運算符”有四種用法。
obj?.prop // 讀取對象屬性
obj?.[expr] // 同上
func?.(...args) // 函數(shù)或對象方法的調用
new C?.(...args) // 構造函數(shù)的調用
傳導運算符之所以寫成 obj?.prop ,而不是 obj?prop ,是為了方便編譯器能夠區(qū)分三元運算符 ?: (比如 obj?prop:123 )。
下面是更多的例子

// 如果 a 是 null 或 undefined, 返回 undefined // 否則返回 a.b.c().d a?.b.c().d // 如果 a 是 null 或 undefined,下面的語句不產生任何效果 // 否則執(zhí)行 a.b = 42 a?.b = 42 // 如果 a 是 null 或 undefined,下面的語句不產生任何效果 delete a?.

總結

本博客源于本人閱讀相關書籍和視頻總結,創(chuàng)作不易,謝謝點贊支持。學到就是賺到。我是歌謠,勵志成為一名優(yōu)秀的技術革新人員。

歡迎私信交流,一起學習,一起成長。

推薦鏈接 其他文件目錄參照

“睡服“面試官系列之各系列目錄匯總(建議學習收藏)

?

?

總結

以上是生活随笔為你收集整理的“睡服”面试官系列第十五篇之对象的扩展(建议收藏学习)的全部內容,希望文章能夠幫你解決所遇到的問題。

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

国产精品不卡在线 | 天天操天天能 | 国产午夜精品理论片在线 | 欧美人人爱| 97超视频在线观看 | 4p变态网欧美系列 | 久久综合影视 | 亚洲视频播放 | 天天射日 | 国产精品美女毛片真酒店 | 久久久综合香蕉尹人综合网 | 国产xvideos免费视频播放 | 国产一区二区三精品久久久无广告 | 国产一区二区高清视频 | 成人免费一级片 | 青草视频在线播放 | 免费视频在线观看网站 | 久久国产视屏 | 久久久久黄 | 欧美最爽乱淫视频播放 | 日韩精品视频在线免费观看 | 激情av一区二区 | 成人va视频 | 久久一级片 | 精品国产成人av | 国产97色 | 国产精品人人做人人爽人人添 | 久久免费中文视频 | 免费网站在线观看人 | 片黄色毛片黄色毛片 | 久久综合五月天婷婷伊人 | 美女视频久久 | 国产欧美在线一区二区三区 | 色久天| 国产精品自产拍在线观看网站 | 视频三区在线 | 国色天香在线 | 狠狠躁夜夜a产精品视频 | 中文字幕之中文字幕 | 国产午夜精品久久久久久久久久 | 国产精品s色| 久久人人爽人人 | 日韩免费三区 | 国产区高清在线 | 久久免费视频99 | 国产精品四虎 | 免费av在线网 | 日本中文在线观看 | 国产福利一区二区三区视频 | 国产一区不卡在线 | 婷婷av电影 | 色就是色综合 | 色播五月激情五月 | 久久久久久国产精品999 | 久久免费中文视频 | 在线观看免费观看在线91 | 久草在线最新免费 | 亚洲少妇xxxx| 亚洲码国产日韩欧美高潮在线播放 | 国产丝袜一区二区三区 | 久久国产影视 | 99久久精品一区二区成人 | 五月婷婷色播 | 国产69熟| 亚洲永久精品视频 | 国产免费观看久久 | 五月婷婷.com | 日韩视频中文字幕在线观看 | 日日夜夜精品免费观看 | 激情综合网五月婷婷 | 久久不卡日韩美女 | 国产91粉嫩白浆在线观看 | 国产黄色一级片在线 | 99久久精品国产观看 | 日韩啪视频 | 在线观看激情av | 91日韩精品一区 | 天天综合导航 | 久久久久久久久久久久久9999 | 成人久久免费 | 一区二区久久 | 亚洲韩国一区二区三区 | 91资源在线播放 | 色婷婷激情电影 | 天天爽综合网 | 天天色天天射综合网 | av片在线看 | 91av在线视频免费观看 | 亚洲精品乱码久久久久久蜜桃欧美 | 日韩在线观看三区 | 五月婷婷开心中文字幕 | 国产美女黄网站免费 | 亚洲干 | 久久成人毛片 | 国产精品免费在线视频 | 99av在线视频 | 麻豆系列在线观看 | 国产精品女人久久久久久 | 欧美午夜剧场 | 中文免费观看 | 1024在线看片 | 中文视频在线看 | 五月婷婷激情六月 | 精品国产自在精品国产精野外直播 | 久久久久欠精品国产毛片国产毛生 | 97视频免费播放 | 国产精品久久久久久久久久久久午夜 | 欧美成人69av | 在线观看www. | 精品国产色 | 激情欧美一区二区三区 | 欧美日韩不卡一区二区三区 | 亚洲精品三级 | 在线之家免费在线观看电影 | 99看视频在线观看 | 成人永久在线 | 99精品欧美一区二区三区 | 久久久久国产精品一区二区 | 激情伊人五月天久久综合 | 在线看片一区 | 91亚洲视频在线观看 | 成年人在线免费视频观看 | 婷婷色站| 久久曰视频 | 国产精品美女久久久久久久网站 | 一区二区三区在线免费播放 | 日韩在线免费电影 | 在线一区av | 中文字幕在线看 | 91传媒激情理伦片 | 中文在线字幕观看电影 | 久久精品二区 | 亚洲女人天堂成人av在线 | 国产精品婷婷 | 久久综合色婷婷 | 亚洲精品在线免费 | 中文字幕永久 | 久久久99精品免费观看app | 婷香五月 | 国产精品久久网 | 国产精品美女免费看 | 91最新国产| 国产一二三四在线观看视频 | 少妇高潮冒白浆 | 私人av| 香蕉视频网址 | 日本久久免费视频 | 欧美性粗大hdvideo | 一区二区三区精品在线视频 | 三级大片网站 | 91视频国产高清 | 99精品视频在线观看 | 国产一级片一区二区三区 | 一级黄色电影网站 | 欧美-第1页-屁屁影院 | 亚洲精品网址在线观看 | 丁香婷婷在线 | 国产在线一区二区 | 日日夜夜狠狠干 | www国产亚洲 | 亚洲精品永久免费视频 | 98涩涩国产露脸精品国产网 | 色网站黄| 亚洲视频综合 | 在线免费观看国产 | 99re中文字幕 | 激情五月婷婷综合网 | 欧美天堂久久 | 日本黄色大片免费 | 在线精品国产 | 一级a性色生活片久久毛片波多野 | 久草在线最新 | 成人国产网址 | 亚洲一区动漫 | 久久久国产毛片 | 亚洲免费精品视频 | 青春草免费在线视频 | 久久久久久久久久免费 | 国产999精品 | 日本在线观看一区二区三区 | 99热最新 | 欧美精品亚洲精品 | 色综合激情网 | 中文字幕专区高清在线观看 | 激情视频区| 欧美尹人 | 99热最新地址 | 日韩精品在线观看视频 | 国产黄色片在线 | 五月婷社区 | 成人永久视频 | 欧美日韩国产二区三区 | 在线免费看黄色 | 2023国产精品自产拍在线观看 | 中文不卡视频 | 免费av小说 | 97国产人人 | 精品专区一区二区 | 久久国产精品99精国产 | 精品一区精品二区高清 | 亚洲欧美视频在线播放 | 米奇狠狠狠888 | 成人国产综合 | 国产偷在线 | 日本一区二区三区免费看 | 日本免费久久高清视频 | 中文字幕在线观看免费观看 | 国产小视频在线免费观看 | 日日骑 | 欧美日本一二三 | 91精品国产99久久久久 | 亚洲国产成人高清精品 | 激情网在线视频 | 久久久久网站 | 国产精品18久久久久久久久久久久 | 国产视频一区二区在线观看 | www.日韩免费 | 91成人免费电影 | 久久精品视频3 | 久久亚洲免费 | 成人av电影在线播放 | 久久精品国产久精国产 | 色综合久久五月天 | 成 人 黄 色视频免费播放 | 亚洲欧美国产精品va在线观看 | 色婷婷欧美 | 在线不卡a | 欧美日韩视频在线一区 | 在线看片视频 | 欧美精品天堂 | 日韩手机视频 | 午夜av免费观看 | 中文字幕人成乱码在线观看 | 亚洲日本一区二区在线 | 国产真实精品久久二三区 | 久久天堂影院 | 久久久免费毛片 | 91久久电影 | 亚洲婷婷免费 | 国产黄大片在线观看 | 日韩欧美精选 | 国产综合福利在线 | 精品在线一区二区三区 | 午夜精品福利在线 | 夜夜嗨av色一区二区不卡 | 日日日天天天 | 天堂av免费 | 91高清免费在线观看 | 美腿丝袜一区二区三区 | 欧美日韩高清不卡 | 久久久久久福利 | 叶爱av在线| 成年人黄色免费看 | 久久五月激情 | 国内久久久久 | 欧美久久影院 | 黄色免费网战 | 久久99精品一区二区三区三区 | 亚洲精品久久久久久久不卡四虎 | 国产精品免费高清 | 日韩高清av在线 | 91专区在线观看 | 亚洲天堂网站视频 | 国产精品久久一区二区三区不卡 | 久99久视频 | 99精品观看 | 国产精品久久99 | 99精品视频在线观看免费 | 精品视频久久久 | 亚洲欧美色婷婷 | 日韩精品视频免费专区在线播放 | 91成人网在线 | 成人小视频在线观看免费 | 91九色精品国产 | 99在线视频网站 | 操操综合网 | 国产精品永久在线观看 | 就要干b| 国产精品手机看片 | 草久久久久 | 国产一级久久久 | 韩国三级av在线 | 91探花在线 | 大胆欧美gogo免费视频一二区 | 久99精品 | 欧美日韩高清在线 | 日本护士撒尿xxxx18 | 美女网站视频色 | 亚洲国产一区二区精品专区 | 成人在线黄色 | 亚洲专区在线播放 | 人人爱人人舔 | av免费在线观| 在线观看片 | 久久久精品一区二区 | 国际精品久久久 | 亚洲国产美女久久久久 | 99精品偷拍视频一区二区三区 | 久久久久久久久久影院 | 97精品一区二区三区 | 日韩精品一区二区在线视频 | 久久视频这里只有精品 | 国产一级免费视频 | 93久久精品日日躁夜夜躁欧美 | 麻豆视频免费版 | 精品专区一区二区 | 色综合久久网 | 国产精品亚洲精品 | 午夜av免费观看 | 欧美日韩中| 日本xxxx裸体xxxx17 | 探花视频免费观看高清视频 | 欧美日韩一区二区三区在线观看视频 | 国产精品久久久久久影院 | 亚洲精品高清一区二区三区四区 | 天天操狠狠操夜夜操 | 国产精品免费视频网站 | 在线观看亚洲 | 日韩在线视频播放 | 国内精品久久久久影院优 | 天天透天天插 | 成人91免费视频 | 高清不卡毛片 | 亚洲自拍av在线 | 亚洲伦理中文字幕 | 五月天最新网址 | 欧美久久久久久久久中文字幕 | 99这里只有精品99 | 日韩精品视频一二三 | 91传媒在线看 | 伊人色综合久久天天网 | 亚洲五月 | www.久久久精品 | 夜夜骑天天操 | 久久久午夜精品福利内容 | 狠狠躁日日躁 | 日韩精品久久久久久久电影竹菊 | 国产福利资源 | 在线激情影院一区 | 黄色动态图xx | 国产精品视频专区 | 亚洲91网站 | 国产在线观看不卡 | 怡春院av| 国产中文字幕在线观看 | 超碰在线公开免费 | 97精品久久 | 国产免费一区二区三区最新 | 在线观看免费视频 | 国产精品美女久久久久久免费 | 国产一区免费 | 久久久久久久久久久久电影 | 中文字幕资源网 | 久久久久久高清 | 在线观看av小说 | 二区精品视频 | 亚洲理论影院 | 亚洲精品乱码久久久久久写真 | 中文字幕精品三区 | 国产精品区在线观看 | 久久综合中文字幕 | 色视频在线 | 国产精品免费一区二区三区 | 99久久精品免费视频 | 日韩av免费一区二区 | 日韩欧美综合在线视频 | 黄色日批网站 | 日韩成人免费在线电影 | 久精品在线观看 | 日日爽日日操 | 久久日韩精品 | 国产高清在线免费视频 | 国产亚洲91 | 少妇bbbb| 免费在线观看不卡av | 婷婷深爱网 | 国产91精品高清一区二区三区 | 色网站在线观看 | a电影免费看 | 99精品国产在热久久下载 | 国产热re99久久6国产精品 | 免费在线观看午夜视频 | 日韩欧美在线综合网 | 成人三级av | 久久你懂的| 欧美日韩视频网站 | 中文字幕在线观看1 | 国产免费观看视频 | av电影在线不卡 | 久草视频首页 | 日韩黄色免费 | 黄色毛片观看 | 色欧美88888久久久久久影院 | 又色又爽又激情的59视频 | 51久久成人国产精品麻豆 | 香蕉视频亚洲 | h视频在线看 | 国产精品久久一区二区三区, | 久久婷婷国产色一区二区三区 | 日韩精品在线观看av | 在线不卡中文字幕播放 | 成人黄色免费在线观看 | 中文字幕韩在线第一页 | 欧美先锋影音 | 久久人人爽人人人人片 | 九九热.com | 国产在线看一区 | 欧美日韩高清一区二区三区 | 伊人资源站| 国产中文字幕视频在线观看 | 国产精品初高中精品久久 | 人人超碰97 | 精品1区2区 | 中文字幕一区二 | 97精品国产一二三产区 | 91精品视频在线播放 | 六月色婷| 中文字幕黄色网址 | 97视频一区 | 正在播放国产一区二区 | 午夜视频在线观看一区二区 | 香蕉久久久久久av成人 | 99精品成人 | 久久99精品一区二区三区三区 | 有码中文在线 | av三区在线 | 午夜私人影院 | 国产精品永久 | 久久精品高清视频 | 欧美视屏一区二区 | 色在线高清 | 激情五月婷婷综合网 | 欧美日高清视频 | 亚洲视频在线观看 | 日韩专区视频 | 在线午夜电影神马影院 | 欧美成人手机版 | 手机色在线 | 三级动图 | 黄污网站在线观看 | 成人黄在线 | 欧洲亚洲激情 | 超碰在线9 | 免费一级片在线 | 成年人免费电影 | 亚洲国产天堂av | aav在线 | 国产精品theporn | 日韩在线视频线视频免费网站 | 麻豆91在线观看 | 一区二区视频在线看 | 国产自产高清不卡 | 久久精品精品 | 国产色秀视频 | 在线观看国产永久免费视频 | av导航福利 | 首页av在线 | 亚洲最大在线视频 | 亚洲天堂网在线视频 | 亚洲成人中文在线 | 99色 | 久久歪歪| 欧美一区二区在线免费看 | 四虎国产精品永久在线国在线 | 丁香五月亚洲综合在线 | 国产福利一区二区在线 | 久久久久免费精品视频 | 国内小视频 | 久草在线综合网 | 久久不射电影院 | 欧美a级成人淫片免费看 | 国产亚洲精品美女久久 | 国产福利资源 | 成人在线观看网址 | 97成人精品区在线播放 | 91九色在线 | 国产美女主播精品一区二区三区 | 久久久久国产成人精品亚洲午夜 | 国产无套精品久久久久久 | 国产丝袜在线 | 麻豆视频一区二区 | 国产成人一区三区 | 国产精品麻豆三级一区视频 | www.天天操.com| 五月天婷婷丁香花 | 五月天婷亚洲天综合网精品偷 | 黄色网免费| 干干操操 | 在线观看黄色的网站 | 久草精品在线播放 | 国产三级国产精品国产专区50 | 韩国av电影在线观看 | 日本激情视频中文字幕 | 亚洲视频大全 | 亚洲精品在线视频观看 | 国产涩涩在线观看 | 国产精品密入口果冻 | 国产精品久久久久久999 | 国产精品一码二码三码在线 | 丁香花五月 | 国产精品毛片一区 | 狠狠躁18三区二区一区ai明星 | 国产不卡网站 | 91精品啪在线观看国产 | 亚洲黄色在线免费观看 | 婷婷色中文 | 国产视频色 | 96av在线视频 | 欧美一区二区在线 | 最近中文字幕完整高清 | 亚洲精品午夜久久久久久久久久久 | 伊人伊成久久人综合网站 | 亚洲区精品视频 | 成人av av在线 | 一区三区在线欧 | 国产精品黄色影片导航在线观看 | 午夜影视av| 日韩精品一区二区免费视频 | 九九热免费在线观看 | 丝袜美腿av | 亚洲精品视频在 | 日日夜夜添 | 国产高清在线免费视频 | 插插插色综合 | 国产精品视频99 | 婷婷丁香狠狠爱 | 婷婷色综 | 日韩欧美成| 亚洲va天堂va欧美ⅴa在线 | 四虎永久免费在线观看 | 又色又爽又黄 | 欧美大片在线看免费观看 | 日韩一区二区三区在线观看 | 国产亚洲精品久久19p | 五月天狠狠操 | 蜜臀久久99静品久久久久久 | 天天干天天操人体 | 久久久久久久久久久久久久免费看 | 欧美日韩中文字幕综合视频 | 午夜国产一区 | 狠狠色伊人亚洲综合网站色 | 色片网站在线观看 | 一区二区视频电影在线观看 | 成人免费视频观看 | 国产精品久久久久免费 | 国产精品影音先锋 | 色99中文字幕 | 色婷五月| 成年人免费看片网站 | 国产精品久久久久久久7电影 | 亚洲 欧洲av | 99r在线 | 狠狠色丁香久久婷婷综合_中 | 欧美一区三区四区 | 黄色在线看网站 | 久久a级片| 欧美激情视频在线观看免费 | 91在线看免费 | 婷婷激情五月综合 | 最近中文字幕 | 高清视频一区二区三区 | 国产精品久久久久久爽爽爽 | 国产在线不卡 | 久操97| 久久国产经典 | 久久怡红院 | 天天av综合网 | 成人在线免费看视频 | 91色蜜桃| 亚洲精品影院在线观看 | 顶级欧美色妇4khd | 亚洲经典视频在线观看 | 亚洲国产欧洲综合997久久, | 国内精品久久久久影院男同志 | 色综合久久99 | 日本午夜在线观看 | 美女福利视频网 | 视频三区| 国产精品欧美久久久久天天影视 | 黄在线免费观看 | 99久久久国产精品免费观看 | 亚洲一区欧美精品 | 国产一区二区三区 在线 | 男女靠逼app| 99热精品国产一区二区在线观看 | 又色又爽又激情的59视频 | 在线高清一区 | 九九99| 九色琪琪久久综合网天天 | 一区二区三区影院 | 欧美另类交人妖 | 亚洲国产高清视频 | 久久成人亚洲欧美电影 | 色婷av | 97国产大学生情侣酒店的特点 | 日本精品va在线观看 | 国产91影视 | 99国产精品免费网站 | 久久久久久久亚洲精品 | 精品久久久久一区二区国产 | 久久免费视频国产 | 青春草视频在线播放 | 久久精品中文字幕少妇 | 美女视频黄网站 | 国产亚洲人 | 国产精选视频 | 97日日| 中文字幕激情 | 欧美亚洲免费在线一区 | 亚洲精品xx | 91在线播放视频 | 国产精品久久久久久久久久不蜜月 | 中文字幕在线视频一区二区 | 亚洲精品中文字幕视频 | 婷婷久草 | 国产97在线看 | 国产免费观看高清完整版 | 欧美视频日韩 | 国产人成在线视频 | 免费黄色在线网址 | 69视频国产 | 天天操夜夜爱 | 国产精品一区二区av影院萌芽 | 午夜久久电影网 | 在线观看国产福利片 | 五月婷在线视频 | 久久美女精品 | 一区二区三区高清不卡 | 国产人成在线视频 | 一本一道久久a久久精品 | 亚洲一区久久 | 久久免费视频在线观看 | 中文字幕 在线 一 二 | 中文字幕的 | 日韩精品在线播放 | 色综合久久久久久中文网 | 国产一卡二卡在线 | 超碰人人超碰 | 最近免费观看的电影完整版 | 久久久久国产精品视频 | 在线观看a视频 | av黄在线播放 | 精品国产一区二区三区久久久蜜臀 | 在线观看91精品国产网站 | 久久成人精品视频 | 国产99久久久国产精品免费二区 | 国产精品久久二区 | 免费97视频 | 精品亚洲视频在线观看 | 日韩啪视频 | 国产精品 9999 | 午夜久久电影网 | 久久毛片高清国产 | 国产亚洲字幕 | 久久国产精品久久w女人spa | 天天色 天天 | 日韩av片在线 | 久久成人精品电影 | 久草在线中文888 | 久久久久久黄色 | 四虎在线观看精品视频 | 国产五月婷婷 | 成年人视频免费在线播放 | free. 性欧美.com | 久久全国免费视频 | 色婷婷久久久综合中文字幕 | 亚洲成人av在线播放 | 中文字幕在线视频网站 | 中文字幕日本电影 | 久久成人亚洲欧美电影 | sesese图片 | 三上悠亚一区二区在线观看 | 91香蕉视频色版 | 久久综合色影院 | 久久五月婷婷丁香 | 国产精品自产拍在线观看蜜 | 91精品久久久久久久91蜜桃 | 在线看黄色的网站 | 一级a毛片高清视频 | 国产一级片免费播放 | 久久久官网 | 四虎www.| 国产一区成人 | 国产午夜在线 | 日韩欧美综合 | 亚洲成年人免费网站 | 午夜免费久久看 | 岛国精品一区二区 | 午夜影视剧场 | 夜色资源站wwwcom | 国产精品久久久久一区二区 | 欧美一区二区在线免费观看 | 亚洲深爱激情 | 在线看国产精品 | 在线观看免费观看在线91 | 狠狠操操网 | 97视频免费播放 | 中文字幕在线专区 | 91麻豆精品国产91久久久使用方法 | 黄色三级免费看 | va视频在线 | 夜夜操天天干 | 91看片麻豆 | 91人人澡人人爽 | 婷婷av电影| 久久久久观看 | 夜夜天天干| 久久手机看片 | 中文字幕在线观看视频一区 | www99精品| 在线a人v观看视频 | 欧美一区二区精品在线 | 久久久精品网站 | 麻豆av一区二区三区在线观看 | 五月天亚洲综合小说网 | 探花在线观看 | 成人va天堂| 久草在线视频免费资源观看 | 免费在线一区二区 | 国产精品理论片在线播放 | 久久高清免费观看 | 97在线免费 | 欧美精品v国产精品 | 日韩深夜在线观看 | 中文字幕在线资源 | 亚洲电影久久久 | 国产一区二区三区高清播放 | 久久蜜臀一区二区三区av | 精品久久久精品 | 丁香花在线观看免费完整版视频 | 99视频一区 | 99久久99久国产黄毛片 | 狠狠躁日日躁狂躁夜夜躁av | 成人av在线一区二区 | 久久久久久久久久毛片 | 成人久久18免费网站图片 | 成年人黄色大全 | 日韩免费不卡av | 亚洲精品久久久久久久蜜桃 | 国产免费高清视频 | 国产视频精品在线 | 最近免费中文字幕mv在线视频3 | 99re国产| a黄色一级片| 成人avav| 91精品在线视频 | 欧美日韩在线看 | 亚洲国产午夜精品 | 欧美色图视频一区 | 亚洲精品视频免费在线 | 欧美色就是色 | 久热免费在线 | 91在线免费观看网站 | 97在线精品视频 | 91视频麻豆| 99久久www | av在线播放快速免费阴 | www.五月婷婷.com | 青青久草在线视频 | 国产精品久久久久久一二三四五 | 天天综合久久 | 国产成人免费 | 91精选在线 | 玖玖视频网 | 天天操天天爱天天爽 | 亚洲专区免费观看 | 在线观看精品国产 | 国内精品久久久久久久久久久 | 亚洲黄网站 | 日韩午夜av | 天天干天天插伊人网 | 中文字幕有码在线播放 | 日韩视频一区二区在线观看 | 国产福利91精品张津瑜 | 91视频com | 国产精品久久久久久久久久不蜜月 | 丁香六月五月婷婷 | 亚洲成人黄色 | 亚洲免费在线播放视频 | 美女视频黄色免费 | 四虎永久国产精品 | 亚洲综合婷婷 | 五月天六月婷婷 | 黄色亚洲免费 | 日韩高清dvd| 91天天操| 91精品国产三级a在线观看 | 播五月综合 | 久久国产精品99久久久久久进口 | 久久歪歪 | 日韩av片免费在线观看 | 亚洲精品看片 | 中文字幕av一区二区三区四区 | 亚洲免费精品视频 | 久在线 | 在线激情小视频 | 免费高清在线观看成人 | 午夜国产福利视频 | 色综合久久88色综合天天人守婷 | 超碰公开97 | 中文在线免费视频 | 国产在线观看高清视频 | 国产最新91| 国产精品99久久99久久久二8 | 国产精品久久久久久久久久久久冷 | 在线亚洲观看 | 国产精品永久免费 | 午夜12点 | 亚洲一级片在线看 | 日韩av不卡在线播放 | 国产成人一区三区 | 丁香在线观看完整电影视频 | 日韩美精品视频 | 久久久久久国产精品久久 | 成人午夜片av在线看 | av中文字幕日韩 | 99精品亚洲 | 麻豆视频在线看 | 国产视频69 | 国产精品免费看久久久8精臀av | 国产精品区二区三区日本 | av福利在线导航 | 色99之美女主播在线视频 | 美女露久久 | 综合精品久久 | 91精彩在线视频 | 91视频在线免费看 | 蜜桃视频在线观看一区 | 欧美日韩亚洲在线观看 | 最近高清中文在线字幕在线观看 | 成人网在线免费视频 | 玖玖在线免费视频 | 天天草夜夜 | 国产精品久久久久久久av电影 | 不卡的一区二区三区 | 国产国产人免费人成免费视频 | 国产精品视频专区 | 国产精品99久久久久人中文网介绍 | 亚洲女在线 | 国产vs久久 | 欧美日韩1区2区 | 国产精品99久久久精品免费观看 | 黄网站免费看 | 国产中文字幕在线播放 | 99久久婷婷国产一区二区三区 | 日韩精品一区二区三区免费观看视频 | 六月丁香婷 | 九九热免费视频在线观看 | 免费观看第二部31集 | 国产成人精品一区二区三区网站观看 | 韩日三级在线 | 国产二区精品 | 日韩理论片中文字幕 | 超碰伊人网 | 日韩精品一区二区久久 | 91视频91色| 91爱爱中文字幕 | 中文字幕一区二区三区四区久久 | 欧美精品午夜 | 日韩首页 | 五月天色站 | 国产精品第一页在线 | 日日夜夜免费精品 | 91亚洲精品久久久久图片蜜桃 | 国内揄拍国产精品 | 久久久久女人精品毛片九一 | 91插插视频 | 国产久草在线观看 | 国产精品久久久久av | 免费黄色激情视频 | 国产日韩精品在线观看 | 在线观看日韩免费视频 | 欧美 激情 国产 91 在线 | 最近日韩中文字幕中文 | 五月婷激情 | www黄色| 天天射射天天 | 久久天堂亚洲 | 成人av免费播放 | 又紧又大又爽精品一区二区 | 欧美日韩大片在线观看 | 日韩黄色大片在线观看 | 久久综合狠狠综合久久综合88 | 欧美激情综合色 | 日韩区欠美精品av视频 | 中文字幕免 | 国产精品久久久免费看 | 午夜10000| 国产精品第一 | 亚洲综合五月 | 一级黄色片在线免费看 | 久草在线高清视频 | 免费观看日韩 | 日韩欧美视频在线免费观看 | 国产婷婷久久 | 狠狠综合网 | 欧美精品中文 | 国产亚洲欧美一区 | 99免费在线视频 | 日韩精品你懂的 | 日韩免费看视频 | av成人在线电影 | 一区二区三区精品在线视频 | 日韩精品视频免费看 | 人人爽人人射 | 99精品国产福利在线观看免费 | 国产精品免费久久久久久久久久中文 | 五月天婷婷丁香花 | 国产一级电影在线 | 久久999精品| 69绿帽绿奴3pvideos | 欧美日在线 | 国产成人精品亚洲a | 天堂av在线网址 | 国产精品久久久久久爽爽爽 | 欧美热久久 | 精品a在线 | 国产黄色一级大片 | 久久高清免费视频 | 色网站在线免费观看 | 天天爱天天色 | 伊人狠狠干 | 日韩xxx视频| 制服丝袜欧美 | 91国内在线视频 | 精品uu| 成人a视频在线观看 | ww视频在线观看 | 欧美日韩一区二区久久 | 日韩免费久久 | 三上悠亚一区二区在线观看 | av中文字幕免费在线观看 | 久久再线视频 | 久久网址 | 91人人爽人人爽人人精88v | www,黄视频 | 亚洲国产精品视频在线观看 | 国产小视频在线免费观看视频 | 久久久穴| 国产精品毛片一区视频播不卡 | 福利一区视频 | 在线国产中文 | 91精品欧美一区二区三区 | 日日干干夜夜 | 国产婷婷一区二区 | 欧洲黄色片 | 五月天婷婷视频 | 成年人在线免费视频观看 | 亚洲成 人精品 | 亚洲国产精品久久久久久 | 久草免费新视频 | 免费黄色av | 中文有码在线 | 亚洲成人二区 | 91免费观看网站 | 激情婷婷丁香 | 色婷婷欧美 | 91成年人视频 | 久久精品国产成人 | 日本视频久久久 | 在线观看91视频 | 国产一区二区在线免费视频 | 天天射天天射天天射 | 九九在线精品视频 | www.97色.com | 在线视频日韩一区 | 午夜.dj高清免费观看视频 | 久久成人18免费网站 | 欧美一二三视频 | 日韩免费 | 成年人视频在线免费观看 | av解说在线观看 | 91麻豆文化传媒在线观看 | 中文字幕a∨在线乱码免费看 | 五月婷婷在线观看视频 | 国产黄色特级片 | 99国产精品| 午夜精品成人一区二区三区 | 成人免费观看电影 | 午夜精品久久久久久久99 | 国产成人在线精品 | 色综合中文字幕 | 国产精品欧美久久久久天天影视 | 亚洲国产精品500在线观看 | 一区二区三区免费 | 色综合狠狠干 | 久久a级片| 二区精品视频 | 中文字幕在线观看视频一区 | 国产精品欧美激情在线观看 | 97电影院在线观看 | 午夜精品福利在线 | 最近中文字幕免费观看 | 夜夜操狠狠干 | 日日综合网| 国产精品中文字幕在线播放 | 久久天天躁狠狠躁亚洲综合公司 | 五月婷婷婷婷婷 |