摘要:需要鏈接標(biāo)準(zhǔn)參考教程對象阮一峰標(biāo)準(zhǔn)構(gòu)造器函數(shù)可能是最重要的對象之一,盡管我們從來不會直接調(diào)用它。該方法返回被凍結(jié)的對象。
Object 需要鏈接: MDN —— Object JavaScript標(biāo)準(zhǔn)參考教程(Object對象)——阮一峰
標(biāo)準(zhǔn)構(gòu)造器函數(shù)Object可能是JavaScript最重要的對象之一,盡管我們從來不會直接調(diào)用它。每當(dāng)使用一個對象直接量時,都會隱式調(diào)用它:
var a = {}; // 等同于var a = new Object() var b = {x:1,y:2}; // 等同于var b = new Object({x:1,y:2});
構(gòu)造函數(shù)定義了數(shù)據(jù)類型,所以表達(dá)式var a = new Object()表明兩件事情:a是Object的一個實(shí)例,而a的原型是Object.prototype。我們用對象字面量創(chuàng)建的每個對象都會獲得由Object.prototype定義的行為
以下將討論幾個常用的主要的屬性方法 1. Object()// 首先,將Object作為構(gòu)造函數(shù)調(diào)用和對象字面量直接定義是等價的 var o = {}; var o2 = new Object(); // 注意這里所說的等價不是指相等,是指其本身和原型繼承相同 // 當(dāng)然也可以 var a = {}; var a2 = new Object(a); console.log(a===a2); // trueObject本身作為工具方法
// 返回一個Object構(gòu)造器實(shí)例 var obj = Object(); console.log(obj instanceof Object); // true // 返回一個字符串構(gòu)造器實(shí)例 var str = Object("string"); console.log(str instanceof Object); // true 等價 new String("string") // 返回一個數(shù)字構(gòu)造器實(shí)例 var num = Object(123); console.log(num instanceof Object); // true 等價 new Number(123) // 返回一個布爾構(gòu)造器實(shí)例 var boo = Object(true); // 等價 new Boolean(true) var boo2 = Object(false); console.log(boo instanceof Object && boo2 instanceof Object); // true // null存在的意義在于對象引用之中,null值最初含義為:沒有引用任何對象 // null型只能取null一個值,null值是一個字面量,但是對null進(jìn)行typeof結(jié)果為對象 console.log(typeof null); // object console.log(Object(null) instanceof Object); // true // 對null調(diào)用Object方法,返回一個空對象 // undefined型也只能取undefined一個值,對undefined進(jìn)行typeof ,值為undefined console.log(typeof undefined); // undefined console.log(Object(undefined) instanceof Object); // true // 也是返回一個空對象
Object()傳入?yún)?shù)為基本類型值,則返回值為其類型的構(gòu)造函數(shù)的實(shí)例。Object本身當(dāng)作工具方法使用時,可以將任意值轉(zhuǎn)為對象。這個方法常用于保證某個值一定是對象。如果參數(shù)是原始類型的值,Object方法返回對應(yīng)的包裝對象的實(shí)例
上面探討的是基礎(chǔ)類型值,那如果是引用類型值呢?
var arr = [1,2,3]; console.log(Object(arr)); // 把原對象返回了 console.log(Object(arr)===arr); // true var fn = function () {}; // 把原函數(shù)返回了 console.log(Object(fn)); // function () {} console.log(Object(fn)===fn); // true var obj = {x:"obj.x"}; console.log(Object(obj)); // [object Object] console.log(Object(obj)===obj); // true // 一個判斷是否是對象的函數(shù) function judgeObj(obj) { return Object(obj)===obj? true : false; } console.log(judgeObj([])); // true console.log(judgeObj(true)); // false console.log(judgeObj({})); // true console.log(judgeObj(123)); // false當(dāng)Object()傳入的參數(shù)是引用類型值,則會返回原對象; 2. Object.keys(obj)
受Enumerable條件限制,且不可枚舉原型鏈中的屬性Object.keys() 方法會返回一個由一個給定對象的自身可枚舉屬性組成的數(shù)組,數(shù)組中屬性名的排列順序和使用 for...in 循環(huán)遍歷該對象時返回的順序一致 (兩者的主要區(qū)別是 一個 for-in 循環(huán)還會枚舉其原型鏈上的屬性)。
// 無法枚舉到原型鏈中的屬性 var obj = Object.create({y:20}); obj.x = 10; console.log(Object.keys(obj)); // "x" // 無法枚舉Enumerable為false屬性 Object.defineProperty(obj,"z",{ value:"z", enumerable:false }) console.log(Object.keys(obj)); // "x" // 對于數(shù)組對象 var arr = ["a","b","c"]; console.log(Object.keys(arr)); // "0,1,2" // 對于隨機(jī)排列的數(shù)組對象 var obj_ramdom = {100:"a",2:"b",50:"c"}; console.log(Object.keys(obj_ramdom)); // "2,50,100"詳細(xì)說明:MDN —— Object.keys() 3. Object.getOwnPropertyNames(obj)
不受Enumerable條件限制,但不可枚舉原型鏈中屬性Object.getOwnPropertyNames 返回一個數(shù)組,該數(shù)組對元素是 obj 自身擁有的枚舉或不可枚舉屬性名稱字符串。 數(shù)組中枚舉屬性的順序與通過 for...in 循環(huán)(或 Object.keys)迭代該對象屬性時一致。 數(shù)組中不可枚舉屬性的順序未定義。
如果你只要獲取到可枚舉屬性,查看 Object.keys 或用 for...in循環(huán)(還會獲取到原型鏈上的可枚舉屬性,不過可以使用hasOwnProperty()方法過濾掉)。
// 無法枚舉到原型鏈中的屬性 var obj = Object.create({y:20}); obj.x = 10; console.log( Object.getOwnPropertyNames(obj) ); // "x" // 可以枚舉Enumerable為false的屬性 Object.defineProperty(obj,"z",{ value:"z", enumerable:false }) console.log( Object.getOwnPropertyNames(obj) ); // "x,z" // 對于數(shù)組對象(length屬性為不可枚舉) var arr = ["a","b","c"]; console.log( Object.getOwnPropertyNames(arr) ); // "0,1,2,length" // 對于隨機(jī)排列的數(shù)組對象 var obj_ramdom = {100:"a",2:"b",50:"c"}; console.log( Object.getOwnPropertyNames(obj_ramdom) ); // "2,50,100"詳細(xì):MDN —— Object.getOwnPropertyNames() for-in、Object.keys、Object.getOwnPropertyNames特點(diǎn)區(qū)分 三者關(guān)于是否受Enumerable的限制測試
var obj = {x:10,y:20}; Object.defineProperty(obj,"z",{ value:30, enumerable:false, }); // for-in for (var a in obj) { console.log(a); // "x,y" } // Object.keys console.log( Object.keys(obj) // "x,y" ); // Object.getOwnPropertyNames() console.log( Object.getOwnPropertyNames(obj) // "x,y,z" );三者關(guān)于是否可以枚舉原型鏈的測試
function Test() { this.x = 10; this.y = 20; } Test.prototype.z = 30; // z為原型鏈屬性 var obj = new Test(); // for-in for (var a in obj) { console.log(a) // "x,y,z" } // Object-keys console.log( Object.keys(obj) // "x,y" ) // Object.getOwnPropertyNames() console.log( Object.getOwnPropertyNames(obj) // "x,y" )
我們?nèi)绾斡洃浤??就記最特殊的?/p> for-in:只有它可以枚舉原型鏈里的屬性,并且它也不是Object對象的方法 Object.getOwnPropertyNames():只有它可以享有Enumerable的"豁免權(quán)",不管如何設(shè)置只要是這個對象上的自有屬性都可以枚舉到! 對象屬性控制相關(guān)方法 四個相關(guān)的方法在這里先列出,這里要要提到數(shù)據(jù)屬性和訪問器屬性
《JS高程》—— 數(shù)據(jù)屬性與訪問器屬性
強(qiáng)薦:阮一峰 —— 屬性描述對象
4. Object.defineProperty()5. Object.getOwnPropertyDescriptor()Object.defineProperty() 方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現(xiàn)有屬性, 并返回這個對象。
6. Object.defineProperties()Object.getOwnPropertyDescriptor() 返回指定對象上一個自有屬性對應(yīng)的屬性描述符。(自有屬性指的是直接賦予該對象的屬性,不需要從原型鏈上進(jìn)行查找的屬性)
// 采用Object.defineProperty定義的屬性,如果不顯示定義 // enumerable,configurable,writable值默認(rèn)為false(與對象字面量相反) var obj = {}; Object.defineProperty(obj,"x",{ value:"obj.x" }); // 使用Object.getOwnPropertyDescriptor()獲取屬性對象 var obj_attr = Object.getOwnPropertyDescriptor(obj,"x"); for (var i in obj_attr) { document.write(i+" : "+obj_attr[i]+"
") } // 默認(rèn)下數(shù)據(jù)屬性都是false
Object.defineProperties() 方法直接在一個對象上定義新的屬性或修改現(xiàn)有屬性,并返回該對象。
var obj = {}; Object.defineProperties(obj,{ x:{ value:"obj.x", writable:true, enumerable:true, configurable:true }, y:{ value:"obj.y", writable:true, enumerable:true, configurable:true }, z:{ value:"obj.z" } }) console.log(Object.keys(obj)); // "x,y" z屬性enumerable默認(rèn)為false // 當(dāng)然,z屬性的數(shù)據(jù)屬性都是false沖突:
《JavaScript編程全解》:只要將get屬性與set屬性指定為相應(yīng)的函數(shù),就能夠定義一個只能夠通過訪問器getter和setter來訪問值的屬性。訪問器與value屬性是互相排斥的,也就是說,如果指定了value屬性的值,訪問器(包括get和set)就會失效;反之,如果指定了訪問器(get或set中的某一個亦或是都存在),value屬性就會失效。
《JS高程3》:不一定非要同時指定getter和setter。只指定getter意味著屬性是不能寫,嘗試寫入屬性會被忽略。在嚴(yán)格模式下,嘗試寫入只指定了getter函數(shù)的的屬性會拋出錯誤。類似地,沒有指定setter函數(shù)的屬性也不能讀,否則在非嚴(yán)格模式下會返回undefined,在嚴(yán)格模式下會拋出錯誤。
var obj = {_x:10}; // 定義一個訪問器屬性 Object.defineProperty(obj,"x",{ get:function () { return this._x } }) // 讀取obj.x會隱式調(diào)用訪問器屬性,返回obj._x的值(下劃線代表此屬性只能通過訪問器讀寫) console.log(obj.x); // 10 // 嘗試為訪問器屬性賦值 // 直接賦值 obj.x = "aaa"; console.log(obj.x); // 10 賦值失敗 // 獲取obj.x的attributes var objxAttr = Object.getOwnPropertyDescriptor(obj,"x"); for (var i in objxAttr) { document.write( i+" | "+objxAttr[i]+"
" ) } // get | function () { return this._x } // set | undefined // enumerable | false // configurable | false // 不可寫的原因是value屬性與訪問器屬性沖突,即(get、set)與value屬性沖突 // 可以通過查看attributes屬性,判斷屬性是否是訪問器屬性還是數(shù)據(jù)屬性,存在set或者get的是訪問器屬性
具體內(nèi)容請移步至相關(guān)知識點(diǎn)進(jìn)行更深入學(xué)習(xí),這里只介紹方法基礎(chǔ)用法
對象狀態(tài)相關(guān)方法 Object.preventExtensions()如果一個對象可以添加新的屬性,則這個對象是可擴(kuò)展的。preventExtensions 可以讓這個對象變的不可擴(kuò)展,也就是不能再有新的屬性。需要注意的是不可擴(kuò)展的對象的屬性通常仍然可以被刪除。嘗試給一個不可擴(kuò)展對象添加新屬性的操作將會失敗,不過可能是靜默失敗,也可能會拋出 TypeError 異常(嚴(yán)格模式)。
Object.preventExtensions 只能阻止一個對象不能再添加新的自身屬性,仍然可以為該對象的原型添加屬性。然而Object.preventExtensions會阻止一個對象將__proto__屬性重新指向另一個對象。
// Object.preventExtensions將原對象變的不可擴(kuò)展,并且返回原對象 var obj = {}; var obj2 = Object.preventExtensions(obj); alert(obj===obj2); // true obj.x = "obj.x"; alert(obj.x); // undefined // 采用對象字面量定義的對象默認(rèn)可擴(kuò)展 var o = {}; alert(Object.isExtensible(o)); // true // 當(dāng)然,通過調(diào)用方法可以阻止 Object.preventExtensions(o); alert(Object.isExtensible(o)); // false // 使用Object.defineProperty方法為一個不可擴(kuò)展的對象添加新屬性會拋出異常. var o2 = {a:"a"}; Object.preventExtensions(o2); Object.defineProperty(o2,"b",{ value:"test" }) // "Uncaught TypeError: Cannot define property:b, object is not extensible." // 一個不可擴(kuò)展對象的原型是不可更改的,__proto__是個非標(biāo)準(zhǔn)魔法屬性,可以更改一個對象的原型. var b = Object.preventExtensions({x:1,y:2}); b.__proto__ = {a:10,b:20}; // "Uncaught TypeError: #
詳細(xì):MDN —— Object.preventExtensions()
Object.seal()通常情況下,一個對象是可擴(kuò)展的(可以添加新的屬性)。密封一個對象會讓這個對象變的不能添加新屬性,且所有已有屬性會變的不可配置。屬性不可配置的效果就是屬性變的不可刪除,以及一個數(shù)據(jù)屬性不能被重新定義成為訪問器屬性,或者反之。但屬性的值仍然可以修改。嘗試刪除一個密封對象的屬性或者將某個密封對象的屬性從數(shù)據(jù)屬性轉(zhuǎn)換成訪問器屬性,結(jié)果會靜默失敗或拋出TypeError 異常(嚴(yán)格模式)。
不會影響從原型鏈上繼承的屬性。但 _proto_ ( ) 屬性的值也會不能修改。
// 默認(rèn)可以修改屬性,添加屬性 var obj = { a:"a", b:"b" }; // 密封對象Object.seal(),注意方法會返回原對象 obj = Object.seal(obj); console.log(Object.isSealed(obj)); // true // 依然可以修改屬性上的值 obj.a = "Rewrite obj.a"; obj.b = "Rewrite obj.b"; console.log(obj.a+" | "+obj.b); // "Rewrite obj.a | Rewrite obj.b" // 但是除此之外的操作都無法完成 obj.z = "obj.z"; console.log(obj.z); // undefined 新屬性寫入失敗 console.log(delete obj.a); // false 刪除失敗 // 無法定義訪問器屬性 Object.defineProperty(obj,"b",{ // "Uncaught TypeError: Cannot redefine property: b" get:function () { return this.b; } }); // 方法也無法寫入新屬性 Object.defineProperty(obj,"z",{ // 拋出TypeError異常 value:"obj.z" }); console.log(obj.z); // "Uncaught TypeError: Cannot define property:z, object is not extensible."Object.freeze()
Object.freeze() 方法可以凍結(jié)一個對象,凍結(jié)指的是不能向這個對象添加新的屬性,不能修改其已有屬性的值,不能刪除已有屬性,以及不能修改該對象已有屬性的可枚舉性、可配置性、可寫性。也就是說,這個對象永遠(yuǎn)是不可變的。該方法返回被凍結(jié)的對象。
// 默認(rèn)可以修改屬性,添加屬性,刪除屬性等操作 var obj = { a:"a", b:"b", o:{} }; // 調(diào)用Object.freeze obj = Object.freeze(obj); // 現(xiàn)在任何對對象的操作都會失敗,嚴(yán)格模式下會TypeError異常 console.log(delete obj.a); // false obj.z = "obj.z"; console.log(obj.z); // undefined // 但是非凍結(jié)對象依然可以修改,對象內(nèi)數(shù)組、對象等引用類型 obj.o.fn = function () {console.log("yes")}; obj.o.fn(); // "yes" 添加成功MDN提供了一個完全凍結(jié)對象的函數(shù):
obj = { internal : {} }; Object.freeze(obj); obj.internal.a = "aValue"; obj.internal.a // "aValue" // 想讓一個對象變的完全凍結(jié),凍結(jié)所有對象中的對象,我們可以使用下面的函數(shù). function deepFreeze (o) { var prop, propKey; Object.freeze(o); // 首先凍結(jié)第一層對象. for (propKey in o) { prop = o[propKey]; if (!o.hasOwnProperty(propKey) || !(typeof prop === "object") || Object.isFrozen(prop)) { // 跳過原型鏈上的屬性和已凍結(jié)的對象. continue; } deepFreeze(prop); //遞歸調(diào)用. } } obj2 = { internal : {} }; deepFreeze(obj2); obj2.internal.a = "anotherValue"; obj2.internal.a; // undefinedObject.isExtensible()、Object.isSealed()、Object.isFrozen()
為對應(yīng)的檢測方法:
嚴(yán)格程度升序:preventExtensions —— seal —— freeze鏈接:
MDN:Object.isExtensible()
MDN:Object.isSealed()
MDN:Object.isFrozen()
Object.isExtensible():
默認(rèn)情況下,對象是可擴(kuò)展的:即可以為他們添加新的屬性。以及它們的 proto 屬性可以被更改。Object.preventExtensions,Object.seal 或 Object.freeze 方法都可以標(biāo)記一個對象為不可擴(kuò)展(non-extensible)。
Object.isSealed():
// 新建對象默認(rèn)不可密封 var obj = {}; console.log(Object.isSealed(obj)); // false // 如果是空對象變?yōu)椴豢蓴U(kuò)展preventExtensions,則對象也會變成密封對象 obj = Object.preventExtensions(obj); console.log( Object.isExtensible(obj)+" | " +Object.isSealed(obj) ) // false | true 不可擴(kuò)展 | 密封 // 但不是空對象,則不會發(fā)生上面情況,記住:密封對象與Configurable屬性相關(guān)聯(lián) var obj2 = {x:"obj2.x"}; Object.preventExtensions(obj2); console.log( Object.isExtensible(obj2)+" | " +Object.isSealed(obj2) ) // false | false 不可擴(kuò)展 | 不密封 // 反過來設(shè)置configurable設(shè)置為false,則自動變?yōu)槊芊鈱ο? var o = {a:"o.a"}; Object.preventExtensions(o); Object.defineProperty(o,"a",{ configurable:false }); console.log( Object.isSealed(o) ); // true // 直接生成一個密封對象 var obj_seal = {}; Object.seal(obj_seal); // 當(dāng)然密封對象也可以是凍結(jié)對象 Object.isFrozen(obj_seal); // true var o2 = Object.seal({a:"o2.a"}); console.log(Object.isFrozen(o2)); // false 依舊可更改o2.a屬性
Object.isFrozen()
一個對象是凍結(jié)的(frozen)是指它不可擴(kuò)展,所有屬性都是不可配置的(non-configurable),且所有數(shù)據(jù)屬性(data properties)都是不可寫的(non-writable)
// 一個對象默認(rèn)是可擴(kuò)展的,所以它也是非凍結(jié)的. assert(Object.isFrozen({}) === false); // 一個不可擴(kuò)展的空對象同時也是一個凍結(jié)對象. var vacuouslyFrozen = Object.preventExtensions({}); assert(Object.isFrozen(vacuouslyFrozen) === true); // 一個非空對象默認(rèn)也是非凍結(jié)的. var oneProp = { p: 42 }; assert(Object.isFrozen(oneProp) === false); // 讓這個對象變的不可擴(kuò)展,并不意味著這個對象變成了凍結(jié)對象, // 因?yàn)閜屬性仍然是可以配置的(而且可寫的). Object.preventExtensions(oneProp); assert(Object.isFrozen(oneProp) === false); // ...如果刪除了這個屬性,則它會成為一個凍結(jié)對象. delete oneProp.p; assert(Object.isFrozen(oneProp) === true); // 一個不可擴(kuò)展的對象,擁有一個不可寫但可配置的屬性,則它仍然是非凍結(jié)的. var nonWritable = { e: "plep" }; Object.preventExtensions(nonWritable); Object.defineProperty(nonWritable, "e", { writable: false }); // 變得不可寫 assert(Object.isFrozen(nonWritable) === false); // 把這個屬性改為不可配置,會讓這個對象成為凍結(jié)對象. Object.defineProperty(nonWritable, "e", { configurable: false }); // 變得不可配置 assert(Object.isFrozen(nonWritable) === true); // 一個不可擴(kuò)展的對象,擁有一個不可配置但可寫的屬性,則它仍然是非凍結(jié)的. var nonConfigurable = { release: "the kraken!" }; Object.preventExtensions(nonConfigurable); Object.defineProperty(nonConfigurable, "release", { configurable: false }); assert(Object.isFrozen(nonConfigurable) === false); // 把這個屬性改為不可寫,會讓這個對象成為凍結(jié)對象. Object.defineProperty(nonConfigurable, "release", { writable: false }); assert(Object.isFrozen(nonConfigurable) === true); // 一個不可擴(kuò)展的對象,值擁有一個訪問器屬性,則它仍然是非凍結(jié)的. var accessor = { get food() { return "yum"; } }; Object.preventExtensions(accessor); assert(Object.isFrozen(accessor) === false); // ...但把這個屬性改為不可配置,會讓這個對象成為凍結(jié)對象. Object.defineProperty(accessor, "food", { configurable: false }); assert(Object.isFrozen(accessor) === true); // 使用Object.freeze是凍結(jié)一個對象最方便的方法. var frozen = { 1: 81 }; assert(Object.isFrozen(frozen) === false); Object.freeze(frozen); assert(Object.isFrozen(frozen) === true); // 一個凍結(jié)對象也是一個密封對象. assert(Object.isSealed(frozen) === true); // 當(dāng)然,更是一個不可擴(kuò)展的對象. assert(Object.isExtensible(frozen) === false);Object.getPrototypeOf()
給定對象的原型。如果沒有繼承屬性,則返回 null 。
var obj = {}; console.log(Object.getPrototypeOf(obj) === Object.prototype); // true var fn = function () {}; console.log(Object.getPrototypeOf(fn) === Function.prototype); // true var arr = []; console.log(Object.getPrototypeOf(arr) === Array.prototype); // true var q = {x:"x"}; var p = Object.create(q); console.log(Object.getPrototypeOf(p) === q); // true // 如果參數(shù)不是引用類型,將拋出異常 var num = 123; Object.getPrototypeOf(num); // "Uncaught TypeError: Object.getPrototypeOf called on non-object"Object實(shí)例方法 Object.prototype.valueOf()
JavaScript 調(diào)用 valueOf() 方法用來把對象轉(zhuǎn)換成原始類型的值(數(shù)值、字符串和布爾值)。 你很少需要自己調(diào)用此函數(shù);當(dāng)遇到一種需要轉(zhuǎn)換成一個原始值情況時候, JavaScript 會自動調(diào)用此函數(shù)。
默認(rèn)情況下, valueOf() 會被每個對象Object繼承。每一個內(nèi)置對象都會覆蓋這個方法為了返回一個合理的值,如果對象沒有原始值,valueOf() 就會返回對象自身。
你可以在自己的代碼中使用 valueOf 方法用來把內(nèi)置對象的值轉(zhuǎn)換成原始值。 當(dāng)你創(chuàng)建了自定義對象時,你可以覆蓋 Object.prototype.valueOf() 并調(diào)用來取代 Object 方法。
JavaScript的許多內(nèi)置對象都重寫了該函數(shù),以實(shí)現(xiàn)更適合自身的功能需要。因此,不同類型對象的valueOf()方法的返回值和返回值類型均可能不同。
// Array:返回數(shù)組本身 var arr = [1,2,3,"Array"]; console.log(arr+" | "+(arr.valueOf() === arr)); // "1,2,3,Array | true" // String:返回當(dāng)前字符串 var str = "string"; console.log(str.valueOf() === str); // true // Number:返回當(dāng)前值 var num = 123; console.log(num.valueOf() === num); // true // Boolean:返回當(dāng)前布爾值 var boo = true; // 布爾值 console.log(boo.valueOf() === boo); // true // 這里是布爾對象 var boo2 = new Boolean(false); // 布爾對象 console.log(boo2.valueOf()); // false console.log(typeof boo2.valueOf()); // boolean // 注意:這里對布爾對象操作,返回的是原值的boolean類型,而不在是引用類型 // Date:從1970年1月1日到現(xiàn)在的毫秒數(shù) var date = new Date(); console.log(date.valueOf()); // "1497789410938" // function: 返回當(dāng)前函數(shù) var fn = function () {console.log("fn")}; (fn.valueOf())(); // fn // Object: 返回對象本身 var obj = {x:"obj.a"}; console.log(obj.valueOf() === obj); // true
當(dāng)然也可以覆蓋方法:
var obj = {a:1}; obj.valueOf = function () {return this.a} console.log(obj+1); // 2 // 這里隱式調(diào)用了valueOf方法Object.prototype.toString()
每個對象都有一個 toString() 方法,當(dāng)對象被表示為文本值時或者當(dāng)以期望字符串的方式引用對象時,該方法被自動調(diào)用。默認(rèn)情況下,toString() 方法被每個繼承自O(shè)bject的對象繼承。如果此方法在自定義對象中未被覆蓋,toString() 返回 "[object type]",其中type是對象類型。
// toString返回對象的字符串形式,默認(rèn)情況下返回類型字符串 var o1 = new Object(); var o2 = {a:1}; console.log(o1.toString()); console.log(o2.toString()); // "[object Object]" // 當(dāng)然可以自定義它 var obj = {}; obj.toString = function () {return 1} console.log(2+obj); // 3關(guān)于toString()更詳細(xì)的可以看這里: 阮一峰 toString()的應(yīng)用:判斷數(shù)據(jù)類型 Object.prototype.toLocaleString()
Object.prototype.hasOwnProperty()Object"s toLocaleString 返回調(diào)用 toString() 方法的結(jié)果。
var num = 123; console.log(num.toString() === num.toLocaleString()); // true var obj = {}; console.log(obj.toString() === obj.toLocaleString()); // true
所有繼承了 Object 的對象都會繼承到 hasOwnProperty 方法。這個方法可以用來檢測一個對象是否含有特定的自身屬性;和 in 運(yùn)算符不同,該方法會忽略掉那些從原型鏈上繼承到的屬性。
// 判斷屬性書否存在 var obj = {x:"obj.x"}; console.log(obj.hasOwnProperty("x")); // true delete obj.x; console.log(obj.hasOwnProperty("x")); // false // 判斷自身屬性還是繼承屬性 var p = {z:10}; var o = Object.create(p); o.a = 20; console.log(o.hasOwnProperty("a")+" | "+o.hasOwnProperty("z")); // true | false console.log(o.hasOwnProperty("toString")); // false console.log(o.hasOwnProperty("hasOwnProperty")); // false // 遍歷一個對象的自身屬性 var o1 = {z:"o1.z"}; var o2 = Object.create(o1); o2.x = "o2.x"; o2.y = "o2.y"; for (var i in o2) { if (o2.hasOwnProperty(i)) { console.log("自身屬性:"+i+" | "+"value:"+(o2[i])); } else { console.log(i+"不是自身屬性") } } // "自身屬性:x | value:o2.x" // "自身屬性:y | value:o2.y" // "z不是自身屬性"
hasOwnProperty也可以重寫,所以需要注意這一點(diǎn):
var foo = { hasOwnProperty: function() { return false; }, bar: "Here be dragons" }; foo.hasOwnProperty("bar"); // 始終返回 false // 如果擔(dān)心這種情況,可以直接使用原型鏈上真正的 hasOwnProperty 方法 ({}).hasOwnProperty.call(foo, "bar"); // true // 也可以使用 Object 原型上的 hasOwnProperty 屬性 Object.prototype.hasOwnProperty.call(foo, "bar"); // trueObject.prototype.isPrototypeOf()
Object.prototype.propertyIsEnumerable()isPrototypeOf 方法允許你檢查一個對象是否存在于另一個對象的原型鏈上。
function fn1() { this.a = "a"; } function fn2() { this.b = "b"; } fn2.prototype = new fn1(); function fn3() { this.c = "c"; } fn3.prototype = new fn2(); function fn4() { this.d = "d"; } fn4.prototype = new fn3(); var test = new fn4(); console.log( test.hasOwnProperty("a")+ " | "+test.hasOwnProperty("b")+" | "+test.hasOwnProperty("c")+" | "+test.hasOwnProperty("d") ) // "false | false | false | true"
MDN:Object.prototype.propertyIsEnumerable()每個對象都有 propertyIsEnumerable 方法。該方法可以判斷出指定對象里的屬性是否可枚舉,也就是說該屬性是否可以通過 for...in 循環(huán)等遍歷到,不過有些屬性雖然可以通過 for...in 循環(huán)遍歷到,但因?yàn)樗鼈儾皇亲陨韺傩?,而是從原型鏈上繼承的屬性,所以該方法也會返回false。如果對象沒有指定的屬性,該方法返回 false。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/83512.html
摘要:目錄導(dǎo)語對象對象小結(jié)導(dǎo)語本系列文章將重點(diǎn)講解提供的原生庫標(biāo)準(zhǔn)庫,只要在支持語言的平臺,標(biāo)準(zhǔn)庫中的提供的對象的屬性和方法都能使用對象對象的理解講的標(biāo)準(zhǔn)庫,首先要從對象談起,因?yàn)橹蟮乃袑ο蠖伎梢钥醋鍪菍ο髽?gòu)造出來的因此,對象可以看做是一個構(gòu) 目錄 導(dǎo)語 1. Object對象 2. Array對象 3. 小結(jié) 導(dǎo)語 本系列文章將重點(diǎn)講解JavaScript提供的原生庫——標(biāo)準(zhǔn)庫,只要...
摘要:目錄導(dǎo)語包裝對象的理解三大包裝對象的知識點(diǎn)小結(jié)導(dǎo)語包裝對象是為了彌補(bǔ)基本數(shù)據(jù)類型的非對象特性而產(chǎn)生的,對于基本類型值而言,本來是不存在屬性和方法的,但是我們可以在使用字面量創(chuàng)建字符串時,調(diào)用例如的方法,那么其內(nèi)在原理究竟是什么呢閱讀完本篇文 目錄 導(dǎo)語 1. 包裝對象的理解 2. 三大包裝對象的知識點(diǎn) 3. 小結(jié) 導(dǎo)語 包裝對象是為了彌補(bǔ)基本數(shù)據(jù)類型的非對象特性而產(chǎn)生的,對于基本類型...
摘要:,微軟發(fā)布,同時發(fā)布了,該語言模仿同年發(fā)布的。,公司在瀏覽器對抗中沒落,將提交給國際標(biāo)準(zhǔn)化組織,希望能夠成為國際標(biāo)準(zhǔn),以此抵抗微軟。同時將標(biāo)準(zhǔn)的設(shè)想定名為和兩類。,尤雨溪發(fā)布項(xiàng)目。,正式發(fā)布,并且更名為。,發(fā)布,模塊系統(tǒng)得到廣泛的使用。 前言 作為程序員,技術(shù)的落實(shí)與鞏固是必要的,因此想到寫個系列,名為 why what or how 每篇文章試圖解釋清楚一個問題。 這次的 why w...
摘要:由于計算機(jī)的國際化,組織的標(biāo)準(zhǔn)牽涉到很多其他國家,因此組織決定改名表明其國際性。規(guī)范由萬維網(wǎng)聯(lián)盟制定。級標(biāo)準(zhǔn)級標(biāo)準(zhǔn)是不存在的,級一般指的是最初支持的。 這篇筆記的內(nèi)容對應(yīng)的是《JavaScript高級程序設(shè)計(第三版)》中的第一章。 1.ECMA 和 ECMA-262 ECMA 是歐洲計算機(jī)制造商協(xié)會的縮寫,全程是 European Computer Manufacturers Ass...
摘要:一般我們對這種構(gòu)造函數(shù)命名都會采用,并把它稱呼為類,這不僅是為了跟的理念保持一致,也是因?yàn)榈膬?nèi)建類也是這種命名。由生成的對象,其是。這是標(biāo)準(zhǔn)的規(guī)定。本文的主題是原型系統(tǒng)的變遷,所以并沒有涉及和對原型鏈的影響。 概述 JavaScript 的原型系統(tǒng)是最初就有的語言設(shè)計。但隨著 ES 標(biāo)準(zhǔn)的進(jìn)化和新特性的添加。它也一直在不停進(jìn)化。這篇文章的目的就是梳理一下早期到 ES5 和現(xiàn)在 ES6,...
閱讀 3116·2023-04-25 16:50
閱讀 921·2021-11-25 09:43
閱讀 3533·2021-09-26 10:11
閱讀 2529·2019-08-26 13:28
閱讀 2542·2019-08-26 13:23
閱讀 2433·2019-08-26 11:53
閱讀 3577·2019-08-23 18:19
閱讀 3000·2019-08-23 16:27