Object.defineProperty,Object.assign,Object.keys 簡介

Object.defineProperty()

語法:數組

Object.defineProperty(obj, prop, descriptor)

參數說明:函數

obj:必需。目標對象 
prop:必需。需定義或修改的屬性的名字
descriptor:必需。目標屬性所擁有的特性測試

返回值:this

傳入函數的對象。即第一個參數objspa

針對屬性,咱們能夠給這個屬性設置一些特性,好比是否只讀不能夠寫;是否能夠被for..inObject.keys()遍歷。code

給對象的屬性添加特性描述,目前提供兩種形式:數據描述和存取器描述。對象

數據描述

當修改或定義對象的某個屬性的時候,給這個屬性添加一些特性:blog

var obj = {
    test:"hello"
}
//對象已有的屬性添加特性描述
Object.defineProperty(obj,"test",{
    configurable:true | false,
    enumerable:true | false,
    value:任意類型的值,
    writable:true | false
});
//對象新添加的屬性的特性描述
Object.defineProperty(obj,"newKey",{
    configurable:true | false,
    enumerable:true | false,
    value:任意類型的值,
    writable:true | false
});

 

數據描述中的屬性都是可選的,來看一下設置每個屬性的做用。繼承

value

屬性對應的值,能夠使任意類型的值,默認爲undefined索引

var obj = {}
//第一種狀況:不設置value屬性
Object.defineProperty(obj,"newKey",{

});
console.log( obj.newKey );  //undefined
------------------------------
//第二種狀況:設置value屬性
Object.defineProperty(obj,"newKey",{
    value:"hello"
});
console.log( obj.newKey );  //hello

 

writable

屬性的值是否能夠被重寫。設置爲true能夠被重寫;設置爲false,不能被重寫。默認爲false。

var obj = {}
//第一種狀況:writable設置爲false,不能重寫。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false
});
//更改newKey的值
obj.newKey = "change value";
console.log( obj.newKey );  //hello

//第二種狀況:writable設置爲true,能夠重寫
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:true
});
//更改newKey的值
obj.newKey = "change value";
console.log( obj.newKey );  //change value

 

enumerable

此屬性是否能夠被枚舉(使用for...in或Object.keys())。設置爲true能夠被枚舉;設置爲false,不能被枚舉。默認爲false。

var obj = {}
//第一種狀況:enumerable設置爲false,不能被枚舉。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false
});

//枚舉對象的屬性
for( var attr in obj ){
    console.log( attr );  
}
//第二種狀況:enumerable設置爲true,能夠被枚舉。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:true
});

//枚舉對象的屬性
for( var attr in obj ){
    console.log( attr );  //newKey
}

 

configurable

是否能夠刪除目標屬性或是否能夠再次修改屬性的特性(writable, configurable, enumerable)。設置爲true能夠被刪除或能夠從新設置特性;設置爲false,不能被能夠被刪除或不能夠從新設置特性。默認爲false。

這個屬性起到兩個做用:

  1. 目標屬性是否能夠使用delete刪除

  2. 目標屬性是否能夠再次設置特性

//-----------------測試目標屬性是否能被刪除------------------------
var obj = {}
//第一種狀況:configurable設置爲false,不能被刪除。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:false
});
//刪除屬性
delete obj.newKey;
console.log( obj.newKey ); //hello

//第二種狀況:configurable設置爲true,能夠被刪除。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:true
});
//刪除屬性
delete obj.newKey;
console.log( obj.newKey ); //undefined

//-----------------測試是否能夠再次修改特性------------------------
var obj = {}
//第一種狀況:configurable設置爲false,不能再次修改特性。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:false
});

//從新修改特性
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:true,
    enumerable:true,
    configurable:true
});
console.log( obj.newKey ); //報錯:Uncaught TypeError: Cannot redefine property: newKey

//第二種狀況:configurable設置爲true,能夠再次修改特性。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:true
});

//從新修改特性
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:true,
    enumerable:true,
    configurable:true
});
console.log( obj.newKey ); //hello

 

除了能夠給新定義的屬性設置特性,也能夠給已有的屬性設置特性

//定義對象的時候添加的屬性,是可刪除、可重寫、可枚舉的。
var obj = {
    test:"hello"
}

//改寫值
obj.test = 'change value';

console.log( obj.test ); //'change value'

Object.defineProperty(obj,"test",{
    writable:false
})


//再次改寫值
obj.test = 'change value again';

console.log( obj.test ); //依然是:'change value'

 

提示:一旦使用Object.defineProperty給對象添加屬性,那麼若是不設置屬性的特性,那麼configurable、enumerable、writable這些值都爲默認的false

var obj = {};
//定義的新屬性後,這個屬性的特性中configurable,enumerable,writable都爲默認的值false
//這就致使了neykey這個是不能重寫、不能枚舉、不能再次設置特性
//
Object.defineProperty(obj,'newKey',{

});

//設置值
obj.newKey = 'hello';
console.log(obj.newKey);  //undefined

//枚舉
for( var attr in obj ){
    console.log(attr);
}

 

設置的特性總結:

value: 設置屬性的值
writable: 值是否能夠重寫。true | false
enumerable: 目標屬性是否能夠被枚舉。true | false
configurable: 目標屬性是否能夠被刪除或是否能夠再次修改特性 true | false

存取器描述

當使用存取器描述屬性的特性的時候,容許設置如下特性屬性:

var obj = {};
Object.defineProperty(obj,"newKey",{
    get:function (){} | undefined,
    set:function (value){} | undefined
    configurable: true | false
    enumerable: true | false
});

 

注意:當使用了getter或setter方法,不容許使用writable和value這兩個屬性

getter/setter

當設置或獲取對象的某個屬性的值的時候,能夠提供getter/setter方法。

  • getter 是一種得到屬性值的方法

  • setter是一種設置屬性值的方法。

在特性中使用get/set屬性來定義對應的方法。

var obj = {};
var initValue = 'hello';
Object.defineProperty(obj,"newKey",{
    get:function (){
        //當獲取值的時候觸發的函數
        return initValue;    
    },
    set:function (value){
        //當設置值的時候觸發的函數,設置的新值經過參數value拿到
        initValue = value;
    }
});
//獲取值
console.log( obj.newKey );  //hello

//設置值
obj.newKey = 'change value';

console.log( obj.newKey ); //change value

 

注意:get或set不是必須成對出現,任寫其一就能夠。若是不設置方法,則get和set的默認值爲undefined

configurable和enumerable同上面的用法。

 ——————————————————————————————————————————————————————

Object.assign()

 

基本用法

Object.assign方法用於對象的合併,將源對象( source )的全部可枚舉屬性,複製到目標對象( target )。

var target = { a: 1, b: 1 };  
var source1 = { b: 2, c: 2 };  
var source2 = { c: 3 };  
Object.assign(target, source1, source2);  
target // {a:1, b:2, c:3}  

若是隻有一個參數,Object.assign會直接返回該參數。

var obj = {a: 1};  
Object.assign(obj) === obj // true  

若是該參數不是對象,則會先轉成對象,而後返回。

typeof Object.assign(2) // "object"  

因爲undefined和null沒法轉成對象,因此若是它們做爲參數,就會報錯。

Object.assign(undefined) //  報錯  
Object.assign(null) //  報錯  

若是非對象參數出如今源對象的位置(即非首參數),那麼處理規則有所不一樣。首先,這些參數都會轉成對象,若是沒法轉成對象,就會跳過。這意味着,若是undefined和null不在首參數,就不會報錯。

let obj = {a: 1};  
Object.assign(obj, undefined) === obj // true  
Object.assign(obj, null) === obj // true  

其餘類型的值(即數值、字符串和布爾值)不在首參數,也不會報錯。可是,除了字符串會以數組形式,拷貝入目標對象,其餘值都不會產生效果。

var v1 = 'abc';  
var v2 = true;  
var v3 = 10;  
var obj = Object.assign({}, v1, v2, v3);  
console.log(obj); // { "0": "a", "1": "b", "2": "c" }  

上面代碼中,v一、v二、v3分別是字符串、布爾值和數值,結果只有字符串合入目標對象(以字符數組的形式),數值和布爾值都會被忽略。這是由於只有字符串的包裝對象,會產生可枚舉屬性。

Object(true) // {[[PrimitiveValue]]: true}  
Object(10) // {[[PrimitiveValue]]: 10}  
Object('abc') // {0: "a", 1: "b", 2: "c", length: 3, [[PrimitiveValue]]: "abc"}  

上面代碼中,布爾值、數值、字符串分別轉成對應的包裝對象,能夠看到它們的原始值都在包裝對象的內部屬性[[PrimitiveValue]]上面,這個屬性是不會被Object.assign拷貝的。只有字符串的包裝對象,會產生可枚舉的實義屬性,那些屬性則會被拷貝。

 

Object.assign拷貝的屬性是有限制的,只拷貝源對象的自身屬性(不拷貝繼承屬性),也不拷貝不可枚舉的屬性(enumerable: false)。

Object.assign({b: 'c'},  
    Object.defineProperty({}, 'invisible', {  
        enumerable: false,  
        value: 'hello'  
    })  
)  
// { b: 'c' }  

上面代碼中,Object.assign要拷貝的對象只有一個不可枚舉屬性invisible,這個屬性並無被拷貝進去。
屬性名爲 Symbol 值的屬性,也會被Object.assign拷貝。

Object.assign({ a: 'b' }, { [Symbol('c')]: 'd' })  
// { a: 'b', Symbol(c): 'd' }  

 

 ——————————————————————————————————————————————

Object.key()

 

Object.keys(),使用該方法返回一個數組

傳入對象,返回屬性名

var obj = {'a':'123','b':'345'};
console.log(Object.keys(obj));  //['a','b']

var obj1 = { 100: "a", 2: "b", 7: "c"};
console.log(Object.keys(obj1)); // console: ["2", "7", "100"]

var obj2 = Object.create({}, { getFoo : { value : function () { return this.foo } } });
obj2.foo = 1;
console.log(Object.keys(obj2)); // console: ["foo"]

 

構造函數 返回空數組或者屬性名

 function Pasta(name, age, gender) {
            this.name = name;
            this.age = age;
            this.gender = gender;
            this.toString = function () {
                    return (this.name + ", " + this.age + ", " + this.gender);
            }
    }

    console.log(Object.keys(Pasta)); //console: []

    var spaghetti = new Pasta("Tom", 20, "male");
    console.log(Object.keys(spaghetti)); //console: ["name", "age", "gender", "toString"]

數組 返回索引

  var arr = ["a", "b", "c"];
    console.log(Object.keys(arr)); // console: ["0", "1", "2"]

 

傳入字符串,返回索引

var str = 'ab1234';
console.log(Object.keys(obj));  //[0,1,2,3,4,5]
相關文章
相關標籤/搜索