屬性的簡潔表示法
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ī)則
- 首先遍歷所有的數(shù)值鍵,按照數(shù)值升序排列
- 其次遍歷所有的字符串鍵,按照加入時間升序排列
- 最后遍歷說有Symbol鍵,按照加入時間升序排列
super關鍵字
es6新加入一個關鍵字,用于指向當前對象的原型對象