在第5篇中,講解了多個對象字面量的改進,本節將重點介紹兩個新增的靜態方法,以及對象屬性的重復處理和枚舉順序。
## 一、Object.is()
  此方法用于判斷兩個值是否相同,內部實現了SameValue算法,其行為類似于全等(===)比較,但它認為兩個NaN是相等的,而+0和-0卻是不等的和。Object.is()全等的區別如下所示。
~~~
NaN === NaN; //false
Object.is(NaN, NaN); //true
+0 === -0; //true
Object.is(+0, -0); //false
~~~
## 二、Object.assign()
  此方法可將多個對象合并成一個,它的第一個參數是目標對象,剩余的參數都是源對象,返回值是最終的目標對象,接下來會列舉出此方法的6個特點。
  (1)只能拷貝可枚舉的自有屬性(定義在對象中),無法拷貝繼承屬性(定義在對象原型中)和不可枚舉的屬性。以下面的代碼為例,obj2對象中的name是繼承屬性,age是不可枚舉的屬性,只有school是可枚舉的自有屬性,因此只有school屬性拷貝到了空對象中。
~~~
var obj1 = { name: "strick" },
obj2 = Object.create(obj1); //name是繼承屬性
obj2.age = 28; //age是不可枚舉的屬性
Object.defineProperty(obj2, "age", {
enumerable: false
});
obj2.school = "university"; //school是可枚舉的自有屬性
Object.assign({}, obj2); //{school: "university"}
~~~
  (2)遇到同名的屬性,后面的會覆蓋之前的。例如下面的兩個對象obj1和obj2都包含name屬性,obj1在obj2之前傳到方法中,最終obj1對象的name屬性將被覆蓋掉。
~~~
var obj1 = { name: "strick" },
obj2 = { name: "freedom" };
Object.assign({}, obj1, obj2); //{name: "freedom"}
~~~
  (3)Object.assign()執行的是淺拷貝,如果屬性的值是對象,那么只會拷貝引用該對象的指針。在下面的代碼中,obj1對象的man屬性是一個對象,將其與空對象合并,然后把返回值賦給obj2變量,再修改obj1中的name屬性,由于是淺拷貝,因此obj2中的name屬性也會受影響。
~~~
var obj1 = { man: { name: "strick" } },
obj2 = Object.assign({}, obj1);
obj1.man.name = "freedom";
console.log(obj2); //{man: {name: "freedom"}}
~~~
  (4)Symbol類型的屬性也能被拷貝。Symbol是ES6引入的第6種基本類型,可以像字符串那樣作為對象的屬性名,具體如下所示。
~~~
var obj1 = { [Symbol("name")]: "strick" },
obj2 = Object.assign({}, obj1);
console.log(obj2); //{Symbol(name): "strick"}
~~~
  (5)當源對象的位置是基本類型的值時,它們會被包裝成對象,再進行合并。但由于undefined和null沒有包裝對象,并且數字和布爾值的包裝對象又沒有可枚舉的屬性,因此只有字符串的包裝對象才能不被忽略,最終以數組的形式拷貝到目標對象中,如下所示。
~~~
var obj = Object.assign({}, 1, "a", true, undefined, null);
console.log(obj); //{0: "a"}
~~~
  (6)源對象的訪問器屬性會變成目標對象的數據屬性。如下代碼所示,obj對象包含一個名為name的訪問器屬性,在把它與空對象合并后,目標對象會有一個名為name的數據屬性,其值就是訪問器屬性中get()方法的返回值。
~~~
var obj = {
get name() {
return "strick";
}
};
Object.assign({}, obj); //{name: "strick"}
~~~
## 三、重復屬性
  在ES5的嚴格模式中,重復的屬性名會引起語法錯誤。但ES6不會再做這個檢查,當出現重復屬性時,排在后面的同名屬性將覆蓋前面的,即屬性值以后面的為準,執行過程如下所示。
~~~
var obj = {
name: "strick",
name: "freedom"
};
console.log(obj.name); //"freedom"
~~~
## 四、枚舉順序
  ES6規定了自有屬性的枚舉順序,并且會將同一類別的屬性整合到一塊,具體的排列規則如下所列:
  (1)首先遍歷數字類型或數字字符串的屬性,按大小升序排列。
  (2)接著遍歷字符串類型的屬性,按添加時間的先后順序排列。
  (3)最后遍歷符號類型的屬性,也按添加順序排列。
  for-in循環、JSON對象的序列化方法stringify()、Object對象的getOwnPropertyNames()、keys()、getOwnPropertySymbols()以及新引入的assign()方法在執行過程中都會遵循這套新的排列規則,具體如下所示。
~~~
var obj = {
c: 1,
1: 2,
a: 3,
"0": 4,
[Symbol("x")]: 5,
[Symbol("y")]: 6
};
var properties = [];
for(var key in obj) {
if(obj.hasOwnProperty(key)) { //過濾掉繼承屬性
properties.push(key);
}
}
console.log(properties); //["0", "1", "c", "a"]
JSON.stringify(obj); //{"0":4,"1":2,"c":1,"a":3}
Object.getOwnPropertyNames(obj); //["0", "1", "c", "a"]
Object.keys(obj); //["0", "1", "c", "a"]
Object.getOwnPropertySymbols(obj); //[Symbol(x), Symbol(y)]
Object.assign({}, obj); //{0: 4, 1: 2, c: 1, a: 3, Symbol(x): 5, Symbol(y): 6}
~~~
*****
> 原文出處:
[博客園-ES6躬行記](https://www.cnblogs.com/strick/category/1372951.html)
[知乎專欄-ES6躬行記](https://zhuanlan.zhihu.com/pwes6)
已建立一個微信前端交流群,如要進群,請先加微信號freedom20180706或掃描下面的二維碼,請求中需注明“看云加群”,在通過請求后就會把你拉進來。還搜集整理了一套[面試資料](https://github.com/pwstrick/daily),歡迎瀏覽。

推薦一款前端監控腳本:[shin-monitor](https://github.com/pwstrick/shin-monitor),不僅能監控前端的錯誤、通信、打印等行為,還能計算各類性能參數,包括 FMP、LCP、FP 等。
- ES6
- 1、let和const
- 2、擴展運算符和剩余參數
- 3、解構
- 4、模板字面量
- 5、對象字面量的擴展
- 6、Symbol
- 7、代碼模塊化
- 8、數字
- 9、字符串
- 10、正則表達式
- 11、對象
- 12、數組
- 13、類型化數組
- 14、函數
- 15、箭頭函數和尾調用優化
- 16、Set
- 17、Map
- 18、迭代器
- 19、生成器
- 20、類
- 21、類的繼承
- 22、Promise
- 23、Promise的靜態方法和應用
- 24、代理和反射
- HTML
- 1、SVG
- 2、WebRTC基礎實踐
- 3、WebRTC視頻通話
- 4、Web音視頻基礎
- CSS進階
- 1、CSS基礎拾遺
- 2、偽類和偽元素
- 3、CSS屬性拾遺
- 4、浮動形狀
- 5、漸變
- 6、濾鏡
- 7、合成
- 8、裁剪和遮罩
- 9、網格布局
- 10、CSS方法論
- 11、管理后臺響應式改造
- React
- 1、函數式編程
- 2、JSX
- 3、組件
- 4、生命周期
- 5、React和DOM
- 6、事件
- 7、表單
- 8、樣式
- 9、組件通信
- 10、高階組件
- 11、Redux基礎
- 12、Redux中間件
- 13、React Router
- 14、測試框架
- 15、React Hooks
- 16、React源碼分析
- 利器
- 1、npm
- 2、Babel
- 3、webpack基礎
- 4、webpack進階
- 5、Git
- 6、Fiddler
- 7、自制腳手架
- 8、VSCode插件研發
- 9、WebView中的頁面調試方法
- Vue.js
- 1、數據綁定
- 2、指令
- 3、樣式和表單
- 4、組件
- 5、組件通信
- 6、內容分發
- 7、渲染函數和JSX
- 8、Vue Router
- 9、Vuex
- TypeScript
- 1、數據類型
- 2、接口
- 3、類
- 4、泛型
- 5、類型兼容性
- 6、高級類型
- 7、命名空間
- 8、裝飾器
- Node.js
- 1、Buffer、流和EventEmitter
- 2、文件系統和網絡
- 3、命令行工具
- 4、自建前端監控系統
- 5、定時任務的調試
- 6、自制短鏈系統
- 7、定時任務的進化史
- 8、通用接口
- 9、微前端實踐
- 10、接口日志查詢
- 11、E2E測試
- 12、BFF
- 13、MySQL歸檔
- 14、壓力測試
- 15、活動規則引擎
- 16、活動配置化
- 17、UmiJS版本升級
- 18、半吊子的可視化搭建系統
- 19、KOA源碼分析(上)
- 20、KOA源碼分析(下)
- 21、花10分鐘入門Node.js
- 22、Node環境升級日志
- 23、Worker threads
- 24、低代碼
- 25、Web自動化測試
- 26、接口攔截和頁面回放實驗
- 27、接口管理
- 28、Cypress自動化測試實踐
- 29、基于Electron的開播助手
- Node.js精進
- 1、模塊化
- 2、異步編程
- 3、流
- 4、事件觸發器
- 5、HTTP
- 6、文件
- 7、日志
- 8、錯誤處理
- 9、性能監控(上)
- 10、性能監控(下)
- 11、Socket.IO
- 12、ElasticSearch
- 監控系統
- 1、SDK
- 2、存儲和分析
- 3、性能監控
- 4、內存泄漏
- 5、小程序
- 6、較長的白屏時間
- 7、頁面奔潰
- 8、shin-monitor源碼分析
- 前端性能精進
- 1、優化方法論之測量
- 2、優化方法論之分析
- 3、瀏覽器之圖像
- 4、瀏覽器之呈現
- 5、瀏覽器之JavaScript
- 6、網絡
- 7、構建
- 前端體驗優化
- 1、概述
- 2、基建
- 3、后端
- 4、數據
- 5、后臺
- Web優化
- 1、CSS優化
- 2、JavaScript優化
- 3、圖像和網絡
- 4、用戶體驗和工具
- 5、網站優化
- 6、優化閉環實踐
- 數據結構與算法
- 1、鏈表
- 2、棧、隊列、散列表和位運算
- 3、二叉樹
- 4、二分查找
- 5、回溯算法
- 6、貪心算法
- 7、分治算法
- 8、動態規劃
- 程序員之路
- 大學
- 2011年
- 2012年
- 2013年
- 2014年
- 項目反思
- 前端基礎學習分享
- 2015年
- 再一次項目反思
- 然并卵
- PC網站CSS分享
- 2016年
- 制造自己的榫卯
- PrimusUI
- 2017年
- 工匠精神
- 2018年
- 2019年
- 前端學習之路分享
- 2020年
- 2021年
- 2022年
- 2023年
- 2024年
- 日志
- 2020