Math.max 實現得到陣列中最大的一項
var array = [1,2,3,4,5]; var max = Math.max.apply(null, array); console.log(max); // 5
呼叫的時候第一個引數給了一個null,這個是因為沒有物件去呼叫這個方法,只需要用這個方法幫助運算,得到返回的結果就行,所以直接傳遞了一個null過去。
Math.min 實現得到陣列中最小的一項
var array = [1,2,3,4,5]; var min= Math.min.apply(null, array); console.log(min); // 1
在原生物件上面新增max與min方法
那就會需要用到原生物件方法Object.defineProperty()
,會直接在一個物件上定義一個新屬性,或者修改一個物件的現有屬性, 並返回這個物件
Object.defineProperty(Array.prototype, 'max', { writable: false, enumerable: false, configurable: true, value: function () { return Math.max.apply(null, this); } }); Object.defineProperty(Array.prototype, 'min', { writable: false, enumerable: false, configurable: true, value: function () { return Math.min.apply(null, this); } });
直接在陣列上呼叫即可:
var arr = [54,545,2165,545,56]; console.log(arr.max()); console.log(arr.min());
上面講到了Object.defineProperty的方法,下面我們來理解下。
Object.defineProperty的使用
物件是由多個名/值對組成的無序的集合。物件中每個屬性對應任意型別的值。定義物件可以使用建構函式或字面量的形式:
var obj = new Object; //obj = {} obj.name = "張三"; //新增描述 obj.say = function(){}; //新增行為
除了以上新增屬性的方式,還可以使用Object.defineProperty
定義新屬性或修改原有的屬性。
Object.defineProperty()描述
語法:Object.defineProperty(obj, prop, descriptor)
引數說明:
-
obj:必需。目標物件
-
prop:必需。需定義或修改的屬性的名字
-
descriptor:必需。目標屬性所擁有的特性
返回值:
-
傳入函式的物件。即第一個引數obj
針對屬性,我們可以給這個屬性設定一些特性,比如是否只讀不可以寫;是否可以被for..in
或Object.keys()
遍歷。
給物件的屬性新增特性描述,目前提供兩種形式:資料描述和存取器描述。
資料描述
當修改或定義物件的某個屬性的時候,給這個屬性新增一些特性:
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。
這個屬性起到兩個作用:
-
目標屬性是否可以使用delete刪除
-
目標屬性是否可以再次設定特性
//-----------------測試目標屬性是否能被刪除------------------------ 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 //這就導致了newkey這個是不能重寫、不能列舉、不能再次設定特性 // 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
通過Object.defineProperty給一個物件的某個屬性新增多個方法,如下例子:
var obj = {}; Object.defineProperty(obj,'atrr',{ get:function(){ var self = this; var num = 0; return { add:function(value){ return num + value; }, reduce:function(value){ return num - value; } } } }); console.log(obj.atrr.add(5)); //5 console.log(obj.atrr.add(8)); //8 console.log(obj.atrr.reduce(8)); //-8
說明:在obj物件的atrr物件上新增了兩個方法add與reduce.
相容性
在ie8下只能在DOM物件上使用,嘗試在原生的物件使用 Object.defineProperty()
會報錯。