成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

《JavaScript程序設(shè)計》—— 標(biāo)準(zhǔn)對象 Object

Meils / 1072人閱讀

摘要:需要鏈接標(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);            // true
Object本身作為工具方法
    // 返回一個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本身當(dāng)作工具方法使用時,可以將任意值轉(zhuǎn)為對象。這個方法常用于保證某個值一定是對象。如果參數(shù)是原始類型的值,Object方法返回對應(yīng)的包裝對象的實(shí)例

Object()傳入?yún)?shù)為基本類型值,則返回值為其類型的構(gòu)造函數(shù)的實(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)

Object.keys() 方法會返回一個由一個給定對象的自身可枚舉屬性組成的數(shù)組,數(shù)組中屬性名的排列順序和使用 for...in 循環(huán)遍歷該對象時返回的順序一致 (兩者的主要區(qū)別是 一個 for-in 循環(huán)還會枚舉其原型鏈上的屬性)。

Enumerable條件限制,且不可枚舉原型鏈中的屬性
    // 無法枚舉到原型鏈中的屬性
    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)

Object.getOwnPropertyNames 返回一個數(shù)組,該數(shù)組對元素是 obj 自身擁有的枚舉或不可枚舉屬性名稱字符串。 數(shù)組中枚舉屬性的順序與通過 for...in 循環(huán)(或 Object.keys)迭代該對象屬性時一致。 數(shù)組中不可枚舉屬性的順序未定義。

不受Enumerable條件限制,但不可枚舉原型鏈中屬性

如果你只要獲取到可枚舉屬性,查看 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.keysObject.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()

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

5. Object.getOwnPropertyDescriptor()

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
6. Object.defineProperties()

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ù),就能夠定義一個只能夠通過訪問器gettersetter來訪問值的屬性。訪問器與value屬性是互相排斥的,也就是說,如果指定了value屬性的值,訪問器(包括getset)就會失效;反之,如果指定了訪問器(getset中的某一個亦或是都存在),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: # is not extensible" 

詳細(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; // undefined
Object.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"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.prototype.hasOwnProperty()

所有繼承了 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"); // true
    
Object.prototype.isPrototypeOf()

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"
Object.prototype.propertyIsEnumerable()

每個對象都有 propertyIsEnumerable 方法。該方法可以判斷出指定對象里的屬性是否可枚舉,也就是說該屬性是否可以通過 for...in 循環(huán)等遍歷到,不過有些屬性雖然可以通過 for...in 循環(huán)遍歷到,但因?yàn)樗鼈儾皇亲陨韺傩?,而是從原型鏈上繼承的屬性,所以該方法也會返回false。如果對象沒有指定的屬性,該方法返回 false。

MDN:Object.prototype.propertyIsEnumerable()

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/83512.html

相關(guān)文章

  • JavaScript標(biāo)準(zhǔn)庫系列——Object對象和Array對象(一)

    摘要:目錄導(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)庫,只要...

    Scholer 評論0 收藏0
  • 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)生的,對于基本類型...

    sean 評論0 收藏0
  • 什么是 JAVASCRIPT?

    摘要:,微軟發(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...

    ephererid 評論0 收藏0
  • 001-讀書筆記-JavaScript高級程序設(shè)計 JavaScript簡介

    摘要:由于計算機(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...

    masturbator 評論0 收藏0
  • JavaScript 原型系統(tǒng)的變遷,以及 ES6 class

    摘要:一般我們對這種構(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,...

    chuyao 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<