摘要:若數值字符串和布爾值做為待合并數據,合并至目標目標對象時,只有字符串會以數組形式,拷貝到目標對象。上面代碼中,布爾值數值字符串分別轉成對應的包裝對象,可以看到它們的原始值都在包裝對象的內部屬性上面,這個屬性是不會被拷貝的。
屬性簡寫延續之前的關于ES6的學習內容整理,該篇主要是整理ES6中關于對象的擴展,希望對大家有幫助。之前已經整理了ES6--字符串擴展和ES6--函數擴展,大家有興趣可以移步了解。
允許直接寫入變量/函數,作為對象的屬性/方法。
let str = "Clearlove" let obj = {str} obj // { str: "Clearlove" } // 等同于 let str = "Clearlove" let obj = { str: str }
作為方法時的簡寫:
let obj = { method() { return "Hello~" } } // 等同于 let obj = { method: function() { return "Hello~" } }
屬性和方法的簡寫一般作為函數函數的返回值, 對象屬性的賦值器和構造器, 以及CommonJS 模塊輸出一組變量,就非常合適使用簡潔寫法。
let Obj = {}; function getItem (key) { return key in Obj ? Obj[key] : null; } function setItem (key, value) { Obj[key] = value; } function clear () { Obj = {}; } module.exports = { getItem, setItem, clear } // 等同于 module.exports = { getItem: getItem, setItem: setItem, clear: clear }屬性表達式
javascript中定義對象屬性,最常見的方式如下:
let obj = {} obj.iseditable = true
ES6中允許用表達式作為對象的屬性,將表達式放在一對中括號中,如下:
let key1 = "key1" let obj = { [key1]: "123", ["key" + "2"]: "abc" }
表達式還可以定義方法名:
let obj = { ["say" + "hello"]() { return "hello" } } obj.sayhello() // helloObject.is()
用于比較兩個值是否嚴格相等,與嚴格比較運算符===基本一致
Object.is("Clearlove", "Clearlove") // true Object.is({}, {}) // false
與嚴格比較運算符===的差異主要有兩點:1. +0不等于-0, 2. 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 });Object.assign()
Object.assign方法用于對象合并,將待合并對象的所有可枚舉屬性,復制到目標對象中。
let target = { name: "Clearlvoe" } let age = { age: 18 } let sex = { sex: "男" } Object.assign(target, age, sex) target // {name: "Clearlvoe", age: 18, sex: "男"}
如果目標對象與待合并對象有同名屬性,或多個待合并對象有同名屬性,則后面的屬性會覆蓋前面的屬性。
如果只有一個參數,Object.assign會直接返回該參數。
let target = { name: "Clearlvoe" } Object.assign(target) // { name: "Clearlvoe" } Object.assign(target) === target // true
如果該參數不是對象,則會先轉成對象,然后返回。但undefined和null無法轉化為對象,所有以它們為參數時,會報錯。
typeof Object.assign(2) // "object" Object.assign(undefined) // Uncaught TypeError: Cannot convert undefined or null to object Object.assign(null) // Uncaught TypeError: Cannot convert undefined or null to object
但如果undefined或null是作為帶合并數據,則不會報錯,因為無法轉化為對象,所有跳過。
let target = { name: "Clearlvoe" } Object.assign(target, undefined) === obj // true Object.assign(target, null) === obj // true
若數值、字符串和布爾值做為待合并數據,合并至目標目標對象時,只有字符串會以數組形式,拷貝到目標對象。而數值和布爾值則會被忽略。
let str = "abc"; let boolean = true; var num = 10; let obj = Object.assign({}, str, boolean, num); console.log(obj); // { "0": "a", "1": "b", "2": "c" }
字符串能被拷貝,是因為字符串的包裝對象,會產生可枚舉屬性。
Object(true) // {[[PrimitiveValue]]: true} Object(10) // {[[PrimitiveValue]]: 10} Object("abc") // {0: "a", 1: "b", 2: "c", length: 3, [[PrimitiveValue]]: "abc"}
上面代碼中,布爾值、數值、字符串分別轉成對應的包裝對象,可以看到它們的原始值都在包裝對象的內部屬性[[PrimitiveValue]]上面,這個屬性是不會被Object.assign拷貝的。只有字符串的包裝對象,會產生可枚舉的實義屬性,那些屬性則會被拷貝。
Object.assign拷貝的屬性是有限制的,只拷貝源對象的自身屬性(不拷貝繼承屬性),也不拷貝不可枚舉的屬性(enumerable: false)。
Object.assign({name: "Clearlove"}, Object.defineProperty({}, "invisible", { enumerable: false, value: "hello" }) ) // {name: "Clearlove"}
上面代碼中,Object.assign要拷貝的對象只有一個不可枚舉屬性invisible,這個屬性并沒有被拷貝進去。
注意點Object.assign()是淺拷貝,如果源對象的某個屬性值是對象,那么目標對象拷貝到的是這個 對象的引用。
let source = {person: { name: "Clearlove"}} let target = Object.assign({}, source) source.person.name = "Meiko" target.person.name // "Meiko"
對于這種嵌套的對象,一旦遇到同名屬性,Object.assign()的處理方法是替換,而不是添加。
let source = {person: { name: "Clearlove" }} let target = {person: { name: "Meiko", age: 18 }} Object.assign(target, source) // {person: { name: "Clearlove" }}常見用途 為對象添加屬性
class LOL { constructor(name, age) { Object.assign(this, {name, age}) } }
上面方法通過Object.assign方法,將name屬性和age屬性添加到LOL類的對象實例。
為對象添加方法Object.assign(SomeClass.prototype, { addClass(classname) { .... }, removeClass(class) { .... } })克隆對象
function clone(origin) { return Object.assign({}, origin); }
上面代碼將原始對象拷貝到一個空對象,就得到了原始對象的克隆。
不過,采用這種方法克隆,只能克隆原始對象自身的值,不能克隆它繼承的值。如果想要保持繼承鏈,可以采用下面的代碼。
function clone(origin) { let originProto = Object.getPrototypeOf(origin) return Object.assign(Object.create(originProto), origin) }合并多個對象
將對個對象合并到目標對象中
const merge = (target, ...sources) => Object.assign(target, ...sources)
如果希望合并后返回一個新對象,可以改寫上面函數,對一個空對象合并
const merge = (...sources) => Object.assign({}, ...sources)為屬性制定默認值
const DEAFULT = { number: 0, template: "html" } funcition processContent(options) { options = Object.assigin({}, DEAFULT, options) console.log(options) }
注意,由于存在淺拷貝的問題,DEFAULT對象和options對象的所有屬性的值,最好都是簡單類型,不要指向另一個對象。否則,DEFAULT對象的該屬性很可能不起作用。
屬性的可枚舉性和遍歷 可枚舉性對象的每個屬性都有一個描述對象(Descriptor),用來控制該屬性的行為。
let person = { name: "Clearlove" } Object.getOwnPropertyDescriptor(person, "name") // { // value: Clearlove, // writable: true, // enumerable: true, // configurable: true // }
描述對象的enumerable屬性,稱為”可枚舉性“,如果該屬性為false,就表示某些操作會忽略當前屬性。
目前有四個操作會忽略enumerable為false的屬性:
for..in循環: 只遍歷自身和繼承的可枚舉的屬性
Object.keys(): 返回對象所有可枚舉的屬性的鍵名
JSON.stringify: 只字符串化可枚舉的屬性
Object.assign(): 忽略enumerable為false的屬性,只拷貝可枚舉的屬性
這四個操作之中,前三個是 ES5 就有的,最后一個Object.assign()是 ES6 新增的。其中,只有for...in會返回繼承的屬性,其他三個方法都會忽略繼承的屬性,只處理對象自身的屬性。實際上,引入“可枚舉”(enumerable)這個概念的最初目的,就是讓某些屬性可以規避掉for...in操作,不然所有內部屬性和方法都會被遍歷到。
比如,對象原型的toString方法,以及數組的length屬性,就通過“可枚舉性”,從而避免被for...in遍歷到。
Object.getOwnPropertyDescriptor(Object.prototype, "toString").enumerable // false Object.getOwnPropertyDescriptor([], "length").enumerable // false
上面代碼中,toString和length屬性的enumerable都是false,因此for...in不會遍歷到這兩個繼承自原型的屬性。
另外,ES6 規定,所有 Class 的原型的方法都是不可枚舉的。
Object.getOwnPropertyDescriptor(class {foo() {}}.prototype, "foo").enumerable // false未完待續
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/91812.html
摘要:循環遍歷對象自身的和繼承的可枚舉屬性不含屬性。返回一個數組,包含對象自身的所有屬性的鍵名。目前,只有對象方法的簡寫法可以讓引擎確認,定義的是對象的方法。showImg(https://user-gold-cdn.xitu.io/2019/5/21/16ada8456223b0e1); 1. 屬性的簡潔表示法 在ES6中 允許直接寫入變量和函數,作為對象的屬性和方法,使得代碼的書寫更為簡潔。...
摘要:屬性的簡潔表示法在中允許直接寫入變量和函數,作為對象的屬性和方法,使得代碼的書寫更為簡潔。循環遍歷對象自身的和繼承的可枚舉屬性不含屬性。返回一個數組,包含對象自身的所有屬性的鍵名。 showImg(https://segmentfault.com/img/remote/1460000019259004?w=1282&h=1920); 1. 屬性的簡潔表示法 在ES6中 允許直接寫入變量...
摘要:標準入門讀書筆記和命令新增命令,用于聲明變量,是塊級作用域。用于頭部補全,用于尾部補全。函數調用的時候會在內存形成一個調用記錄,又稱為調用幀,保存調用位置和內部變量等信息。等到執行結束再返回給,的調用幀才消失。 《ES6標準入門》讀書筆記 @(StuRep) showImg(https://segmentfault.com/img/remote/1460000006766369?w=3...
摘要:字符串的擴展字符串的遍歷器接口字符串可以被循環遍歷。即能識別編號大于查詢字符串是否包含某個字符返回布爾值,表示是否找到了參數字符串。返回布爾值,表示參數字符串是否在原字符串的頭部。 字符串的擴展 1.字符串的遍歷器接口 字符串可以被for...of循環遍歷。 與es5的比較for循環雖可以遍歷字符串,但不能識別大于oxFFFF的編碼; 2.位置 --> 字符/碼點 根據指定位置返回對應...
摘要:參數的形式為變量名擴展運算符是三個點。傳遞給函數的一組參數值,被整合成了數組。擴展運算符的應用普通的函數調用上面代碼中,和這兩行,都是函數的調用,它們的都使用了擴展運算符。這時,擴展運算符可以將其轉為真正的數組,原因就在于對象實現了。 rest參數和擴展運算符都是ES6新增的特性。rest參數的形式為:...變量名;擴展運算符是三個點(...)。 rest參數 rest參數用于獲取函數...
閱讀 2784·2023-04-25 18:06
閱讀 2576·2021-11-22 09:34
閱讀 1684·2021-11-08 13:16
閱讀 1302·2021-09-24 09:47
閱讀 3049·2019-08-30 15:44
閱讀 2773·2019-08-29 17:24
閱讀 2584·2019-08-23 18:37
閱讀 2433·2019-08-23 16:55