日韩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)秀的技術革新人員。

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

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

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

?

?

總結

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

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

日韩三级av | 日韩av片无码一区二区不卡电影 | 国产一区二区精品久久 | 日韩理论影院 | 欧美日韩国产色综合一二三四 | 久草在线资源网 | 涩涩资源网 | 99精品国产99久久久久久福利 | 欧美激情xxxx性bbbb | 日韩欧美69 | 亚洲综合色丁香婷婷六月图片 | 超碰国产97 | 91精品综合在线观看 | 久久特级毛片 | 国产高清视频免费观看 | 最近中文字幕免费观看 | 久久黄色免费视频 | 在线视频18在线视频4k | 深夜免费小视频 | 激情婷婷在线 | 国产麻豆果冻传媒在线观看 | 国产精品久久久久久吹潮天美传媒 | 久久婷婷一区 | 久久亚洲综合色 | 欧美韩国日本在线 | 欧美日韩免费在线观看视频 | 国产精品成人久久久久 | 欧美激情va永久在线播放 | 97碰在线| 日韩欧美在线观看一区二区三区 | 中文字幕第一页在线视频 | 天天看天天干天天操 | 激情欧美在线观看 | 免费成人看片 | 色网址99| 国产视频欧美视频 | 亚洲综合视频在线观看 | 亚洲黄色在线播放 | 国产一级免费在线观看 | 国产精品久一 | 国产91免费看| 91.精品高清在线观看 | 日韩三级精品 | 久久天天草| 狠狠狠综合 | 九色porny真实丨国产18 | 亚洲日本在线一区 | 国产在线a| 成人a视频在线观看 | 999国内精品永久免费视频 | 91av资源网 | 色婷婷激婷婷情综天天 | 欧美日韩一区二区视频在线观看 | 88av网站| 日韩草比 | 久久久久五月天 | 欧美久久综合 | 日韩av区| 日韩二区在线 | 久久99精品久久久久久久久久久久 | 狠狠躁夜夜躁人人爽视频 | 久久精品国产一区二区电影 | 91日韩精品视频 | 国产精品大尺度 | 香蕉视频在线看 | 99久久综合国产精品二区 | 一区二区三区日韩精品 | 精品亚洲一区二区三区 | 久久久久久黄 | 操操日 | 久草精品在线播放 | 黄p在线播放 | 在线视频电影 | 国产精品免费久久久久久 | 久久免费观看少妇a级毛片 久久久久成人免费 | 免费的国产精品 | 国产男女无遮挡猛进猛出在线观看 | 五月天色综合 | 久久伊人国产精品 | 国产视频精选在线 | av不卡免费在线观看 | 久久天天躁狠狠躁亚洲综合公司 | 国产免费专区 | 人人爽人人爽人人片av | 啪啪免费视频网站 | 精品免费视频123区 午夜久久成人 | 久久精品视频5 | 亚洲第一伊人 | 在线成人免费 | www.久久久com | 久久精品视频播放 | 97在线观视频免费观看 | 中文字幕一区二区三区四区在线视频 | 久久午夜国产 | 黄色免费av | 免费激情在线电影 | 久久免费的视频 | 日本99热 | av导航福利 | 欧美日韩18 | 欧美一区二区三区在线看 | 青草视频在线 | 国产精品成久久久久三级 | 成年人免费观看在线视频 | 国内成人精品2018免费看 | 日韩久久久 | 亚洲免费在线视频 | 国产黄在线免费观看 | 国产成人精品av在线 | 国产精选在线观看 | 最新av网站在线观看 | 国产高清黄色 | 日韩综合一区二区 | 91精品在线观看视频 | 黄色h在线观看 | 国产永久网站 | 国产精品免费久久久久影院仙踪林 | 91久久久国产精品 | 99久久99久久精品国产片 | 成人国产电影在线观看 | 国产精品一区二区av麻豆 | 在线三级av | 亚洲天堂网视频在线观看 | 国产又粗又猛又爽又黄的视频免费 | 狠狠狠狠狠狠天天爱 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 激情综合五月网 | 在线小视频你懂的 | 天操夜夜操 | 亚洲一级免费电影 | 在线国产99 | 一区二区三区不卡在线 | 在线观看成人一级片 | 五月婷婷综合在线观看 | 91在线精品视频 | 96久久 | 天堂资源在线观看视频 | 91丨九色丨国产在线 | 四虎永久国产精品 | 国产999视频在线观看 | 亚洲欧美在线观看视频 | 久久蜜臀一区二区三区av | 亚洲综合激情小说 | 成人三级黄色 | 欧美激情第一区 | 中文字幕观看在线 | 国产成人精品一区二区三区在线观看 | 国产不卡视频在线 | 久9在线| 亚洲成人午夜在线 | 久久女教师 | 97免费在线观看视频 | 久久久久久高潮国产精品视 | 国内视频在线观看 | 国产一区二区视频在线播放 | 久久超级碰 | 在线看日韩 | 欧美日韩国产在线一区 | 久久久国产影视 | 黄色日本片 | 日韩久久一区二区 | 91精品国 | 亚洲一区精品人人爽人人躁 | 久99视频 | 欧美精品亚洲精品日韩精品 | 午夜12点 | 六月丁香在线视频 | 欧美综合在线观看 | 久久久人人人 | 免费一级片观看 | 日本三级全黄少妇三2023 | 免费午夜视频在线观看 | 在线视频一区观看 | 91精品久久久久久综合五月天 | 玖草影院 | 夜夜爽天天爽 | 五月天六月婷婷 | 国产成人免费观看久久久 | 91视频高清免费 | 成人av一区二区在线观看 | 五月婷婷色播 | 808电影免费观看三年 | 色吊丝在线永久观看最新版本 | 免费成人黄色片 | 一区二区视频在线观看免费 | 国产精品私人影院 | 亚洲aⅴ在线观看 | 丁香婷婷综合五月 | 午夜影院一级 | 国产免费作爱视频 | 黄色精品免费 | av在线播放不卡 | 成人h电影在线观看 | 色视频国产直接看 | 韩国中文三级 | 四虎伊人| 国产亚洲欧美日韩高清 | www.久久99 | 日韩手机在线观看 | 麻豆果冻剧传媒在线播放 | 成人免费观看av | 青青河边草手机免费 | 久久综合九色综合欧美狠狠 | 精品久久久久久久久久久久久久久久久久 | 国产精品福利一区 | 久久不见久久见免费影院 | 国产视频 久久久 | 伊人午夜 | 免费观看成人网 | 久久久久久久久毛片 | 91色视频 | 国产手机视频在线播放 | 久久天天操 | 天天综合精品 | 国产三级在线播放 | 国产综合久久 | 在线观看黄网 | 开心婷婷色 | 天天曰天天曰 | 久久免费精品一区二区三区 | 九九免费在线看完整版 | 中文字幕成人在线观看 | 欧美成人区 | 欧美人操人 | 亚洲精品欧洲精品 | 91视频网址入口 | 欧美性色综合网 | 国内精品久久久久久久久久久久 | 91视频午夜 | 99久久99热这里只有精品 | 一区二区三区观看 | 亚洲黄色在线免费观看 | 国产无套一区二区三区久久 | 国产精品毛片一区二区在线看 | 亚洲视频一级 | 特级黄色视频毛片 | 五月黄色 | 日本久久中文 | 欧美久久久久久久久 | av线上看| 国产精品破处视频 | 欧美日韩国产区 | 国产麻豆精品久久一二三 | 久久久精品一区二区三区 | av丝袜制服| 一区二区电影网 | 欧美极品少妇xxxxⅹ欧美极品少妇xxxx亚洲精品 | 香蕉在线影院 | 国产精品一区二区久久 | 国产在线中文 | 99热99re6国产在线播放 | 日韩视频一区二区 | 久久综合操 | 麻豆视频免费播放 | 九精品| 六月久久婷婷 | 激情婷婷丁香 | 日韩区在线观看 | 91视频传媒 | 在线a视频免费观看 | 国产成人99av超碰超爽 | 国产成人精品久久亚洲高清不卡 | 中文字幕在 | 亚洲视频在线免费看 | 亚洲综合成人专区片 | www.夜夜夜 | 色综久久| 成人网在线免费视频 | 午夜国产福利在线观看 | 国产 视频 久久 | 天天射综合网视频 | 成年人在线播放视频 | 粉嫩一区二区三区粉嫩91 | 国产精品国产三级国产aⅴ入口 | 久久人91精品久久久久久不卡 | 国产专区一| av看片网址 | 欧美日韩中文字幕综合视频 | 国产免费高清视频 | 一区二区三区在线免费观看 | 久久色视频 | 69国产盗摄一区二区三区五区 | 成年人免费电影 | 欧美韩国日本在线观看 | 五月激情久久久 | 久草在线官网 | 日韩欧美网址 | 国产录像在线观看 | 国产精品18p | 手机av网站 | 国产一区私人高清影院 | www.午夜| 国内精品在线看 | 国产一区免费在线观看 | 丝袜网站在线观看 | 在线观看欧美成人 | 日本二区三区在线 | 久久精品国产99国产 | 亚洲成人蜜桃 | 国产999免费视频 | 狠狠色噜噜狠狠狠狠2021天天 | 不卡中文字幕在线 | 69xx视频 | 免费在线播放黄色 | 亚洲精品国偷拍自产在线观看蜜桃 | 久久男人中文字幕资源站 | 欧洲性视频 | 国产一区观看 | 欧美成人xxxxxxxx | 色吧久久 | 亚洲成aⅴ人片久久青草影院 | 五月婷婷色综合 | www.久久91| 91视频高清免费 | 91午夜精品 | 美女搞黄国产视频网站 | 97福利视频 | 国产美女精品视频 | 亚洲欧洲视频 | 又黄又爽又无遮挡的视频 | 免费在线黄色av | 国产精品免费观看视频 | 亚洲精品理论 | 五月婷婷在线视频观看 | 91黄色小网站| 成人免费ⅴa | 91精品国产综合久久婷婷香蕉 | 91视频首页 | 久久经典国产视频 | 国产精品久久久久免费 | 成年人在线观看免费视频 | 婷婷射五月| 香蕉影视在线观看 | 女人18片毛片90分钟 | 国产高清视频在线免费观看 | 亚洲无线视频 | 国产成人精品一区二区三区在线 | 韩国一区二区三区在线观看 | 国产精品一区二区久久国产 | 色综合天天综合在线视频 | 婷婷五天天在线视频 | 色网站免费在线观看 | 亚洲永久精品视频 | 五月丁香 | 99精品视频免费 | 亚洲国产三级在线观看 | 99国内精品| 日韩日韩日韩日韩 | 婷婷丁香国产 | 在线亚洲成人 | 色欧美日韩 | 91视频在线观看下载 | 久草在线观| 国产成人免费在线 | 97在线观看免费高清完整版在线观看 | 欧美一级电影在线观看 | av免费网页| 欧美一区二区三区激情视频 | 在线观看成人毛片 | 黄网站免费大全入口 | 亚洲理论片在线观看 | 91在线影视 | 久久久久久久久久免费 | 日本在线观看中文字幕无线观看 | 91精品在线麻豆 | av 一区 二区 久久 | 免费在线观看av网站 | 欧美性色黄 | 国产色视频123区 | 日韩免费电影一区二区三区 | 成人片在线播放 | 国产精品成人免费一区久久羞羞 | 午夜久久影院 | 久久伊人精品天天 | 欧美日韩国产一区二 | 精品欧美一区二区三区久久久 | 五月天色综合 | 天堂av网址 | 在线播放 一区 | 激情av网址 | 成人午夜黄色 | 在线免费观看麻豆视频 | 91天堂影院| 超碰在线97免费 | 91麻豆精品国产91久久久使用方法 | 国产精品中文字幕在线观看 | 久久99精品久久只有精品 | 欧美日韩不卡一区二区 | 精品女同一区二区三区在线观看 | 伊人久久精品久久亚洲一区 | 国产精品久久久久亚洲影视 | 伊人欧美 | 中文字幕在线观看播放 | 亚洲成人精品在线 | 亚洲免费在线视频 | 97色婷婷成人综合在线观看 | 狠狠狠狠干 | 欧美日韩一区二区三区在线免费观看 | 在线免费观看国产黄色 | 日韩mv欧美mv国产精品 | 一级做a视频 | 国产资源在线视频 | 少妇高潮冒白浆 | 国产九九在线 | www.国产精品 | 成人中文字幕在线 | 操操操av| 美女黄频在线观看 | 91av视频在线观看免费 | 色综合天天综合 | 欧美另类色图 | 日本一区二区三区视频在线播放 | 亚洲波多野结衣 | 亚洲国产一区av | av大全在线 | 一区二区三区在线免费 | 99久久久成人国产精品 | 人人爱人人添 | 99产精品成人啪免费网站 | 欧美最新另类人妖 | 中文字幕一区二区三区久久 | 人人看黄色 | 亚洲精品小视频在线观看 | 国产免费亚洲高清 | 欧美成人a在线 | 久久精品国产一区二区电影 | 欧美ⅹxxxxxx | 日韩国产精品一区 | 玖玖在线视频观看 | 亚洲91中文字幕无线码三区 | 美女精品网站 | 五月婷婷丁香色 | 色com网| 青青草国产精品 | 成人一级免费电影 | 一区二区不卡视频在线观看 | 日韩成人在线一区二区 | 国产99区 | 国产高清不卡在线 | 欧美亚洲国产一卡 | 91在线一区 | 丁香视频全集免费观看 | 国产999精品| 久久久综合九色合综国产精品 | 91传媒免费观看 | 蜜臀久久99精品久久久无需会员 | 国产精品粉嫩 | 国产美女精品视频 | 久久激情综合网 | 成人毛片100免费观看 | 成人免费观看网址 | 91精品老司机久久一区啪 | 欧美另类交人妖 | 97视频在线观看网址 | 国产爽妇网 | 久久艹国产视频 | 98精品国产自产在线观看 | 久久免费电影网 | 国产黄色免费观看 | 日韩网站一区二区 | 日韩精品中文字幕在线不卡尤物 | 99精品黄色片免费大全 | www.狠狠插.com | 欧美大片在线看免费观看 | 国产免费久久av | 国产精品自在线拍国产 | 亚洲人成精品久久久久 | 97精品一区二区三区 | 韩日精品中文字幕 | 亚洲精品国偷拍自产在线观看 | 综合网天天色 | 久久精品视频一 | 岛国av在线不卡 | 国产一区二区在线观看视频 | 亚洲午夜精品久久久久久久久 | 99久久999久久久精玫瑰 | 国产视频精选 | 色偷偷888欧美精品久久久 | 在线观看日韩 | 最近的中文字幕大全免费版 | 精品亚洲欧美无人区乱码 | 成+人+色综合 | 久二影院 | 成人黄大片 | 在线小视频国产 | 综合久久2023 | 国产一级片毛片 | 久久精品国产亚洲精品2020 | 麻豆传媒电影在线观看 | 欧美老女人xx | 91麻豆精品国产 | 欧美精品久久久久久久久久久 | 成人黄色小说在线观看 | 曰韩在线| 色在线视频网 | 超碰官网 | 激情狠狠干 | 人人草在线视频 | 日韩丝袜视频 | 国产 日韩 在线 亚洲 字幕 中文 | 日韩久久精品一区二区三区 | 白丝av在线 | 九色免费视频 | 99久久精品视频免费 | 国产精品久久久久aaaa | 狠狠干天天干 | 欧美日韩精品区 | 久视频在线播放 | 欧美另类亚洲 | 中文字幕 国产精品 | 91麻豆看国产在线紧急地址 | 九九三级毛片 | 五月天婷婷在线观看视频 | 亚洲综合色丁香婷婷六月图片 | 九九免费在线观看视频 | 亚洲欧美在线视频免费 | 国产精品欧美久久久久久 | 日日干网 | 五月婷婷久久综合 | 亚洲精品久久久久999中文字幕 | 日b视频在线观看网址 | 久久在线免费观看视频 | 日日夜夜操av | 日韩精品久久久久久 | 最近中文字幕 | 超碰免费观看 | 国产精品成久久久久 | 亚洲精品乱码白浆高清久久久久久 | 在线观看电影av | 四虎在线永久免费观看 | 精品一区欧美 | 中文字幕之中文字幕 | 狠狠干.com| 欧美做受高潮1 | 日韩精品视频第一页 | 九九九九九精品 | 中文字幕在线影院 | 91污污| 国产美女搞久久 | 亚洲一区精品二人人爽久久 | 欧美xxxxx在线视频 | 日日干av | 精品一区二区在线免费观看 | 久草视频在线资源站 | 69中文字幕 | 亚洲黄色三级 | 久久久香蕉视频 | 伊人成人精品 | 一区 在线观看 | 看全黄大色黄大片 | 香蕉影视 | 欧美性极品xxxx娇小 | 在线观看深夜视频 | 久草在线99| 成人免费色 | 欧美日韩在线观看不卡 | 丁香五月亚洲综合在线 | 精品一区二区免费在线观看 | 97成人在线 | 精品在线一区二区三区 | 黄色视屏在线免费观看 | 欧美性生活一级片 | 成人国产亚洲 | av线上看 | 日韩av偷拍 | 亚洲精品免费看 | 91精品国产成人www | 亚洲成人国产 | 狠狠天天 | 91网址在线观看 | 美女免费视频观看网站 | 国产特级毛片aaaaaaa高清 | 日韩深夜在线观看 | 911亚洲精品第一 | 激情网站五月天 | 美女视频黄网站 | 国产中文在线观看 | 午夜精品成人一区二区三区 | 麻豆传媒电影在线观看 | 三级毛片视频 | 欧美另类成人 | 91 中文字幕 | 日韩另类在线 | 黄色片网站av | 成人a免费 | 婷婷五月情 | 国产一区二区精品在线 | 五月天高清欧美mv | 99热这里只有精品8 久久综合毛片 | 色婷婷欧美| 激情婷婷在线 | 日韩欧美高清一区二区三区 | 国产精品欧美日韩 | 黄色一级免费 | 国产人成免费视频 | 国产福利精品在线观看 | www99久久| 青青河边草免费直播 | 最近2019中文免费高清视频观看www99 | av在线一二三区 | 激情五月伊人 | 福利一区二区 | 中文字幕专区高清在线观看 | 成人午夜在线电影 | 欧美在线观看小视频 | 久久美女高清视频 | av电影免费在线看 | 在线观看国产区 | 亚洲午夜剧场 | 久久九九久久九九 | 色鬼综合网 | 91自拍视频在线 | 超碰在线官网 | 日韩视频一区二区在线观看 | 日日夜操| 深夜免费小视频 | 成人黄色av免费在线观看 | 日韩精品首页 | 国产一区二区三区高清播放 | 在线免费视| 国产99久久久精品 | 亚洲精品国产综合99久久夜夜嗨 | 日本女人的性生活视频 | 免费国产一区二区视频 | 日韩在线视频不卡 | 国产精品国产三级国产不产一地 | 久久字幕网| 天天爽天天做 | 在线免费亚洲 | 久久久久久久久久久久电影 | av福利超碰网站 | 美女国内精品自产拍在线播放 | 成人三级黄色 | 欧美精品久久久久性色 | 午夜影院三级 | 国产精品久久毛片 | 69精品久久久 | 久久久999免费视频 日韩网站在线 | 国精产品一二三线999 | 国产精品视屏 | 亚洲精品一区二区三区四区高清 | 欧美精品你懂的 | 日韩在线视频播放 | 欧美一级电影在线观看 | 人人爽爽人人 | 好看av在线| 日韩av中文在线观看 | 日韩欧美一区二区三区免费观看 | 伊人五月天.com | 国产精品视频久久 | www.97色.com| 九九免费精品 | 91网页版免费观看 | 在线观看成人国产 | 亚洲dvd| 欧美激情第28页 | 日韩专区在线观看 | 中文字幕国产在线 | 亚洲欧美日韩一区二区三区在线观看 | 日韩中文字幕a | 国产一线二线三线在线观看 | 国产高清av免费在线观看 | 精品一区二区免费在线观看 | av三级av | 久久久国产日韩 | 亚洲精品高清在线 | 日韩在线观看精品 | 久久精品79国产精品 | 99久久激情 | 天堂av高清 | 一区二区三区四区五区在线视频 | 国产成人精品一区一区一区 | 四虎www| 欧美一区二区三区四区夜夜大片 | 日韩三级.com| 国产福利精品在线观看 | 国产xvideos免费视频播放 | 99婷婷狠狠成为人免费视频 | 精品亚洲欧美一区 | 色偷偷88888欧美精品久久 | 欧美性高跟鞋xxxxhd | 久久精品中文字幕免费mv | 国产福利中文字幕 | 久久久久久久久久毛片 | 深爱五月激情网 | 国产人成一区二区三区影院 | 欧美成人tv| av超碰在线| 91精品啪在线观看国产线免费 | 久草在线久草在线2 | 97国产精品免费 | av免费在线观 | 亚洲一级国产 | 怡红院成人在线 | 超碰97人人干 | 九九热只有精品 | 在线播放视频一区 | 国产精品久久久久久久久久白浆 | 在线免费试看 | 欧美不卡在线 | 成人福利在线 | 午夜视频99| 日韩理论电影网 | 碰超在线观看 | 丁香婷婷射 | 国产精品高清av | 久久久福利影院 | 亚洲综合色网站 | 亚洲精品久久久久中文字幕二区 | 337p日本大胆噜噜噜噜 | 99精品免费在线观看 | 久久免费电影 | 国产香蕉97碰碰碰视频在线观看 | 日韩不卡高清 | 日韩精品一区二区三区免费观看 | 亚洲免费高清视频 | 在线观看中文av | 91免费在线 | 国产亚洲精品久久久久动 | 精品国产乱码一区二区三区在线 | 最近日本中文字幕 | 特级a老妇做爰全过程 | 国产中文字幕三区 | 国产精品免费一区二区 | 91在线观看高清 | 国产成人免费 | 日韩一三区 | 亚州精品一二三区 | 久久精品欧美一区二区三区麻豆 | 一区二区免费不卡在线 | 亚洲精选国产 | 美女黄濒 | 蜜桃麻豆www久久囤产精品 | 亚洲在线免费视频 | 伊人永久 | 伊人狠狠操 | 免费网站看v片在线a | www.夜夜操 | 狠狠88综合久久久久综合网 | 黄视频色网站 | 国产精品久久久久久久久婷婷 | 青草视频在线看 | 久久久天天操 | 久久久久成人精品 | 日韩视频精品在线 | 国产精品不卡一区 | 久久综合中文色婷婷 | 久久99精品久久久久久秒播蜜臀 | 成人一区二区三区在线 | 最新av在线免费观看 | 超碰免费久久 | 国产成人综合图片 | 黄色一集片 | 国产高清视频在线播放 | 久久免费成人精品视频 | 久久久久久久久久伊人 | 91丨九色丨丝袜 | 天天干人人插 | 国产剧情一区二区 | 99re8这里有精品热视频免费 | 黄色.com | 日韩欧美精品在线 | 国产精品一区二区视频 | 天天综合人人 | 91视频在线播放视频 | 久久久性| 亚洲视频h | 午夜电影 电影 | 中日韩免费视频 | 欧美成人中文字幕 | www.色国产 | 亚洲成人av电影在线 | 亚洲国产97在线精品一区 | 中文在线天堂资源 | 欧美天堂视频在线 | 国内精品久久久久久久久久久久 | 日日久视频| 日本在线观看一区二区 | 亚洲情婷婷 | 亚欧洲精品视频在线观看 | 91精品在线免费观看 | 成人av直播 | 国产一区在线看 | 91av资源在线 | 久久久www成人免费毛片 | 欧美性色黄大片在线观看 | 国产成人精品亚洲精品 | 国产成人免费高清 | 国产九九九九九 | 国产视频综合在线 | 亚洲精品福利在线 | 日本成人免费在线观看 | 国产精品美女www爽爽爽视频 | www.av在线.com| 日韩黄色免费看 | 中文字幕免费播放 | 久久精品艹 | 久久精品国产亚洲精品 | 91麻豆精品一区二区三区 | 亚洲尺码电影av久久 | 97成人在线视频 | 日韩丝袜在线观看 | 蜜臀av性久久久久蜜臀av | 免费情缘 | 91成人精品一区在线播放 | 91自拍成人| 在线观看一级视频 | 亚洲高清在线视频 | 亚洲欧美视频网站 | 国产精品综合av一区二区国产馆 | 国产精品视频专区 | 西西大胆啪啪 | 久久av不卡 | 国产精品免费久久久 | 色欧美88888久久久久久影院 | 91色九色| 亚洲精品国产精品国自产在线 | 91黄色在线看 | 青青河边草观看完整版高清 | 91自拍视频在线观看 | 麻豆系列在线观看 | 精品视频亚洲 | 九九亚洲视频 | 久久国产精品免费看 | 丰满少妇高潮在线观看 | 久久精品艹 | 久久久久久久久久久久久9999 | 国产精品一区二区久久 | 欧美性春潮 | 成年人在线看片 | 91在线文字幕 | 国产精品一区二区果冻传媒 | 亚洲视频在线免费观看 | 亚洲一区av | 欧美 日韩 成人 | 亚洲国产精品女人久久久 | 毛片永久新网址首页 | 日韩特黄一级欧美毛片特黄 | 精品1区2区3区 | 国产高清av免费在线观看 | 日韩在线中文字幕视频 | 亚洲国产精品久久 | 国产人免费人成免费视频 | 久久全国免费视频 | 色综合久久久久 | 成人av免费 | 中文字幕久久亚洲 | 成人网大片 | 在线观看日韩精品 | a视频在线观看 | 国产在线999 | 99精品国产一区二区三区不卡 | 亚洲三级网站 | 国产免费三级在线观看 | 成人av电影在线观看 | 日韩欧美精品在线视频 | 日韩精品一区二区三区中文字幕 | 五月婷网站 | 天天操福利视频 | 一级黄色片在线免费观看 | 久久黄色小说视频 | 91看片看淫黄大片 | 91精品999| www成人精品 | 亚洲欧美精品一区二区 | 夜色资源站wwwcom | 一区二区三区高清不卡 | 国产理伦在线 | 在线观看视频国产 | 99精品热视频 | 久久久久国产免费免费 | 午夜精品久久一牛影视 | 国内小视频| 六月丁香激情网 | 中文字幕在线看片 | 人人插人人射 | 亚洲精品网站在线 | 91mv.cool在线观看 | 久久国产精品二国产精品中国洋人 | 亚洲精品一区二区精华 | 日韩a级黄色| 成年人在线免费看 | 久久人人97超碰国产公开结果 | 久久久黄色免费网站 | 一区二区三区免费播放 | 欧美日产在线观看 | a黄色一级 | 国产精品一区二区电影 | 国产传媒一区在线 | 日韩精品在线视频 | 中午字幕在线 | 免费看三级网站 | 激情视频区 | 一级片免费在线 | 激情小说网站亚洲综合网 | 免费看污片 | 国产视频丨精品|在线观看 国产精品久久久久久久久久久久午夜 | 国内精品小视频 | 天天做天天爱天天综合网 | 9在线观看免费 | 日韩大片在线播放 | 欧美精品久久久久久久久久久 | 日日碰夜夜爽 | 免费视频三区 | 9999亚洲 | 天天搞天天干天天色 | 韩国一区二区三区在线观看 | 免费在线观看午夜视频 | 成人黄色短片 | 91高清免费 | 日韩欧美综合视频 | 果冻av在线 | 日韩99热| 日本性久久| 97超级碰碰碰视频在线观看 | 国产又粗又猛又黄又爽的视频 | 亚洲成人精品久久 | 日韩精品一区二区三区免费观看视频 | 亚洲国产网址 | 欧美一级艳片视频免费观看 | 国产91aaa| 欧美日韩在线视频免费 | а中文在线天堂 | 伊人久操 | 九九九在线 | 激情视频一区二区三区 | 国产视频一区二区在线观看 | 国产在线综合视频 | 日本99干网 | 视频二区在线视频 | 成人在线播放免费观看 | 狠色狠色综合久久 | 国产精品成人av在线 | 丁香5月婷婷 | 国产日产精品久久久久快鸭 | 久久久久女人精品毛片 | 亚洲好视频 | 国产精品久久久久久模特 | 午夜精品视频免费在线观看 | 最近2019年日本中文免费字幕 | 国产免费观看av | 久操伊人 | 黄色a在线 | 天堂在线成人 | 天天色图 | 91一区二区三区久久久久国产乱 | 国产精品毛片久久久久久久 | 色99在线 | www.看片网站 | 麻豆视频在线播放 | 麻豆视传媒官网免费观看 | 久久久国产99久久国产一 | 一级一级一片免费 | 视频一区二区国产 | 欧美一区二区在线看 | 手机av在线网站 | 成片免费观看视频999 | 亚洲一区二区三区在线看 | 色先锋资源网 | 成人免费一级 | 黄色动态图xx| 成人午夜免费福利 | 国产精品久久久久久久久婷婷 | 国产精品一二 | 免费在线观看不卡av | 99久久99久久精品国产片 | 欧日韩在线 | 日韩有码在线观看视频 | 国产在线一区二区 | 亚洲精品在线免费 | 亚洲精品国产综合99久久夜夜嗨 | 丁香花五月| 操操操com | 91在线视频精品 | 91大神在线观看视频 | 欧美综合久久 | 亚洲va综合va国产va中文 | 国产成人久久精品77777 | 婷婷伊人综合亚洲综合网 | 一区二区亚洲精品 | 国产精品久久久久久一区二区三区 | 国产精品2019| 中文字幕在线日亚洲9 | 日韩欧美一区二区三区黑寡妇 | 91免费观看| 黄色大全免费观看 | 国产又粗又猛又爽又黄的视频免费 | 99久久精品国产观看 | 国产在线观看高清视频 | 狠狠色伊人亚洲综合网站色 | 欧美日bb | 国产理论片在线观看 | 69久久99精品久久久久婷婷 | 免费久久网站 | 97av影院 | 欧美小视频在线观看 | 国产青草视频在线观看 | 九九有精品|