JS物件導向Object型別

小肖愛睡覺發表於2020-10-26

Object建立物件

//表示建立一個空物件
var obj1 = new Object(null);
var obj2 = new Object(undefined);

//表示建立一個與給定值對應型別的物件
var obj3 = new Object(100);
console.log(obj3);//[Number: 100]
var num = new Number(100);
console.log(num);//[Number: 100]


//當以非建構函式形式被呼叫時,Object等同於new Object()
var obj4 = Object();//函式呼叫
var obj5 = new Object();//建構函式呼叫

屬性描述符

JavaScript提供了一個內部資料結構,用於描述物件的值,控制其行為,例如該屬性是否可寫、是否可配置、是否可修改以及是否可列舉等。這個內部資料結構被稱為“屬性描述符”。

每個屬性都有自己對應的屬性描述符,儲存該屬性的元資訊。

{
	value: '臥龍學苑',
	writable: false,
	enumerable: true,
	configurable: false,
	get: undefined,
	set: undefined
}

物件裡目前存在的屬性描述符有兩種主要形式:資料描述符和存取描述符

資料描述符是一個具有值的屬性,該值可能是可寫的,也可能不是可寫的。

存取描述符是由getter-setter函式對描述的屬性。
在這裡插入圖片描述

獲取屬性描述符

Object.getOwnPropertyDescriptor()方法返回指定物件上一個自有屬性對應的屬性描述符。

Object.getOwnPropertyDescriptor(obj,prop)
  • obj:需要查詢的物件
  • prop:目標物件內屬性名稱(String型別)
  • 返回值:如果指定的屬性存在於物件上,則返回其屬性描述物件,否則返回undefined

**注意:**如果該方法的第一個引數不是物件,會報錯(TypeError)

程式碼:

/*
    通過定義物件(屬性或方法)這種方式
      屬性預設都是資料描述符
*/

var obj = {
    name : '肖德碩'
}
/*
    使用Object.getOwnPropertyDescriptor()方法獲取指定屬性的描述符
    Object.getOwnPropertyDescriptor(obj,prop)
      obj - 表示指定屬性對應的目標物件
      prop - 表示獲取描述符的目標屬性名稱
     返回值 - 其屬性描述符物件
*/

var result = Object.getOwnPropertyDescriptor(obj,'name');
console.log(result);

效果:
在這裡插入圖片描述

設定屬性描述符

1.Object.defineProperty()方法為物件定義新屬性或修改現有屬性,並返回該物件。

Object.defineProperty(obj,prop,desciptor)
  • obj:要在其上定義屬性的物件
  • prop:要定義或修改的屬性的名稱
  • descriptor:將別定義或修改的屬性描述符。
  • 返回值:被傳遞給函式的物件

2.Object.defineProperties()方法為物件定義一個或多個新屬性或修改現有屬性,並返回該物件。

Object.defineProperties(obj,props)
  • obj:要在其上定義屬性的物件
  • props:要定義其可列舉屬性或修改的屬性描述符的物件
  • 返回值:被傳遞給函式的物件

設定屬性運算子value

value:表示目標屬性對應的值。

可以是任何有效的JavaScript值(數值,物件,函式等)。

預設為undefined

var obj = {
    //定義物件的同時定義了該屬性以及值(可修改、可刪除以及可列舉的)
    name : '肖德碩'
}

/*
    Object.defineProperty(obj,prop,desc)方法
      作用
        用於定義目標物件的新屬性
        用於修改目標物件的已存在屬性
      引數
        obj - 表示目標物件
        prop - 表示目標物件的目標屬性名稱
        desc -  表示屬性描述符,必須是物件格式
            {
                value : 值
            }
       返回值 - 返回傳遞的物件
* */

Object.defineProperty(obj,'name',{
   value : '小肖'
});
console.log(obj.name);//小肖
/*
    同樣都是為物件新增屬性
    1.如果使用“物件名.屬性名 = 值” -> 可修改 可刪除以及可列舉的
    2.如果使用Object.defineProperty()方法新增屬性
        該新屬性是不可修改、不可刪除以及不可列舉的
 */
Object.defineProperty(obj,'age',{
    value : 18
});
console.log(obj.age);//18

var result1 = Object.getOwnPropertyDescriptor(obj,'age');
console.log(result1);

//一旦屬性的值是不可修改的 - 如果執行修改操作時 -> 沒有語法報錯,但是無效
obj.age = 80;
console.log(obj.age);//18

obj.job = '帥哥';
var result2 = Object.getOwnPropertyDescriptor(obj,'job');
console.log(result2);

結果:
在這裡插入圖片描述

設定屬性運算子writable

writable:Boolean值,表示目標屬性的值是否可以被修改。

當且僅當該屬性的writable為true時,value才能被賦值運算子改變

預設為false

程式碼:

var obj = {
    //定義物件的同時定義了該屬性以及值(可修改、可刪除以及可列舉的)
    name : '肖德碩'
}
Object.defineProperty(obj,'name',{
    value : '小肖',
    writable : false//不可修改
});
console.log(obj.name); //小肖
//修改name屬性值
obj.name = '蕭蕭';
console.log(obj.name); //小肖

Object.defineProperty(obj,'age',{
    value : 18,
    weitable : false
});
console.log(obj.age);//18
//修改age屬性值
obj.age = 80;
console.log(obj.age);//80
//刪除age屬性值
delete obj.age;
console.log(obj.age);//18

效果:
在這裡插入圖片描述

設定屬性運算子configurable

configurable:Boolean值,表示目標屬性的描述符是否可以被修改。

當且僅當該屬性的configurable為true時,該熟悉描述符才能夠被改變,同時該屬性也能從對應的物件上被刪除。

var obj = {
    //定義物件的同時定義了該屬性以及值(可修改、可刪除以及可列舉的)
    name : '肖德碩'
}

//修改現有屬性
Object.defineProperty(obj,'name',{
    value : '小肖',
    writable : false,   //控制當前屬性是否可被修改
    configurable : false    //控制當前屬性是否可被刪除
});
console.log(obj.name);//小肖
//修改name屬性值
obj.name = '蕭蕭';
console.log(obj.name);//小肖

//刪除name屬性值
delete obj.name;
console.log(obj.name);//小肖

效果:
在這裡插入圖片描述

設定屬性運算子enumerable

enumerable:Boolean值,表示目標屬性是否可遍歷

當且僅當該屬性的enumerable為true時,該屬性才能夠出現在物件的列舉屬性中。

預設為false

如果物件的屬性的enumberable的值為false,以下三種操作取不到該屬性:

  • for……in語句
  • Object.keys()方法
  • JSON.dtringify()方法

程式碼:

var obj = {
    //定義物件的同時定義了該屬性以及值(可修改、可刪除以及可列舉的)
    name : '肖德碩'
}
Object.defineProperty(obj,'name',{
    value : '小肖',
    enumerable : false
});
console.log(obj.name);//小肖
/*
    屬性描述符enumerable - 控制當前屬性是否可被列舉(遍歷)
      僅能迴圈遍歷物件中可被列舉的屬性
        for……in語句
        keys()方法
      可以迴圈遍歷物件中可被列舉和不可被列舉的屬性
        getOwnPropertyNames()方法
* */
for(var i in obj) {
    console.log(i);
}
var result1 = Object.keys(obj);
console.log(result1);
var result2 = Object.getOwnPropertyNames(obj);
console.log(result2);

效果:
在這裡插入圖片描述

屬性描述符的設定方式

物件的屬性除了可以直接定義以外,還可以使用存取器進行定義。

其中setter為存值函式,使用屬性描述符中的set;

getter為取值函式,使用屬性描述符中的get

程式碼:

var obj = {
    sayMe : function(){
        console.log('this is function');
    }
}
var result = Object.getOwnPropertyDescriptor(obj,'sayMe');
console.log(result);

Object.defineProperty(obj,'sayMe',{
    value : function(){
        console.log('this is new function');
    },
    writable : false
});
obj.sayMe();

obj.sayMe = function () {
    console.log('這是張無忌');
}
obj.sayMe();

效果:
在這裡插入圖片描述

屬性描述符存取器(一)

程式碼:

var obj =  {
    name : '肖德碩'
}

var value;//全域性變數

Object.defineProperty(obj,'name',{
    //獲取指定的屬性值
    get : function () { //當獲取或訪問當前屬性時,會呼叫get方法
        console.log('this is get function');
        /*
            類似於資料描述符中的value
                get方法在被呼叫時,不能傳遞任何引數
                get方法在被呼叫時,允許傳遞this關鍵字
                  this - 表示當前的目標物件
         */
        return value;
    },

    /*
        set方法用於定義當前目標屬性的修改作用
          該方法接受唯一的一個引數 -> 作為當前目標的新的值
          通過屬性修改操作指定的新的值 -> 作為形參對應的實參
    */
    set : function (newValue) {
        console.log('this is set function:' + value);
        /*
            set方法在被呼叫時,允許傳遞this關鍵字
                  this - 表示當前的目標物件(不能呼叫物件的當前目標屬性)
        * */
        value = newValue;
    }
});
console.log(obj.name);//undefind

obj.name = '小肖';
console.log(obj.name);//小肖

效果:
在這裡插入圖片描述

屬性描述符存取器(二)

程式碼:

var value='啟嘉班';
var obj = {
    //存取描述符中的get
    get attr() {    //表示當前目標屬性名稱
        return value;
    },
    //獲取描述符中的set
    set attr(newValue) {    //表示當前目標屬性名稱
        console.log('setter:' + newValue);
        value = newValue;
    }
}

console.log(obj.attr);//啟嘉班
obj.attr = 100;

效果:
在這裡插入圖片描述

防篡改物件

防篡改是什麼

定義的物件預設在任何時候、任何位置,無論有意義的還是無意義的都可以修改物件的屬性或方法。而這些篡改可能會影響物件的內建屬性或方法,從而導致物件的正常功能可能無法使用。

JavaScript在ECMAScript5版本中新增了放置篡改物件的屬性或方法的機制,工提供了以下三級保護方式:

  1. 禁止擴充套件:禁止為物件擴充套件新的屬性或方法
  2. 密封物件:禁止擴充套件新的屬性或方法,禁止配置現有的屬性或方法的描述符,僅允許讀寫屬性的值。
  3. 凍結物件:禁止對物件執行任何修改操作。

禁止擴充套件

如果禁止為物件擴充套件新的屬性或方法,需要修改物件屬性的extensible為false。

  • Object.preventExtensions()方法用於設定指定物件不可擴充套件,即不能新增屬性或方法。
  • Object.isExtensible()方法判斷一個物件是否是可擴充套件的(是否可以在它上面新增新的屬性)。

程式碼:

var obj = {};
//將物件設定禁止擴充套件
Object.preventExtensions(obj);
//新增屬性或方法無效 -> 語法沒有報錯
obj.name = '肖德碩';
console.log(obj);
/*
    Object.defineProperty()方法新增屬性
      結果 - 報錯
      資訊 - TypeError: Cannot define property name, object is not extensible
* */
Object.defineProperty(obj,'name',{
    value : '小肖'
});
console.log(obj);

/*
    Object.isExtensible(obj)方法
        作用 - 用於判斷指定目標物件是否可擴充套件
        返回值
          true - 表示指定目標物件是擴充套件的
          false - 表示指定目標的物件是不可擴充套件的
* */
var result = Object.isExtensible(obj);
console.log(result);

效果:
在這裡插入圖片描述

密封物件

密封物件,就是指禁止為物件擴充套件新的屬性或方法,並且禁止修改現有屬性的描述符。

  • Object.seal()方法用於封閉一個物件,阻止新增新屬性並將所有現有屬性標記為不可配置。當前屬性的值只要可寫就可以改變
  • Object.isSealed()方法判斷一個物件是否被密封

程式碼:

var obj = {
    name : '肖德碩'
};

console.log(Object.getOwnPropertyDescriptor(obj,'name'));

/*
    將物件進行密封
    1.不能為該物件新增屬性或方法
    2.不能修改該物件的屬性或方法符描述符
        configurable
        enumerable
* */
object.seal(obj);

console.log(Object.getOwnPropertyDescriptor(obj,'name'));

//將該物件進行密封
Object.seal(obj);
/*
//新增屬性
obj.age = 18;
console.log(obj);//{ name: '肖德碩' }

//修改屬性
obj.name = '小肖';
console.log(obj);//{ name: '小肖' }
 */

// Object.defineProperty(obj,'age',{
//     value : 18
// });

Object.defineProperty(obj,'name',{
    value : '小肖',
    writable : false,   //表示不可修改
    configurable : true,
    enumerable : false
});

console.log(Object.getOwnPropertyDescriptor(obj,'name'));

console.log(obj);

效果:
在這裡插入圖片描述

凍結物件

凍結物件,就是指禁止對物件執行任何修改操作。

  • Object.freeze()方法用於凍結一個物件,凍結指的是不能向這個物件新增新的屬性,不能修改其已有屬性的值,不刪除已有屬性,以及不能修改該物件已有屬性的可列舉性、可配置性、可寫性。該方法返回被凍結的物件
  • Object.isFrozen()方法判斷一個物件是否被凍結

程式碼:

var obj = {
    name : '肖德碩'
}
//凍結物件
Object.freeze(obj);

// obj.age = 18;
// console.log(obj);//{ name: '肖德碩' }
// obj.name = '小肖';
// console.log(obj);//{ name: '肖德碩' }
// delete obj.name;
// console.log(obj);//{ name: '肖德碩' }

Object.defineProperty(obj,'age',{
    value : 18
});
console.log(obj);

效果:
在這裡插入圖片描述

相關文章