參考書《ECMAScript 6入門》http://es6.ruanyifeng.com/對象的擴展1.屬性名的簡潔表示法 : ES6允許在代碼中直接寫變數,變數名是屬性名,變數值是屬性值。 let key = "value"; let obj = {key};//obj {key : "value ...
參考書《ECMAScript 6入門》
http://es6.ruanyifeng.com/
對象的擴展
1.屬性名的簡潔表示法 : ES6允許在代碼中直接寫變數,變數名是屬性名,變數值是屬性值。
let key = "value";
let obj = {key};//obj {key : "value"}
2.方法的簡寫表示法
let obj = {
method : function(x,y){
return {x,y};//{x:x,y:y} 屬性簡寫法在方法中的使用
}
}
同
let obj = {
method(x,y){
return {x,y};
}
}
3.屬性表達式: obj[表達式]="value"
a.用{}定義對象時定義屬性的兩種方式
var obj = {
length : 3,
name : "test"
}//ES5的方式
let obj = {
["leng" + "th"] : 3,
["na"+"me"] : "test"
}//ES6的方式
function test2(){
return true;
}
function ["test" + 2](){
return true;
}報錯
let ["test" + 4] = function(){}//報錯
let ["test" + 4] = new Function(){}//報錯
let obj = {
["test" + 4](){
return true;
}
}正確
obj //{test4: ƒ}
b.讀取對象中屬性的方式
obj.name
obj['name']
c.使用表達式定義屬性的方式不可以與屬性簡寫法混用
let a = 1;
let obj = {
["name"+1] : {[a]}//報錯
}
let a = 1;
let obj = {
["name"+1] : {a}//正確
}
d.當表達式定義的屬性名是一個對象時,表達式運行結果是[Object object],不是對象對應的屬性名
let size = 3;
let clothes = {size};
let obj2 = {
["test" + obj] : "testagain"
}
obj2//{test[object Object]: "testagain"}
4.對象的name屬性:對象里的方法的name屬性返回方法所對應的方法名
a.如果是對象里的get方法或者set方法,則對象方法的name屬性返回get/set + 函數名
let cat = {
age:1,
set mini(a){
this.age = age;
}
get mini(){
return this.age;
}
}
cat.mini.name //undefined
Object.getOwnPropertyDescriptor(cat,'mini').get.name //'get mini'
Object.getOwnPropertyDescriptor(cat,'mini').set.name//'set mini'
b.bind方法創造的對象的函數,name屬性返回的是"bound" + 方法名
let obj = {
test(){}
}
obj.test.bind().name //"bound test"
c.使用new Function方法創建的函數,name屬性返回的是"anonymous" + 方法名
(new Function()).name //"anonymous"
(new Function()).bind().name // "bound anonymous"
5.Object.is() //嚴格相等判斷
相等判斷
"==" //ES5
1 == '1' //true 即使1與'1'類型並不相同還是會判斷它們相等,這是因為==引起了數據轉換
"==="//ES5
1 === '1' //false 類型不同判斷為false,比==規則更嚴格
undefined === undefined //true
null === null //true
NaN === NaN //false ===漏洞
+0 === -0 //true ===漏洞
Object.is(a,b) //ES6 判斷a,b是否相等
Object.is(1,2) //false
Object.is(1,2) //false
Object.is(1,'1') //false
Object.is(undefined,undefined)//true
Object.is(null,null)//true
在NaN與+0,-0的判斷上比===更準確,其他與 === 一致
Object.is(NaN,NaN) //true
Object.is(+0,-0) //false
6.Object.assign() : 用於將源對象的所有可枚舉屬性複製到目標對象上
a.此方法可以有多個參數,首參數一定是目標對象,不可以為null或者undefined,會報錯;其餘參數是源對象,當其餘參數不是對象時,只有字元串類型會生效,其他數值,布爾類型都不會生效,遇到不能轉化成對象的null或者undefined,則會跳過,不出錯。
Object.assign(null,{name : "test"}) //報錯 Cannot convert undefined or null to object
Object.assign(null,{name : "test"})//報錯 Cannot convert undefined or null to object
Object.assign(1,{name : "test"}); //Number {1, name: "test"} 首參數不是對象時,會先轉成對象
Object.assign({},undefined); //{}
Object.assign({},null);//{}
b.當其餘參數不是對象時,只有字元串類型會以數組形式生效,其他數值,函數以及布爾類型都不會生效,
Object.assign({},'abc');//{0: "a", 1: "b", 2: "c"}
Object.assign({},100);// {}
Object.assign({},true);//{}
let f = function(){}
Object.assign({},f);//{}
d.用途
(1)可以用來複制對象(淺拷貝)
let target = {name: "target"}
let source = {size: 13}
let newobj = Object.assign(target,source);//得到新的target {name: "target", size: 13}
newobj //{name: "target", size: 13}
target //{name: "target", size: 13}
target.size = 0;
newobj.size // {name: "target", size: 0}
newobj.size = 1;
target //{name: "target", size: 1} newobj與target是一個對象,任何一方的改動都會影響到另一方
//淺拷貝
let target = {name:"target"}
let source = {cat:{name: "nn",age: "3"}}
Object.assign(target,source); //{name:"target",cat:{name: "nn",age: "3"}}
source.cat.name = "big";
target.cat.name;// "big"
(2)如果源對象中有和目標對象同名的屬性,則源對象中的此屬性會全部覆蓋目標對象中的此屬性
let target = {
cat:{
name: "nn",
age: "3",
color: "black"
}
}
let source = {
cat: {
name:"bigdeck"
}
}
Object.assign(target,source);//{cat: cat: {name: "bigdeck"}} /source覆蓋target的整個cat屬性值,並不會只覆蓋cat.name
(3)如果目標對象和源對象都是數組,則會將數組當做對象來處理
Object.assign(['a','b','c'],[1,3]); //[1,3,'c']
這是因為處理時視為對象處理Object.assign({1:'a',2:'b',3:'c'},{1:1,2:3});
(4)如果要複製的值是一個取值就、函數,則會先執行取值函數後賦值
let obj = {
cat : "nn",
get cat(){
return "cat";
},
set cat(a){
this.cat = "a";
}
}
Object.assign({},obj);//{cat: "cat"}
(5)可以為對象添加屬性
Object.assign({},{name:"test"});//{name:"test"}
class Cat{
constructor(age,color){
return Object.assign(this,{age,color});
}
}
var c1 = new Cat(13,"white")
c1 //cat {age: 13, color: "white"}
(6)可以為對象添加函數
Object.assign(c1,{run(){return "run fast";}});
c1//Cat {age: 13, color: "white", run: ƒ}
Object.assign(c1.__proto__,{run2(){return "run fast";}});
c1.__proto__ //{run2: ƒ, constructor: ƒ}
c1 //Cat {age: 13, color: "white", run: ƒ}
(7)克隆對象
Object.assign({},c1);//Cat {age: 13, color: "white", run: ƒ}
Object.assign(Object.create(Object.getPrototypeOf(c1)),c1);//Cat {age: 13, color: "white", run: ƒ}
(8)合併多個對象
Object.assign({},{name:"test"},{age:13},{size:10});//{name: "test", age: 13, size: 10}
let merge = (target,...sources) => Object.assign(target,sources);
merge({},{name:"test"},{age:13},{size:10});//{name: "test", age: 13, size: 10}
merge({},[{name:"test"},{age:13},{size:10}]);//{0: {name: "test"}, 1: {age: 13}, 2: {size: 10}}
(9)為屬性指定預設值
const DEFAULT = {
name : "test"
}
function init(){
var c = Object.assign({},DEFAULT,options);
return c;
}
init({name:"test2"});//利用了Object.assign同名屬性後面的會全覆蓋前面的同名屬性的特點實現了給屬性指定預設值(如果後面的對象沒有與預設對象同名的屬性,則使用預設對象中的屬性)
7.屬性的可枚舉性與遍歷
(1)可枚舉性
Object.getOwnPropertyDescriptor()可以拿到對象的某個屬性的描述對象
Object.getOwnPropertyDescriptor(c1,'age')
{
configurable:true,
enumerable:true,//此屬性為true,表示被此對象描述的的屬性是可枚舉屬性;false則為不可枚舉屬性
value:13,
writable:true
}
有四個操作會忽略enumerable為false的屬性
for...in迴圈:只遍歷對象自身的和繼承的可枚舉屬性
Object.keys():返回對象自身的所有可枚舉屬性的鍵名
JSON.stringify():只串列化對象自身的可枚舉的屬性
Object.assign():忽略enumerable為false的屬性,只拷貝對象自身的可枚舉的屬性
//父類
function Animal(){
this.name = 'Animal';
this.age = 13;
this.size = 100;
}
Object.defineProperties(Animal,{'gender':{value:"boy",enumerable:false},'color':{value:"red",enumerable:true}});
//原型鏈繼承
function Cat(){
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
Cat.prototype.name = 'cat';
Cat.ownSize = 10;
//new一個實例
var cat = new Cat();
Object.defineProperties(cat,{'sizecat':{value:1,enumerable:false},'colorcat':{value:"black",enumerable:true}});
for(var i in cat){
console.log(i+" : "+cat[i]);
}
//colorcat : black自身的可枚舉屬性
//name : 繼承自Cat的可枚舉屬性
//age : 13 繼承字Animal的可枚舉的屬性
//size : 100繼承自Animal的可枚舉的屬性
//constructor : function Cat(){}構造器
Object.keys(cat)//['colorcat'] cat自身可枚舉的屬性
JSON.stringify(cat)//'{"colorcat":"black"}' cat自身可枚舉的屬性
Object.assign({},cat);//{colorcat: "black"} cat自身可枚舉的屬性
(2)屬性的遍歷
for...in:只遍歷對象自身的和繼承的可枚舉屬性
Object.keys(obj):返回對象自身的所有可枚舉屬性的鍵名
Object.getOwnPropertyNames(obj):返回一個數組,包含對象自身的所有屬性的鍵名,這個所有屬性包含不可枚舉屬性但是不包含symbol屬性的鍵名
Object.getOwnPropertyNames(cat);
// ["sizecat", "colorcat"] 'sizecat'對象自身的不可枚舉屬性,'colorcat'對象自身的可枚舉屬性
Object.getOwnPropertySymbols(obj):返回一個數組,包含對象自身的所有Symbol屬性的鍵名
Object.getOwnPropertySymbols(cat);
//[] cat沒有Symbol屬性
Reflect.ownKeys(obj):返回一個數組,包含對象自身的所有屬性的鍵名,不管這個屬性是Symbol還是字元串,也不管是否可枚舉
Reflect.ownKeys(cat);
//["sizecat", "colorcat"] 'sizecat'對象自身的不可枚舉屬性,'colorcat'對象自身的可枚舉屬性
屬性的遍歷順序
首先遍歷所有數值鍵,按照數值升序排列
其次遍歷所有的字元串鍵,按照時間加入順序升序排列
最後遍歷所有的Symbol鍵,按照時間加入順序升序排列
var obj = {1:2,"test":"again","a":"testing",2:3}
obj["objSymbol"] = Symbol()
Reflect.ownKeys(obj);//["1", "2", "test", "a", "objSymbol"]
8.Object.getOwnPropertyDescriptor()與Object.getOwnPropertyDescriptors()
Object.getOwnPropertyDescriptor()返回某個對象屬性的描述對象(此屬性非繼承屬性)
Object.getOwnPropertyDescriptor(cat,'name')//undefined 因為name是繼承屬性
Object.getOwnPropertyDescriptor(cat,'colorcat')// {value: "black", writable: false, enumerable: true, configurable: false} 因為colorcat是自身屬性
Object.getOwnPropertyDescriptors() 返回指定對象所有的自身屬性(非繼承屬性)的描述對象。
Object.getOwnPropertyDescriptors(cat);
//
{
catSymbol:{value: Symbol(), writable: true, enumerable: true, configurable: true}
colorcat:{value: "black", writable: false, enumerable: true, configurable: false}
sizecat:{value: 1, writable: false, enumerable: false, configurable: false}
}
9._proto_屬性,getPrototypeOf()與setPrototypeOf()
(1)_proto_屬性:用於讀取或設置當前對象的prototype對象
var d = {name:"test"}
//讀取對象的__proto__
d.__proto__ //{constructor: ƒ Object(), __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
//設置對象的__proto__
var c = {1:0};
d.__proto__ = c //返回的是c {1: 0}
(2)Object.getPrototypeOf(param):用於讀取一個對象的原型對象。如果參數不是對象,則轉化成對象;如果不能轉化成對象,如undefined或者null,則會報錯。
Object.getPrototypeOf(d) //{1: 0}
Object.getPrototypeOf(1)//Number {0, constructor: ƒ, toExponential: ƒ, toFixed: ƒ, toPrecision: ƒ, toString: ƒ, …}
Object.getPrototypeof(undefined)//報錯 Uncaught TypeError: Object.getPrototypeof is not a function
(3)Object.setPrototypeOf(obj1,obj2):用來設置當前對象的prototype對象,返回參數對象本身。
//將obj2設置為obj1的原型對象。如果第一個參數不是對象,則轉化為對象,但因為返回的是第一個參數,所以沒有變化;如果第一個參數不能轉化成對象,如undefined或者null,則會報錯。
Object.setPrototypeOf(d,Number); //Function {name: "test"}
Object.getPrototypeOf(d);//ƒ Number() { [native code] }
10.super關鍵字:指向當前對象的原型對象
//super關鍵字在表示對象的原型時,只能用在對象的方法中,用在其他方法中都會報錯。
let obj = {
name:super.name//報錯 super用在屬性中
}
let obj = {
method:function(){
return super.name;//報錯 super用在方法中,然後賦值給屬性
}
}
let obj = {
method = ()=> super.name;//報錯 super用在方法中,然後賦值給屬性
}
let obj1 = {
name:"obj1"
}
let obj2 = {
name:"obj2",
method(){
return super.name;//正確 obj1
}
}
Object.setPrototypeOf(obj2, obj1);
obj2.method //"obj1"
11.Object.keys(),Object.values()與Object.entries()
Object.keys():返回一個數組,數組成員是對象自身(不包含可繼承)所有可遍歷屬性的鍵名
Object.values():返回一個數組,數組成員是對象自身所有可遍歷屬性的鍵值
Object.entries():返回一個數組,數組成員是對象自身所有可遍歷的鍵值對
12.對象的擴展運算符
對象的擴展運算符...可以用於對象的解構賦值
(1)擴展運算符
可用於賦值對象
let obj = {name : "test",age : 13}
let obj3 = {...obj}
obj3 // {name: "test", age: 13}
如果參數是null或者undefined,將會忽略不報錯
{...null}//{}
{...undefined}//{}
(2)解構賦值:解構賦值時,使用擴展運算符的參數必須是最後一個參數
let {x,y,...z} = {x : "test",y : 13,size:23,color:"black"}
x = "test"
y = 13
z = {size:23,color:"black"}
let {...x,y,z} = {x : "test",y : 13,size:23,color:"black"} //報錯