JavaScript引用類型---Object

1、對象初始化

建立對象的兩種方法:

1.對象初始化器或對象字面量:{[nameValuePair1[, nameValuePair2[, ...nameValuePairN]]]}數組

參數:nameValuePair1, nameValuePair2, ... nameValuePairNdom

     成對的名稱(字符串)與值(任何值),其中名稱經過冒號與值分隔函數

es2015以後簡化了字面量寫法性能

let a = "foo", b = 42, c = {};
    let object1 = {
        a: a,
        b: b,
        c: c
    };
    //es2015寫法
    let object2 = {
        a, b, c
    };
    console.log(object1.a === object2.a); //true

2.以構造函數形式來調用:new Object([value])
參數:value  任何值測試

let object = new Object({'foo': 123});
    console.log(object.foo); //123

訪問對象屬性

對象屬性能夠用下標小圓點標記或者方括號標記訪問this

let object = new Object({"b": 42});
    console.log(object["b"]); // 42
    object.b = "baz";
    console.log(object.b); //'baz'

從ECMAScript 2015開始,對象初始化語法開始支持計算屬性名,容許在[]中放入表達式,計算結果能夠當作屬性名prototype

let i = 0;
    let object1 = {
        ["foo" + ++i]: i,
        ["foo" + ++i]: i,
        ["foo" + ++i]: i
    };
    console.log(object1.foo1); // 1
    console.log(object1.foo2); // 2
    console.log(object1.foo3); // 3

    let param = 'size';
    let object2 = {
        [param]: 12,
        ["mobile" + param.charAt(0).toUpperCase() + param.slice(1)]: 4
    };
    console.log(object2); // { size: 12, mobileSize: 4 }

2、Object靜態方法

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

語法:Object.defineProperty(obj, prop, descriptor)code

參數:對象

        obj  要在其上定義屬性的對象
        prop  要定義或修改的屬性的名稱
        descriptor  將被定義或修改的屬性描述符
            configurable  t當且僅當該屬性的 configurable 爲 true 時,該屬性描述符纔可以被改變,同時該屬性也能從對應的對象上被刪除。默認爲 false
            enumerable  當且僅當該屬性的enumerable爲true時,該屬性纔可以出如今對象的枚舉屬性中。默認爲 false
            value  與屬性關聯的值。能夠是任何有效的JavaScript值(數字,對象,函數等)。默認爲 undefined.
            writable  當且僅當該屬性的writable爲true時,value才能被賦值運算符改變。默認爲 false
            get  做爲該屬性的 getter 函數,若是沒有 getter 則爲undefined。當訪問該屬性時,該方法會被執行,方法執行時沒有參數傳入,可是會傳入this對象。默認爲 undefined繼承

            set  做爲屬性的 setter 函數,若是沒有 setter 則爲undefined。當屬性值修改時,觸發執行該方法,該方法將接受惟一參數,即該屬性新的參數值。默認爲 undefined

返回值:傳遞給函數的對象

(1)writable決定一個屬性可否被賦值

let object = {};
    Object.defineProperty(object,"a",{
        value: 30,
        writable: true
    });
    console.log(object.a); //30
    object.a = 15;
    console.log(object.a); //15
    Object.defineProperty(object,"b",{
        value: 30,
        writable: false
    });
    console.log(object.b); //30
    object.b = 15; //TypeError: Cannot assign to read only property 'b' of object '#<Object>'

(2)enumerable決定該屬性是否能被枚舉

let object = {};
    Object.defineProperty(object,"a",{
        value: 15,
        writable: true,
        enumerable: true
    });
    Object.defineProperty(object,"b",{
        value: 16,
        writable: true,
        enumerable: false
    });
    Object.defineProperty(object,"c",{
        value: 17,
        writable: true,
        enumerable: true
    });
    for (let i in object) {
        console.log(i+"=",object[i]); //a=15 c=17
    }
    console.log(Object.keys(object)); //["a", "c"]

    console.log(object.propertyIsEnumerable('a')); // true
    console.log(object.propertyIsEnumerable('b')); // false
    console.log(object.propertyIsEnumerable('c')); // true

(3)configurable

let object = {};
    Object.defineProperty(object,"a",{
        get: () => {
            return 10;
        },
        configurable: false
    });
    Object.defineProperty(object,"a",{
        value: 15
    }); //TypeError: Cannot redefine property: a
    console.log(object.a); //10

    object.b = 5;
    //等同於
    Object.defineProperty(object,'b',{
        value: 5,
        writable: true,
        configurable: true,
        enumerable: true
    });
    Object.defineProperty(object,'d',{
        value: 5
    });
    //等同於
    Object.defineProperty(object,'b',{
        value: 5,
        writable: false,
        configurable: false,
        enumerable: false
    });

(4)set/get

function Test() {
        let x = null;
        let arr = [];
        Object.defineProperty(this,'x',{
            get: () => {
                console.log('get');
                return x;
            },
            set: (value) => {
                console.log('set');
                x = value;
                arr.push(x);
            }
        });
        this.getTest = function () {
            return arr;
        }
    }
    let test = new Test();
    test.x; //get
    test.x = 25; //set
    test.x = 30; //set
    console.log(test.getTest()); //[25, 30]

2.Object.defineProperties() 方法直接在一個對象上定義新的屬性或修改現有屬性,並返回該對象

語法:Object.defineProperties(obj, props)
參數:
        obj  要在其上定義屬性的對象
        props  要定義其可枚舉屬性或修改的屬性描述符的對象
返回值:被傳遞給函數的對象

let object = {};
    Object.defineProperties(object, {
        'property1': {
            value: true,
            writable: true
        },
        'property2': {
            value: 'Hello',
            writable: false
        }
    });

3.Object.getOwnPropertyDescriptor() 方法返回指定對象上一個自有屬性對應的屬性描述符,自有屬性指的是直接賦予該對象的屬性,不須要從原型鏈上進行查找的屬性

語法:Object.getOwnPropertyDescriptor(obj, prop)

參數:
        obj  須要查找的目標對象
        prop  目標對象內屬性名稱(String類型)
返回值:若是指定的屬性存在於對象上,則返回其屬性描述符對象(property descriptor),不然返回 undefined

let object = {
        bar: 42,
        get foo() { return 17; }
    };
    let foo = Object.getOwnPropertyDescriptor(object, "foo");
    // {
    //   configurable: true,
    //   enumerable: true,
    //   get: /*the getter function*/,
    //   set: undefined
    // }
    let bar = Object.getOwnPropertyDescriptor(object, "bar");
    // {
    //   configurable: true,
    //   enumerable: true,
    //   value: 42,
    //   writable: true
    // }
    Object.defineProperty(object, "baz", {
        value: 8675309,
        writable: false,
        enumerable: false
    });
    let baz = Object.getOwnPropertyDescriptor(object, "baz");
    // {
    //   configurable: false,
    //   enumerable: false,
    //   value: 8675309,
    //   writable: false
    // }

4.Object.getOwnPropertyDescriptors() 方法用來獲取一個對象的全部自身屬性的描述符

語法:Object.getOwnPropertyDescriptors(obj)###

參數:
        obj  任意對象
返回值:所指定對象的全部自身屬性的描述符,若是沒有任何自身屬性,則返回空對象

let object = {
        bar: 42,
        get foo() { return 17; }
    };
    Object.getOwnPropertyDescriptors(object);
    //{
    //  bar: {value: 42, writable: true, enumerable: true, configurable: true},
    //  foo: {get: ƒ, set: undefined, enumerable: true, configurable: true}
    // }
    function SuperClass() {}
    SuperClass.prototype = {
        x: 15,
        y: 20
    };
    let superClass = new SuperClass();
    superClass.a = 50;
    superClass.b = 100;
    function SubClass() {}
    SubClass.prototype = Object.create(SuperClass.prototype, Object.getOwnPropertyDescriptors(superClass));
    let subClass = new SubClass();
    console.log(subClass.a); //50

5.Object.getOwnPropertyNames()方法返回一個由指定對象的全部自身屬性的屬性名(包括不可枚舉屬性但不包括Symbol值做爲名稱的屬性)組成的數組

語法:Object.getOwnPropertyNames(obj)

參數:
        obj  一個對象,其自身的可枚舉和不可枚舉屬性的名稱被返回
返回值:在給定對象上找到的屬性對應的字符串數組

let arr = ["a", "b", "c"];
    console.log(Object.getOwnPropertyNames(arr).sort()); // ["0", "1", "2", "length"]
    // 類數組對象
    let object = { 0: "a", 1: "b", 2: "c"};
    console.log(Object.getOwnPropertyNames(object).sort()); // ["0", "1", "2"]

6.Object.getOwnPropertySymbols() 方法返回一個給定對象自身的全部 Symbol 屬性的數組

語法:Object.getOwnPropertySymbols(obj)

參數:
        obj  要返回 Symbol 屬性的對象
返回值:在給定對象自身上找到的全部 Symbol 屬性的數組

let object = {};
    let a = Symbol("a");
    let b = Symbol.for("b");

    object[a] = "localSymbol";
    object[b] = "globalSymbol";
    let objectSymbols = Object.getOwnPropertySymbols(object);

    console.log(objectSymbols.length); // 2
    console.log(objectSymbols);         // [Symbol(a), Symbol(b)]
    console.log(objectSymbols[0]);      // Symbol(a)

7.Object.create()方法建立一個新對象,使用現有的對象來提供新建立的對象的__proto__

語法:Object.create(proto, [propertiesObject])

參數:
     proto  新建立對象的原型對象
     propertiesObject  可選,這些屬性對應Object.defineProperties()的第二個參數。
返回值:一個新對象,帶着指定的原型對象和屬性

function Father() {
        this.x = 0;
        this.y = 0;
    }
    Father.prototype.move = function (x,y) {
        this.x += x;
        this.y += y;
    };
    function Son() {
        Father.call(this); //調用父類構造函數
    }
    Son.prototype = Object.create(Father.prototype);
    Son.prototype.constructor = Son;
    let son = new Son();
    console.log(son instanceof Son); //true
    console.log(son instanceof Father); //true

8.Object.getPrototypeOf() 方法返回指定對象的原型

語法:Object.getPrototypeOf(object)
        obj  要返回其原型的對象
返回值:給定對象的原型,若是沒有繼承屬性,則返回 null

let proto = {};
    let object = Object.create(proto);
    Object.getPrototypeOf(object) === proto; // true

    let reg = /a/;
    Object.getPrototypeOf(reg) === RegExp.prototype; // true

9.Object.assign() 方法用於將全部可枚舉屬性的值從一個或多個源對象複製到目標對象

語法:Object.assign(target, ...sources)

參數:
     target  目標對象
     sources  源對象
返回值:目標對象

let obj = { a: 1 };
    let copy = Object.assign({}, obj);
    console.log(copy); // { a: 1 }

此方法是淺拷貝,Object.assign()拷貝的是屬性值,若是源對象的屬性值是一個指向對象的引用,它也只拷貝那個引用值

let obj1 = { a: 0 , b: { c: 0}};
    let obj2 = Object.assign({}, obj1);
    console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
    obj1.b.c = 3;
    console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}}
    console.log(JSON.stringify(obj2)); // { a: 1, b: { c: 3}}

如何實現深拷貝

let obj1 = { a: 0 , b: { c: 0}};
    let obj2 = JSON.parse(JSON.stringify(obj1));
    obj1.b.c = 4;
    console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}

合併兩個對象

let obj1 = { a: 1, b: 1, c: 1 };
    let obj2 = { b: 2, c: 2 };
    let obj3 = { c: 3 };
    let newObj = Object.assign({}, obj1, obj2, obj3);
    console.log(newObj); // { a: 1, b: 2, c: 3 }

10.Object.is()方法判斷兩個值是不是相同的值

語法:Object.is(value1, value2);

參數:
        value1  須要比較的第一個值
        value2  須要比較的第二個值
返回值:表示兩個參數是否相同的Boolean

如下狀況返回true:

  • 兩個值都是 undefined
  • 兩個值都是 null
  • 兩個值都是 true 或者都是 false
  • 兩個值是由相同個數的字符按照相同的順序組成的字符串
  • 兩個值指向同一個對象
  • 兩個值都是數字而且
  • 都是正零 +0
  • 都是負零 -0
  • 都是 NaN
  • 都是除零和 NaN 外的其它同一個數字
console.log(NaN === NaN); //false
    console.log(NaN == NaN); //false
    console.log(Object.is(NaN,NaN)); //true

    console.log(0 == false); //true
    console.log(0 === false); //false
    console.log(Object.is(0,false)); //false

    console.log(-0 == 0); //true
    console.log(-0 === 0); //true
    console.log(Object.is(-0,0)); //false

11.Object.isExtensible() 方法判斷一個對象是不是可擴展的(是否能夠在它上面添加新的屬性)

語法: Object.isExtensible(obj)

參數:
     obj  須要檢測的對象
返回值:表示給定對象是否可擴展的一個Boolean

12.Object.isSealed() 方法判斷一個對象是否被密封

語法:Object.isSealed(obj)

參數:
        obj  要被檢查的對象
返回值:表示給定對象是否被密封的一個Boolean

13.Object.isFrozen()方法判斷一個對象是否被凍結

語法:Object.isFrozen(obj)

參數:
        obj  被檢測的對象
返回值:表示給定對象是否被凍結的Boolean

14.Object.preventExtensions()方法讓一個對象變的不可擴展,也就是永遠不能再添加新的屬性

語法:Object.preventExtensions(obj)

參數:
        obj  將要變得不可擴展的對象
返回值:已經不可擴展的對象
描述:不可擴展對象不能再添加新的屬性,可是原有的屬性仍然可被編輯、刪除

非空對象(其屬性的configurable爲true,writable爲true):

let object = {
        a:1,
        b:2
    };
    console.log(Object.isExtensible(object)); // true
    Object.preventExtensions(object);
    console.log(Object.isExtensible(object)); //false
    console.log(Object.isSealed(object)); // false
    console.log(Object.isFrozen(object)); // false
    ob.b = 20; //能夠賦值
    console.log(ob.b); //20
    delete ob.b; //能夠刪除
    console.log(ob); //{a: 1}
    Object.defineProperty(ob,'c',{ // 不能夠添加屬性
        value: 3,
        writable: true
    }); //Cannot define property c, object is not extensible

非空對象(其屬性的configurable爲false,writable爲true):

let empty = {};
    Object.defineProperty(empty,'foo',{
        value: 'baz',
        writable: true
    });
    Object.preventExtensions(empty);
    console.log(Object.isExtensible(empty)); // false
    console.log(Object.isSealed(empty)); // true
    console.log(Object.isFrozen(empty)); // false

非空對象(其屬性的configurable爲true,writable爲false):

let empty = {};
    Object.defineProperty(empty,'foo',{
        value: 'baz',
        writable: false,
        configurable: true
    });
    Object.preventExtensions(empty);
    console.log(Object.isExtensible(empty)); // false
    console.log(Object.isSealed(empty)); // false
    console.log(Object.isFrozen(empty)); // false

非空對象(其屬性的configurable爲false,writable爲false):

let empty = {};
    Object.defineProperty(empty,'foo',{
        value: 'baz'
    });
    Object.preventExtensions(empty);
    console.log(Object.isExtensible(empty)); // false
    console.log(Object.isSealed(empty)); // true
    console.log(Object.isFrozen(empty)); // true

空對象:

let empty1 = {};
    console.log(Object.isExtensible(empty1)); // true
    Object.preventExtensions(empty1);
    console.log(Object.isExtensible(empty1)); //false
    console.log(Object.isSealed(empty1)); // true
    console.log(Object.isFrozen(empty1)); // true

15.Object.seal()方法封閉一個對象,阻止添加新屬性並將全部現有屬性標記爲不可配置。當前屬性的值只要可寫就能夠改變

語法:Object.seal(obj)

參數:
        obj  將要被密封的對象
返回值:被密封的對象
描述:密封一個對象會讓這個對象變的不能添加新屬性,且全部已有屬性會變的不可配置

空對象:

let empty = {};
    Object.seal(empt);
    console.log(Object.isExtensible(empty)); // false
    console.log(Object.isSealed(empty)); // true
    console.log(Object.isFrozen(empty)); // true

非空對象:

let object = {
        foo: 'bar'
    };
    Object.seal(object);
    object.foo = 'baz'; //可編輯
    console.log(object.foo); //baz
    delete object.foo; //TypeError: Cannot delete property 'foo' of #<Object>
    console.log(Object.isExtensible(object)); // false
    console.log(Object.isSealed(object)); // true
    console.log(Object.isFrozen(object)); // false

16.Object.freeze() 方法能夠凍結一個對象,凍結指的是不能向這個對象添加新的屬性,不能修改其已有屬性的值,不能刪除已有屬性,以及不能修改該對象已有屬性的可枚舉性、可配置性、可寫性。也就是說,這個對象永遠是不可變的

語法:Object.freeze(obj)

參數:
     obj  要被凍結的對象
返回值:被凍結的對象
描述:被凍結對象自身的全部屬性都不可能以任何方式被修改,若是一個屬性的值是個對象,則這個對象中的屬性是能夠修改的,除非它也是個凍結對象

let object1 = {
        property1: 42
    };
    Object.freeze(object1);
    console.log(Object.isExtensible(object1)); // false
    console.log(Object.isSealed(object1)); // true
    console.log(Object.isFrozen(object1)); // true
    object1.property1 = 33; // TypeError: Cannot assign to read only property 'property1' of object '#<Object>'
    console.log(object1.property1); //42

    let object2 = {
        internal: {}
    };
    Object.freeze(object2);
    object2.internal.a = 'aValue';
    console.log(object2.internal.a); //aValue

17.Object.entries()方法返回一個給定對象自身可枚舉屬性的鍵值對數組,其排列與使用 for...in 循環遍歷該對象時返回的順序一致

語法:Object.entries(obj)

參數:
     obj  能夠返回其可枚舉屬性的鍵值對的對象
返回值:給定對象自身可枚舉屬性的鍵值對數組

const object1 = { foo: 'bar', baz: 42 };
    console.log(Object.entries(object1)); // [ ['foo', 'bar'], ['baz', 42] ]
    // array like object
    const object2 = { 0: 'a', 1: 'b', 2: 'c' };
    console.log(Object.entries(object2)); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]
    // array like object with random key ordering
    const object3 = { 100: 'a', 2: 'b', 7: 'c' };
    console.log(Object.entries(object3)); // [ ['2', 'b'], ['7', 'c'], ['100', 'a'] ]

18.Object.keys() 方法會返回一個由一個給定對象的自身可枚舉屬性組成的數組,數組中屬性名的排列順序和使用 for...in 循環遍歷該對象時返回的順序一致

語法:Object.keys(obj)

參數:
        obj  要返回其枚舉自身屬性的對象
返回值:一個表示給定對象的全部可枚舉屬性的字符串數組

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

    // array like object
    let object = { 0: 'a', 1: 'b', 2: 'c' };
    console.log(Object.keys(object)); // ['0', '1', '2']

19.Object.values()方法返回一個給定對象本身的全部可枚舉屬性值的數組,值的順序與使用for...in循環的順序相同

語法:Object.values(obj)

參數:
        obj  被返回可枚舉屬性值的對象
返回值:一個包含對象自身的全部可枚舉屬性值的數組

let arr = ['a', 'b', 'c'];
    console.log(Object.values(arr)); // ['a', 'b', 'c']

    // array like object
    let object = { 0: 'a', 1: 'b', 2: 'c' };
    console.log(Object.values(object)); // ['a', 'b', 'c']

3、Object實例方法

1.hasOwnProperty() 方法會返回一個布爾值,指示對象自身屬性中是否具備指定的屬性

語法:obj.hasOwnProperty(prop)

參數:

        prop  要檢測的屬性  字符串 名稱或者 Symbol
返回值:用來判斷某個對象是否含有指定的屬性的 Boolean

描述:這個方法能夠用來檢測一個對象是否含有特定的自身屬性;和 in 運算符不一樣,該方法會忽略掉那些從原型鏈上繼承到的屬性

let object = new Object();
    object.prop = 'exists';
    console.log(object.hasOwnProperty('prop'));             // true
    console.log(object.hasOwnProperty('toString'));         // false
    console.log(object.hasOwnProperty('hasOwnProperty'));   // false
    console.log('toString' in object); // true
    console.log('prop' in object); // true
    console.log('hasOwnProperty' in object); // true

2.isPrototypeOf() 方法用於測試一個對象是否存在於另外一個對象的原型鏈上

語法:prototypeObj.isPrototypeOf(object)

參數:

        object  在該對象的原型鏈上搜尋

返回值:Boolean,表示調用對象是否在另外一個對象的原型鏈上

function Foo() {}
function Bar() {}
function Baz() {}

Bar.prototype = Object.create(Foo.prototype);
Baz.prototype = Object.create(Bar.prototype);

let baz = new Baz();

console.log(Baz.prototype.isPrototypeOf(baz)); // true
console.log(Bar.prototype.isPrototypeOf(baz)); // true
console.log(Foo.prototype.isPrototypeOf(baz)); // true
console.log(Object.prototype.isPrototypeOf(baz)); // true

3.propertyIsEnumerable() 方法返回一個布爾值,表示指定的屬性是否可枚舉

語法:obj.propertyIsEnumerable(prop)

參數:

        prop  須要測試的屬性名

返回值:用來表示指定的屬性名是否可枚舉的Boolean

let o = {};
let a = [];
o.prop = 'is enumerable';
a[0] = 'is enumerable';

o.propertyIsEnumerable('prop');   //  返回 true
a.propertyIsEnumerable(0);        // 返回 true

4.toString() 方法返回一個表示該對象的字符串

語法:object.toString()

返回值:表示該對象的字符串

let object = new Object();
    console.log(object.toString()); //[object Object]
    function Animal(name,age,color,sex) {
        this.name = name;
        this.age = age;
        this.color = color;
        this.sex = sex;
    }
    Animal.prototype.toString = function () {
        let string = this.name + "是一個" + this.age + "歲的" + this.color + "的" + this.sex + "動物";
        return string;
    };
    let animal = new Animal("小可愛",1,"灰色","雌性");
    console.log(animal.toString()); //小可愛是一個1歲的灰色的雌性動物

5.valueOf() 方法返回指定對象的原始值

語法:object.valueOf()
返回值:返回值爲該對象的原始值

function Animal(name,age,color,sex) {
        this.name = name;
        this.age = age;
        this.color = color;
        this.sex = sex;
    }
    let animal = new Animal("小可愛",1,"灰色","雌性");
    console.log(animal.valueOf()); //{name: "小可愛", age: 1, color: "灰色", sex: "雌性"}
相關文章
相關標籤/搜索