JavaScript對象API解密

JavaScript對象API解密

創建對象得倆種方式

var o = new Object()
var o = {} // 推薦使用

該構造器可以接受任何類型得參數,並且會自動識別參數得類型,並選擇更合適得構造器來完成相關得操作

var o = new Object('something');
o.constructor; // ƒ String() { [native code] }
var n = new Object(123);
n.constructor; // ƒ Number() { [native code] }

Object構造器得成員

Object.prototype

該屬性是所有對象得原型(包括Object對象本身),語言中得其他對象正是通過對該屬性上添加東西來實現它們之間得繼承關係得,所有要小心使用

var s = new String('smallPig')
Object.prototype.num = 1
console.log(s.num)  //1

Object.prototype得成員

Object.prototype.constructor

該屬性只想用來構造該函數對象得構造器,在這裏爲Object()

Object.prototype.constructor ===  Object // true
var o = new Object()
o.constructor === Object //true

Object.prototype.hasOwnProperty(pop)

該方法僅在目標屬性爲對象自身屬性時返回true,而當該屬性是從原型鏈中繼承而來或根本不存在時,返回false

var o = {prop:1};
o.hasOwnProperty('prop'); // true
o.hasOwnProperty('toString'); // false
o.hasOwnProperty('formString'); // false

Object.prototype.isPrototypeOf(obj)

如果目標對象是當前對象得原型,該方法就會返回true,而且,當前對象所在原型上得所有對象都能通過該測試,並不侷限與他得直系關係

var s = new String('');
Object.prototype.isPrototypeOf(s); // true
String.prototype.isPrototypeOf(s); // true
Array.prototype.isPrototypeOf(s); // false

ES5中附加得Object屬性

Object.defineProperty()

[https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty]:

ES5中引入了屬性描述符得概念,我們可以通過對所定義的屬性有更大的控制權

  • value ==>當視圖獲取屬性時所返回的值
  • writable==>該屬性是否可寫
  • enumerable==>該屬性在for in循環中是否會被枚舉
  • configurable==>該屬性是否可被刪除
  • set==>該屬性的更新操作所調用的函數
  • get==>獲取屬性值所調用的函數

數據描述符(其中屬性爲:enumerableconfigurablevaluewritable)與存取描述符(其中屬性爲enumerableconfigurableset()get())之間是有互斥關係的。 在定義了set()get()之後,描述符會認爲存取操作已被 定義了,其中再定義valuewritable引起錯誤

ES3風格的屬性定義方式

var person = {}
person.legs = 2

等價的ES5通過數據描述符定義屬性的方式

var person = {}
Object.defineProperty(person,'legs',{
	value:2,
	writable:true,
	configurable:true,
	enumerable:true
})

其中,除了value的默認值爲undefined以外,其他的默認值都爲false.這就意味着,如果想要通過這一方式定義一個可寫的屬性,必須顯示講它們設爲true.或者,我們也可以通過ES5的存儲描述符來定義

var person = {}
Object.defineProperty(person, 'legs', {
    set:function(v) {
        return this.value = v;
    },
    get: function(v) {
        return this.value;
    },
    configurable: true,
    enumerable: true
});
person.legs = 2;

這樣一來,多了許多可以用來描述屬性的代碼,如果想要防止別人篡改我們的屬性,就必須要用到它們。

var person = {};
Object.defineProperty(person, 'heads', {value: 1});
person.heads = 0; // 0
person.heads; // 1  (改不了)
delete person.heads; // false
person.heads // 1 (刪不掉)
Object.defineProperty(obj, prop, descriptor) (ES5)

Vue.js文檔:如何追蹤變化 把一個普通 JavaScript 對象傳給 Vue 實例的 data 選項,Vue 將遍歷此對象所有的屬性,並使用 Object.defineProperty 把這些屬性全部轉爲 getter/setter。Object.defineProperty 是僅 ES5 支持,且無法 shim 的特性,這也就是爲什麼 Vue 不支持 IE8 以及更低版本瀏覽器的原因。

Object.defineProperty()方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性, 並返回這個對象。

Object.defineProperties(obj, props) (ES5)

該方法的作用與defineProperty()基本相同,只不過它可以用來一次定義多個屬性。 比如:

var glass = Object.defineProperties({}, {
    'color': {
        value: 'transparent',
        writable: true
    },
    'fullness': {
        value: 'half',
        writable: false
    }
});
glass.fullness; // 'half'

Object.freeze(obj)(ES5)

Object.isFrozen(obj)(ES5)

freeze()方法用於執行一切不受seal()方法限制的屬性值變更。Object.freeze() 方法可以凍結一個對象,凍結指的是不能向這個對象添加新的屬性,不能修改其已有屬性的值,不能刪除已有屬性,以及不能修改該對象已有屬性的可枚舉性、可配置性、可寫性。也就是說,這個對象永遠是不可變的。該方法返回被凍結的對象。

var deadline = Object.freeze({date: 'yesterday'});
deadline.date = 'tomorrow';
deadline.excuse = 'lame';
deadline.date; // 'yesterday'
deadline.excuse; // undefined
Object.isSealed(deadline); // true;
Object.isFrozen(deadline); // true
Object.getOwnPropertyDescriptor(deadline, 'date');
// {value: "yesterday", writable: false, enumerable: true, configurable: false} (不可配置,不可寫)
Object.keys(deadline); // ['date'] (可枚舉)

Object.keys(obj)(ES5)

該方法時一種特殊得for in循環。它只返回當前對象得屬性(不像for-in),而且這些屬性也必須是可枚舉的(這點和Object.getOwnPropertyNames()不同,不論是否可以枚舉)。返回值是一個字符串數組。

Object.prototype.customProto = 101;
Object.getOwnPropertyNames(Object.prototype);
// [..., "constructor", "toLocaleString", "isPrototypeOf", "customProto"]
Object.keys(Object.prototype); // ['customProto']
var o = {own: 202};
o.customProto; // 101
Object.keys(o); // ['own']

ES6中附加得Object屬性

Object.is(value1,value2)(ES6)

該方法用來比較兩個值是否嚴格相等。它與嚴格比較運算符(===)的行爲基本一致。 不同之處只有兩個:一是+0不等於-0,而是NaN等於自身。

Object.is('小豬頭', '小豬頭'); // true
Object.is({},{}); // false
Object.is(+0, -0); // false
+0 === -0; // true
Object.is(NaN, NaN); // true
NaN === NaN; // false

ES5可以通過以下代碼部署object.is

Object.defineProperty(Object,'is',{
	value:function(x,y){
		 if (x === y) {
           // 針對+0不等於-0的情況
           return x !== 0 || 1 / x === 1 / y;
        }
        // 針對 NaN的情況
        return x !== x && y !== y;
	},
	configurable: true,
    enumerable: false,
    writable: true
})

Object.assign(target,...sources)(ES6)

該方法用來源對象sources得所有可枚舉得屬性賦值到目標對象target.它至少需要倆個對象作爲參數,第一個參數時目標對象target,後面得參數都是源對象source只要一個參數不是對象,就會拋出TypeError錯誤

var target = {a: 1};
var source1 = {b: 2};
var source2 = {c: 3};
obj = Object.assign(target, source1, source2);
target; // {a:1,b:2,c:3}
obj; // {a:1,b:2,c:3}
target === obj; // true
// 如果目標對象與源對象有同名屬性,或多個源對象有同名屬性,則後面的屬性會覆蓋前面的屬性。
var source3 = {a:2,b:3,c:4};
Object.assign(target, source3);
target; // {a:2,b:3,c:4}

Object.assign只複製自身屬性,不可枚舉的屬性(enumerablefalse)和繼承的屬性不會被複制。

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

屬性名爲Symbol值的屬性,也會被Object.assign()複製。

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

對於嵌套的對象,Object.assign()的處理方法是替換,而不是添加。

Object.assign({a: {b:'c',d:'e'}}, {a:{b:'hello'}});
// {a: {b:'hello'}}

Object.values(obj)(ES8)

Object.values() 方法與Object.keys類似。返回一個給定對象自己的所有可枚舉屬性值的數組,值的順序與使用for...in循環的順序相同 ( 區別在於for-in循環枚舉原型鏈中的屬性 )。

var obj = {a:1,b:2,c:3};
Object.keys(obj); // ['a','b','c']
Object.values(obj); // [1,2,3]

Object.entries(obj)(ES8)

Object.entries() 方法返回一個給定對象自己的可枚舉屬性[key,value]對的數組,數組中鍵值對的排列順序和使用 for...in 循環遍歷該對象時返回的順序一致(區別在於一個for-in循環也枚舉原型鏈中的屬性)。

var obj = {a:1,b:2,c:3};
Object.keys(obj); // ['a','b','c']
Object.values(obj); // [1,2,3]
Object.entries(obj); // [['a',1],['b',2],['c',3]]

原文鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章