1. JavaScript 日常開發(fā)中常用的 Object 操作方法總結

        共 13752字,需瀏覽 28分鐘

         ·

        2021-12-14 17:49

        來源 |?https://juejin.cn/post/6991335772137734152


        今天這篇文章,我主要想給大家總結一下我們日常開發(fā)中一些常用的Object的操作方法,希望可以對各位有所幫助。

        01、JavaScript對象有兩種類型

        • Native:在ECMAScript標準中定義和描述,包括JavaScript內置對象(數(shù)組,日期對象等)和用戶自定義對象;

        • Host:在主機環(huán)境(如瀏覽器)中實現(xiàn)并提供給開發(fā)者使用,比如Windows對象和所有的DOM對象;

        02、創(chuàng)建對象并添加成員

        最簡單的方法(即Object Literal,對象字面變量),之后便可以向它添加屬性。
        字面量:字面量表示如何表達這個值,一般除去表達式,給變量賦值時,等號右邊都可以認為是字面量。
        // 1. 創(chuàng)建空對象后,在添加屬性const obj = { }obj.uname = 'dengke'obj.fn = () => { console.log('ggg')}console.log(obj) // { uname: 'dengke', fn: ? }
        // 2. 創(chuàng)建對象并且直接添加屬性 (常用)const obj1 = { uname:'dengke', fn: () => { console.log('ggg') }}console.log(obj1) // { uname: "dengke", fn: ? }
        補充
        • 擴展運算符(spread)是三個點(...)也可以創(chuàng)建對象(返回一個新對象),注意這是一個淺拷貝
        const obj = { name: 'dengke' }const obj1 = { age: 18, temp: { a: 10 }}
        const obj2 = { ...obj, ...obj1 }console.log(obj2) // { name: 'dengke', age: 18, temp: { a: 10 } }
        obj2.temp.a = 20console.log(obj2) // { name: 'dengke', age: 18, temp: { a: 20 } }console.log(obj1) // { name: 'dengke', age: 18, temp: { a: 20 } }

        03、訪問對象屬性

        const obj = { info: 'wakaka', inner: { a: 10, b: 20 }, arr: [1, 2], sayHi: (name) => { console.log(`hi,${name}`) }}
        // 用 dot(點 .) 的方式訪問console.log(obj.info) // wakakaconsole.log(obj.inner) // {"a":10,"b":20}console.log(obj.arr) // [1,2]obj.sayHi('dengke') // hi,dengke
        // 用 [] 的方式訪問console.log(obj['info']) // wakakaconsole.log(obj['inner']) // {"a":10,"b":20}console.log(obj['arr']) // [1,2]obj['sayHi']('dengke') // hi,dengke
        補充
        • 如果要訪問的對象不存在,可以使用 邏輯運算符 || 指定默認值
        只要“||”前面為false,不管“||”后面是true還是false,都返回“||”后面的值。
        只要“||”前面為true,不管“||”后面是true還是false,都返回“||”前面的值。
        console.log(obj.age || 18) // 18
        • 很多時候,我們想根據(jù)這個值是否為空來做接下來的操作,可以使用空值運算符 (??)?(es11)
        有一個冷門運算符??可以判斷undefined和null,這樣是比較符合普遍需求的。
        const age = 0 const a = age ?? 123 console.log(a) // 0
        • 可選鏈式操作符(?.)?(es11)
        這是當對象上沒有這個鍵的時候,不會報錯,而是賦值undefined
        const foo = { name: "zengbo" } let a = foo.name?.toUpperCase() // "ZENGBO" let b = foo.name?.firstName?.toUpperCase() // "undefined"

        04、刪除對象屬性

        利用關鍵字?`delete`
        const o = { p: 10, m: 20}
        delete o.pconsole.log(o) // { m: 20 }// 刪除對象的屬性后,在訪問返回 undefinedconsole.log(o.p) // undefined

        05、作為函數(shù)參數(shù)

        const displayPerson = (person) => { console.log(`name: ${person.name || '無名氏'}`) console.log(`age: ${person['age'] || 0}`)}
        displayPerson({ name: 'dengke', age: 18 })// name: dengke// age: 18
        displayPerson({ })// name: 無名氏// age: 0

        06、枚舉對象的屬性

        在js里面枚舉對象屬性一共有三種方法:
        • for in: 會遍歷對象中所有的可枚舉屬性(包括自有屬性和繼承屬性)
        • Object.keys(): 會返回一個包括所有的可枚舉的自有屬性的名稱組成的數(shù)組
        • Object.getOwnPropertyNames(): 會返回自有屬性的名稱 (不管是不是可枚舉的)
        1)、?for...in?會遍歷對象中所有的可枚舉屬性(包括自有屬性和繼承屬性)
        const obj = { itemA: 'itemA', itemB: 'itemB'}
        // 使用Object.create創(chuàng)建一個原型為obj的對象 (模擬繼承來的屬性)var newObj = Object.create(obj)
        newObj.newItemA = 'newItemA'newObj.newItemB = 'newItemB'
        for(i in newObj){ console.log(i)}// newItemA// newItemB// itemA// itemB
        // 現(xiàn)在我們將其中的一個屬性變?yōu)椴豢擅杜e屬性Object.defineProperty(newObj, 'newItemA', { enumerable: false})
        for(i in newObj){ console.log(i)}// newItemB// itemA// itemB
        補充
        如果不想讓for...in枚舉繼承來的屬性可以借助Object.prototype.hasOwnProperty()
        // 接上例for(i in newObj){ if( newObj.hasOwnProperty(i) ) console.log(i)}// newItemB
        Object.prototype.hasOwnProperty()該方法在下文有更具體的介紹
        2)、?Object.keys(): 會返回一個包括所有的可枚舉的自有屬性的名稱組成的數(shù)組
        // 接上例const result = Object.keys(newObj)
        console.log(result) // ["newItemB"]
        Object.keys()該方法在下文有更具體的介紹
        3)、Object.getOwnPropertyNames()?會返回自有屬性的名稱 (不管是不是可枚舉的)
        // 接上例const result = Object.keys(newObj)
        console.log(result) // ['newItemA','newItemB']

        07、數(shù)據(jù)類型檢測

        • typeof?常用?多用于原始數(shù)據(jù)類型的判斷
        const fn = function(n){ console.log(n)}const str = 'string'const arr = [1,2,3]const obj = { a:123, b:456}const num = 1const b = trueconst n = null const u = undefined
        console.log(typeof str) // stringconsole.log(typeof arr) // objectconsole.log(typeof obj) // objectconsole.log(typeof num) // numberconsole.log(typeof b) // booleanconsole.log(typeof n) // object null是一個空的對象console.log(typeof u) // undefinedconsole.log(typeof fn) // function
        通過上面的檢測我們發(fā)現(xiàn)typeof檢測的Array和Object的返回類型都是Object,因此用typeof是無法檢測出來數(shù)組和對象的。
        • tostring?常用?最實用的檢測各種類型
        我們經(jīng)常會把這個封裝成一個函數(shù),使用起來更加方便
        /*** @description: 數(shù)據(jù)類型的檢測* @param {any} data 要檢測數(shù)據(jù)類型的變量* @return {string} type 返回具體的類型名稱【小寫】*/const isTypeOf = (data) => { return Object.prototype.toString.call(data).replace(/\[object (\w+)\]/, '$1').toLowerCase()}
        console.log(isTypeOf({})) // objectconsole.log(isTypeOf([])) // arrayconsole.log(isTypeOf("ss")) // stringconsole.log(isTypeOf(1)) // numberconsole.log(isTypeOf(false)) // booleanconsole.log(isTypeOf(/w+/)) // regexpconsole.log(isTypeOf(null)) // nullconsole.log(isTypeOf(undefined)) // undefinedconsole.log(isTypeOf(Symbol("id"))) // symbolconsole.log(isTypeOf(() => { })) // function

        08、Object常用的API

        1)、?Object.assign()

        Object.assign()?方法用于將所有可枚舉屬性的值從一個或多個源對象分配到目標對象。它將返回目標對象。常用來合并對象。
        const obj1 = { a: 1, b: 2 }const obj2 = { b: 4, c: 5 }
        const obj3 = Object.assign(obj1, obj2)
        const obj4 = Object.assign({}, obj1) // 克隆了obj1對象
        console.log(obj1) // { a: 1, b: 4, c: 5 } 對同名屬性b進行了替換 obj1發(fā)生改變是因為obj2賦給了obj1
        console.log(obj2) // { b: 4, c: 5 }
        console.log(obj3) // { a: 1, b: 4, c: 5 }
        console.log(obj4) // { a: 1, b: 4, c: 5 }
        語法
        Object.assign(target, ...sources)
        • 參數(shù):target 目標參數(shù),sources源對象

        • 返回值:目標對象

        注意
        • 如果目標對象中的屬性具有相同的鍵,則屬性將被源對象中的屬性覆蓋。

        • Object.assign 方法只會拷貝源對象自身的并且可枚舉的屬性到目標對象。

        • assign其實是淺拷貝而不是深拷貝

        也就是說,如果源對象某個屬性的值是對象,那么目標對象拷貝得到的是這個對象的引用。同名屬性會替換。
        const obj5 = { name: 'dengke', a: 10, fn: { sum: 10 }}
        const obj6 = Object.assign(obj1, obj5)console.log(obj6) // { a: 10, b: 2, name: 'dengke', fn: {…}}console.log(obj1) // {a: 10, b: 2, name: 'dengke', fn: {…}} 對同名屬性a進行了替換
        • Object.assign 不會在那些source對象值為null或undefined的時候拋出錯誤。

        2)、?Object.keys()

        上邊枚舉對象屬性時有用到了Object.keys(),在這里就具體為大家介紹一下它。
        Object.keys()?方法會返回一個由一個給定對象的自身可枚舉屬性組成的數(shù)組,數(shù)組中屬性名的排列順序和正常循環(huán)遍歷該對象時返回的順序一致。與Object.values()相似,區(qū)別在于這個返回的是數(shù)據(jù)的屬性就是key。接下來就會介紹Object.values(),不要著急。
        const arr = ['a', 'b', 'c']console.log(Object.keys(arr)) // ['0', '1', '2']
        const obj = { 0: 'a', 1: 'b', 2: 'c' }console.log(Object.keys(obj)) // ['0', '1', '2']
        const obj2 = { 100: 'a', 2: 'b', 7: 'c' }console.log(Object.keys(obj2)) // ['2', '7', '100']
        語法
        Object.keys(obj)
        • 參數(shù):obj要返回其枚舉自身屬性的對象。

        • 返回值:一個表示給定對象的所有可枚舉屬性的字符串數(shù)組。

        注意
        • 在ES5里,如果此方法的參數(shù)不是對象(而是一個原始值),那么它會拋出 TypeError。在ES2015中,非對象的參數(shù)將被強制轉換為一個對象。
        Object.keys("foo")?//?TypeError:?"foo"?is?not?an?object???????(ES5?code)Object.keys("foo") // ["0", "1", "2"] (ES2015 code)

        3)、Object.values()

        Object.values()?方法返回一個給定對象自身的所有可枚舉屬性值的數(shù)組,值的順序與使用for...in循環(huán)的順序相同 ( 區(qū)別在于 for-in 循環(huán)枚舉原型鏈中的屬性 )。與Object.keys()相似,區(qū)別在于這個返回的是數(shù)據(jù)的值也就是value
        const obj1 = { foo: 'bar', baz: 42 }console.log(Object.values(obj1)) // ['bar', 42]
        const obj2 = { 0: 'a', 1: 'b', 2: 'c' }console.log(Object.values(obj2)) // ['a', 'b', 'c']
        語法
        Object.values(obj)
        • 參數(shù):obj被返回可枚舉屬性值的對象。

        • 返回值:一個包含對象自身的所有可枚舉屬性值的數(shù)組。

        注意
        • 對象key為number的話,會從升序枚舉返回。
        const obj3 = { 100: 'a', 2: 'b', 7: 'c' }console.log(Object.values(obj3)) // ['b', 'c', 'a']

        4)、Object.entries(obj)

        Object.entries()?方法返回一個給定對象自身可枚舉屬性的鍵值對數(shù)組??墒褂肙bject.fromEntries()方法,相當于反轉了Object.entries()方法返回的數(shù)據(jù)結構。接下來也會介紹Object.fromEntries()
        const obj1 = { name: 'dengke', age: 18};
        for (const [key, value] of Object.entries(obj1)) { console.log(`${key}: ${value}`);}// "name: dengke"// "age: 18"
        const obj2 = { foo: 'bar', baz: 42 }console.log(Object.entries(obj2)) // [ ['foo', 'bar'], ['baz', 42] ]
        const obj3 = { 0: 'a', 1: 'b', 2: 'c' }console.log(Object.entries(obj3)) // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]
        語法
        Object.entries(obj)
        • 參數(shù):obj可以返回其可枚舉屬性的鍵值對的對象。

        • 返回值:給定對象自身可枚舉屬性的鍵值對數(shù)組。

        補充
        • 將Object轉換為Map,new Map()構造函數(shù)接受一個可迭代的entries。借助Object.entries方法你可以很容易的將Object轉換為Map:
        const obj = { foo: "bar", baz: 42 }const map = new Map(Object.entries(obj))console.log(map) // Map { foo: "bar", baz: 42 }

        5)、Object.fromEntries()

        Object.fromEntries()?方法把鍵值對列表轉換為一個對象。與Object.entries()相反。相當于反轉了Object.entries()方法返回的數(shù)據(jù)結構。(下面補充里有具體的演示)
        const entries = new Map([ ['foo', 'bar'], ['baz', 42]]);
        const obj = Object.fromEntries(entries);
        console.log(obj);// Object { foo: "bar", baz: 42 }
        語法
        Object.fromEntries(iterable)
        • 參數(shù):iterable類似Array、Map或者其它實現(xiàn)了可迭代協(xié)議的可迭代對象。

        • 返回值:一個由該迭代對象條目提供對應屬性的新對象。

        補充
        • Map?轉化為?Object
        通過?Object.fromEntries, 可以將Map轉換為Object:
        const map = new Map([ ['foo', 'bar'], ['baz', 42] ])const obj = Object.fromEntries(map)console.log(obj)// { foo: "bar", baz: 42 }
        • Array?轉化為?Object
        通過?Object.fromEntries, 可以將Array轉換為Object:
        const arr = [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]const obj = Object.fromEntries(arr)console.log(obj)// { 0: "a", 1: "b", 2: "c" }
        • 對象轉換
        Object.fromEntries 是與 Object.entries()相反的方法,用?數(shù)組處理函數(shù)?可以像下面這樣轉換對象:
        const object1 = { a: 1, b: 2, c: 3 }
        const object2 = Object.fromEntries( Object.entries(object1) .map(([ key, val ]) => [ key, val * 2 ]))
        // Object.entries(object1) >>> [["a",1],["b",2],["c",3]]
        console.log(object2) // { a: 2, b: 4, c: 6 }

        6)、?Object.prototype.hasOwnProperty()

        上邊枚舉對象屬性時為了避免for..in遍歷繼承來的屬性,給大家補充了可以借助Object.prototype.hasOwnProperty()方法進行判斷,在這里也具體為大家介紹一下它。
        hasOwnProperty()?方法會返回一個布爾值,指示對象自身屬性中是否具有指定的屬性(也就是,是否有指定的鍵)。
        const obj1 = {};obj1.property1 = 42
        console.log(obj1.hasOwnProperty('property1')) // trueconsole.log(obj1.hasOwnProperty('toString')) // falseconsole.log(obj1.hasOwnProperty('hasOwnProperty')) // false
        語法
        obj.hasOwnProperty(prop)
        • 參數(shù):prop 要檢測的屬性的String字符串形式表示的名稱,或者Symbol。

        • 返回值:用來判斷某個對象是否含有指定的屬性的布爾值Boolean。

        注意
        • 只會對自身屬性進行判斷,繼承來的一律返回false。配合for...in使用,可以避免其遍歷繼承來的屬性。
        const o = new Object()o.prop = 'exists'
        console.log(o.hasOwnProperty('prop')) // trueconsole.log(o.hasOwnProperty('toString')) // falseconsole.log(o.hasOwnProperty('hasOwnProperty')) // false
        • 即使屬性的值是 null 或 undefined,只要屬性存在,hasOwnProperty 依舊會返回 true。
        const o = new Object();o.propOne = nullo.propTwo = undefined
        console.log(o.hasOwnProperty('propOne')) // trueconsole.log(o.hasOwnProperty('propTwo')) // true

        7)、?Object.getOwnPropertyNames()

        上邊枚舉對象屬性時也有用到該方法,在這里也具體為大家介紹一下它。
        Object.getOwnPropertyNames()?返回一個數(shù)組,該數(shù)組對元素是 obj自身擁有的枚舉或不可枚舉屬性名稱字符串。數(shù)組中枚舉屬性的順序與通過for...in循環(huán)Object.keys迭代該對象屬性時一致。數(shù)組中不可枚舉屬性的順序未定義。
        const arr = ["a", "b", "c"];console.log(Object.getOwnPropertyNames(arr).sort()) // ["0", "1", "2", "length"]
        // 類數(shù)組對象const obj = { 0: "a", 1: "b", 2: "c"};console.log(Object.getOwnPropertyNames(obj).sort()) // ["0", "1", "2"]
        // 使用Array.forEach輸出屬性名和屬性值Object.getOwnPropertyNames(obj).forEach(function(val, idx, array) { console.log(val + " -> " + obj[val]);})// 0 -> a// 1 -> b// 2 -> c
        // 不可枚舉屬性const my_obj = Object.create({}, { getFoo: { value: function() { return this.foo; }, enumerable: false }});my_obj.foo = 1;
        console.log(Object.getOwnPropertyNames(my_obj).sort())// ["foo", "getFoo"]
        語法
        obj.getOwnPropertyNames(obj)
        -參數(shù):obj一個對象,其自身的可枚舉和不可枚舉屬性的名稱被返回。
        • 返回值:在給定對象上找到的自身屬性對應的字符串數(shù)組。
        補充
        • Object.getOwnPropertyNames和Object.keys的區(qū)別:Object.keys只適用于可枚舉的屬性,而Object.getOwnPropertyNames返回對象的全部屬性名稱(包括不可枚舉的)。
        'use strict'(function () { // 人類的構造函數(shù) const person = function (name, age, sex) { this.name = name this.age = age this.sex = sex this.sing = () => { console.log('sing'); } }
        // new 一個ladygaga const gaga = new person('ladygaga', 26, 'girl') // 給嘎嘎發(fā)放一個不可枚舉的身份證 Object.defineProperty(gaga, 'id', { value: '1234567890', enumerable: false })
        //查看gaga的個人信息 const arr = Object.getOwnPropertyNames(gaga) console.log(arr) // name, age, sex, sing, id // 注意和getOwnPropertyNames的區(qū)別,不可枚舉的id沒有輸出 const arr1 = Object.keys(gaga) console.log(arr1) // name, age, sex, sing})()
        • 如果你只要獲取到可枚舉屬性,可以用Object.keys或用for...in循環(huán)(for...in會獲取到原型鏈上的可枚舉屬性,可以使用hasOwnProperty()方法過濾掉)。

          • 獲取不可枚舉的屬性,可以使用Array.prototype.filter()方法,從所有的屬性名數(shù)組(使用Object.getOwnPropertyNames()方法獲得)中去除可枚舉的屬性(使用Object.keys()方法獲得),剩余的屬性便是不可枚舉的屬性了:
        const target = myObject;const enum_and_nonenum = Object.getOwnPropertyNames(target);const enum_only = Object.keys(target);const nonenum_only = enum_and_nonenum.filter(function(key) { const indexInEnum = enum_only.indexOf(key); if (indexInEnum == -1) { // 沒有發(fā)現(xiàn)在enum_only健集中意味著這個健是不可枚舉的, // 因此返回true 以便讓它保持在過濾結果中 return true; } else { return false; }});
        console.log(nonenum_only);
        注意
        • 在 ES5 中,如果參數(shù)不是一個原始對象類型,將拋出一個 TypeError異常。在 ES2015 中,非對象參數(shù)被強制轉換為對象。
        Object.getOwnPropertyNames('foo') // TypeError: "foo" is not an object (ES5 code)
        Object.getOwnPropertyNames('foo') // ['length', '0', '1', '2'] (ES2015 code)

        8)、?Object.freeze()

        Object.freeze()?方法可以凍結一個對象。一個被凍結的對象再也不能被修改;凍結了一個對象則不能向這個對象添加新的屬性,不能刪除已有屬性,不能修改該對象已有屬性的可枚舉性、可配置性、可寫性,以及不能修改已有屬性的值。此外,凍結一個對象后該對象的原型也不能被修改。freeze()?返回和傳入的參數(shù)相同的對象。
        const obj = { prop: 42}
        Object.freeze(obj)
        obj.prop = 33
        console.log(obj.prop)// 42
        語法
        obj.freeze(obj)
        • 參數(shù):obj要被凍結的對象。

        • 返回值:被凍結的對象。

        補充
        • 被凍結的對象是不可變的。但也不總是這樣。下例展示了凍結對象不是常量對象(淺凍結)。
        const obj1 = { internal: {}}Object.freeze(obj1)
        obj1.internal.a = 'aValue'console.log(obj1.internal.a) // 'aValue'
        • 要使對象不可變,需要遞歸凍結每個類型為對象的屬性(深凍結)。
        // 深凍結函數(shù).function deepFreeze(obj) { // 取回定義在obj上的屬性名 const propNames = Object.getOwnPropertyNames(obj)
        // 在凍結自身之前凍結屬性 propNames.forEach(function(name) { const prop = obj[name]
        // 如果prop是個對象,凍結它 if (typeof prop == 'object' && prop !== null) deepFreeze(prop) })
        // 凍結自身 return Object.freeze(obj);}
        const obj2 = { internal: {}}
        deepFreeze(obj2)obj2.internal.a = 'anotherValue'obj2.internal.a // undefined

        9)、?Object.isFrozen()

        Object.isFrozen()?方法判斷一個對象是否被凍結。
        // 一個對象默認是可擴展的, 所以它也是非凍結的。Object.isFrozen({}) // false
        // 一個不可擴展的空對象同時也是一個凍結對象。var vacuouslyFrozen = Object.preventExtensions({})Object.isFrozen(vacuouslyFrozen) // true
        var frozen = { 1: 81 }Object.isFrozen(frozen) // false
        // 使用Object.freeze是凍結一個對象最方便的方法.Object.freeze(frozen)Object.isFrozen(frozen) // true
        語法
        obj.isFrozen(obj)
        • 參數(shù):obj被檢測的對象。

        • 返回值:表示給定對象是否被凍結的Boolean。

        注意
        • 在 ES5 中,如果參數(shù)不是一個對象類型,將拋出一個TypeError異常。在 ES2015 中,非對象參數(shù)將被視為一個凍結的普通對象,因此會返回true。
        Object.isFrozen(1) // (ES5 code)// TypeError: 1 is not an object
        Object.isFrozen(1) // (ES2015 code)// true

        瀏覽 48
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
          
          

            1. 中国一级片免费 | 舔花核视频 | 亚洲性爱AV | 国内精品久久久久久久影视蜜臀 | 又粗又壮巨龙挤进美妇动态图 |