5. 對象的擴展

屬性的簡潔表示法

es6允許直接寫入變量和函數(shù)作為對象的屬性的方法

const name='tom';
const obj={
    name,
    sayHi(){
        console.log('hi');
    }
}
//es5
var obj={
    name:name,
    sayHi:function () {
        console.log("hi");
    }
}

使用這種語法可以極大的簡化我們返回對象的寫法

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

屬性名表達式

在es6中允許我們在使用大括號內定義屬性名/方法時使用變量

let key={
  a:1
}
let obj={
    ['name'+'Is']:'tom',
    ['say'+'Hi']:function () {
        console.log("hi");
    }
  [key]:'value'
  //如果屬性名是一個對象,會被自動轉換為[object Object]的形式
}
obj//{nameIs: "tom", sayHi: ?, [object Object]: "value"}

需要注意的是在使用了變量語法時不能使用簡潔表達式,會報錯

在es5中如果不是在大括號的形式下添加對象屬性,同樣可以使用變量定義屬性名

var obj={};
obj['name']='tom';

方法的name屬性

對象的方法也是一個函數(shù),所以也會有name屬性

 var obj={
    say:()=>{
        console.log(this);
    }
};
obj.say.name //say

Object.is()

用來比較兩個值是否嚴格相等,與嚴格運算符'==='的行為基本一致,但是在判別時不會出現(xiàn)像前者一樣的判斷NaN不等于自身或+0等于-0的情況,也不會出現(xiàn)'=='的默認轉換數(shù)據(jù)類型的情況

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

在es5中可以通過如下代碼來部署Object.is

Object.defineProperty(Object,'is',{
    value:function (x,y) {
        if(x===y) {
            return x !== 0 || 1 / x === 1 / y;
        }
        return x!==x&&y!==y;
    },
    configurable:true,
    enumerable:false,
    writable:true
})

Object.assign()

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

Object.assign(target,source1,source2)

注意:如果目標對象與源對象有同名屬性,或多個源對象有同名屬性,那么后面的屬性會覆蓋前面的屬性

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

如果參數(shù)不是對象,該參數(shù)會被轉換為對象然后返回,有undefined和null不是對象,所以如果它們作為參數(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}

Object.assign(undefined) //Uncaught TypeError
typeof Object.assign(2) //object

如果非對象屬性參數(shù)出現(xiàn)在源對象的位置,那么這些參數(shù)如果能夠被轉換為對象,會被轉換,如果不能轉化,則會直接跳過,也就是說,null和undefined只要不出現(xiàn)在首參數(shù),就不會報錯,其它類型的值雖然不會報錯,但是除了字符轉以外,其它值都不會生效,字符串則會被認為是可枚舉對象以數(shù)組對象拷貝到目標對象

Object.assign只拷貝源對象的自身屬性,不拷貝繼承屬性,也不拷貝不可枚舉的屬性,而且該方法實行的是淺拷貝,最后的對象是對源對象的值的引用,也就是說如果源對象的值如果是對象,該值發(fā)生改變,那么都會反應到目標對象上

const target = {},
      obj = {
        a:{
            name:'tom'
        },
        age: 18
      };
Object.assign(target,obj);
console.log(target); //a:{name:'tom'}
obj.a.name="change";
console.log(target); //a:{name: "change"}

對于嵌套的對象,一旦遇到同名屬性,Object.assign的處理方式是替換,而不是添加,這一點需要特別注意

在處理數(shù)組時,如果目標對象和源對象都是數(shù)組,那么目標對象的數(shù)組內的值會被源對象數(shù)組相對位置上的值替換掉

屬性的可枚舉性和遍歷

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

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

描述對象的enumerable屬性,稱為'可枚舉行',如果該屬性為false,就表示某些操作會忽略當前屬性

目前,有四個操作會忽略enumerable為false的屬性。

  • for...in循環(huán):只遍歷對象自身的和繼承的可枚舉的屬性
  • Object.keys():以數(shù)組格式返回對象自身的所有可枚舉的屬性的鍵名
  • JSON.stringify():只串行化對象自身的可枚舉的屬性
  • Object.assign():忽略enumerable為false的屬性,只拷貝對象自身的可枚舉的屬性

這三個操作,前三個是es5就有的,其中for...in會返回繼承的屬性,其它三個方法都會忽略繼承的屬性,只處理對象自身的屬性。實際上,引入"可枚舉"這一概念的最初目的就是讓某些屬性可以規(guī)避掉for...in操作,不然所有內部屬性和方法都會被遍歷到,比如,對象原型的toString方法,以及數(shù)組的length屬性,就通過設置"可枚舉"為false來避免被for...in遍歷到

另外,在es6中,所有class的原型的方法都是不可枚舉的

總體來說,大多數(shù)時候我們只關心對象自身的屬性,所以盡量使用Object.keys()來替代for...in循環(huán)

屬性的遍歷

ES6一共有5種可以遍歷對象的屬性

  • for...in

    循環(huán)遍歷對象自身的和繼承的可枚舉屬性

  • Object.keys()

    Object.keys返回一個數(shù)組,包含對象自身的(不包含繼承的)所有可枚舉屬性的鍵名

  • Object.getOwnPropetyNames(obj)

    返回一個數(shù)組,包含對象自身的所有屬性(包含不可枚舉屬性)的鍵名

  • Object.getOwnpropetySymbols(obj)

    返回一個數(shù)組,包含對象自身的所有Symbol屬性的鍵名

  • Reflet.ownKeys(obj)

    返回對象所有的鍵名,包括Symbol

    以上的五種方法遍歷對象的鍵名,都遵守同樣的屬性遍歷的次序規(guī)則

    1. 首先遍歷所有的數(shù)值鍵,按照數(shù)值升序排列
    2. 其次遍歷所有的字符串鍵,按照加入時間升序排列
    3. 最后遍歷說有Symbol鍵,按照加入時間升序排列

super關鍵字

es6新加入一個關鍵字,用于指向當前對象的原型對象


?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容