js知識梳理1:理解對象的屬性特性

来源:https://www.cnblogs.com/qcjay/archive/2018/08/19/9499821.html
-Advertisement-
Play Games

寫在前面 註:這個系列是本人對js知識的一些梳理,其中不少內容來自書籍:Javascript高級程式設計第三版和JavaScript權威指南第六版,感謝它們的作者和譯者。有發現什麼問題的,歡迎留言指出。 1.數據屬性 數據屬性的4個特性: Configurable:①表示能否通過delete刪除屬性 ...


寫在前面

註:這個系列是本人對js知識的一些梳理,其中不少內容來自書籍:Javascript高級程式設計第三版和JavaScript權威指南第六版,感謝它們的作者和譯者。有發現什麼問題的,歡迎留言指出。

1.數據屬性

數據屬性的4個特性:

  • Configurable:①表示能否通過delete刪除屬性從而重新定義,②能否修改屬性的特性,③能否把屬性修改為訪問器屬性。對象直接量里預設值true。
  • Enumerable:表示能否通過for-in迴圈返回屬性。對象直接量里預設值true。
  • Writable:表示能否修改屬性的值。對象直接量里預設值true。
  • Value:包含這個屬性的數據值。對象直接量里預設值undefined。
//查看對象直接量的屬性的屬性特性預設值
var people = {
    name:'jaychou',
    sayName:function () {
        console.log(this.name);
    }
};
/**{value: "jaychou", writable: true, enumerable: true, configurable: true}*/
console.log(Object.getOwnPropertyDescriptor(people,'name'));
/**{value: ƒ, writable: true, enumerable: true, configurable: true}*/
console.log(Object.getOwnPropertyDescriptor(people,'sayName'));
//getOwnPropertyDescriptor對於繼承屬性和不存在的屬性,返回undefined

要修改屬性預設的特性,使用Object.defineProperty()方法,接收3個參數:對象,屬性名字和描述符對象。

//修改屬性預設特性:
Object.defineProperty(person,'job',{
    emumerable:false,//不可枚舉
    value:'singer',
    writable:false,//不可寫
    configurable:true
});
/**{name: "jaychou", sayName: ƒ, job: "singer"}*/
console.log(person);
for(var prop in person){
    //列印name,sayName
    console.log(prop);
}
//會報錯
try{
    person.job = 'director';
}catch (e) {
    //Cannot assign to read only property 'job' of object
    console.log(e);
}

可以多次調用Object.defineProperty()方法修改同一個屬性,但在把configurable特性設置為false之後就會有限制了:

Object.defineProperty(person,'height',{
    configurable:false,//不可配置
    writable:true,
    value:172
});
try{
    Object.defineProperty(person,'height',{
        configurable:true,//出錯
        enumerable:true,//出錯
        value:175,//正常
        writable:false,//writable從true變false可以,false變true也會出錯
    });
}catch (e) {
    //Cannot redefine property: height at Function.defineProperty
    console.log(e);
}
try{
    delete person.height;
}catch (e) {
    //設置成不可配置後也不可刪除:Cannot delete property 'height' of #<Object>
    console.log(e);
}

另外,調用 Object.defineProperty()方法時,如果不指定,configurable、enumerable 和 writable 特性的預設值都是 false。如果是修改已有屬性,則無此限制。

2.存儲器屬性

存儲器屬性不包含數據值,只包含包含 getter 和 setter 函數(非必需)。 在讀取存儲器屬性時,會調用 getter 函數,這個函數負責返回有效的值;在寫入存儲器屬性時,會調用 setter 函數並傳入新值,這個函數負責決定如何處理數據。4個屬性特性如下:

  • Configurable:①表示能否通過delete刪除屬性從而重新定義,②能否修改屬性的特性,③能否把屬性修改為數據屬性。對象直接量的預設值true
  • Enumerable:表示能否通過for-in迴圈返回屬性。對象直接量的預設值true
  • Get:在讀取屬性時調用的函數。對象直接量預設值undefined
  • Set:在寫入屬性時調用的函數。對象直接量的預設值undefined

定義存儲器屬性最簡單的方法是使用對象直接量語法的拓展寫法:

var p = {
    x:3.0,
    y:4.0,
    //r是可讀寫的存取器屬性
    get r(){return Math.sqrt(this.x*this.x+this.y*this.y);},
    set r(newValue){
        var oldvalue = Math.sqrt(this.x*this.x+this.y*this.y);
        var ratio = newValue/oldvalue;
        this.x *= ratio;
        this.y *= ratio;
    },
    //theta是只讀存取器屬性
    get theta(){return Math.atan2(this.y,this.x);}
}
console.log(p.r);
p.r = 25;

使用Object.defineProperty()方法定義存儲器屬性:

var book = {
    _year:2004,
    edition:1
};
Object.defineProperty(book,"year",{
    get:function () { return this._year; },
    set:function (newValue) {
        if(newValue>2004){
            this._year = newValue;
            this.edition += newValue - 2004;
        }
    }
})
/**{get: ƒ, set: ƒ, enumerable: false, configurable: false}*/
console.log(Object.getOwnPropertyDescriptor(book,'year'));

如例子所示,使用存儲器屬性的常見方式,即設置一個屬性的值會導致其他屬性發生變化。還有一種常見就是現在流行的類似於Vue的響應式原理,就是把data中的屬性都使用defineProperty修改為存儲器屬性,可以監聽到數據的變化。

3.定義多個屬性

經常要創建或修改多個屬性,這時候可以使用Object.defineProperties()方法,它接收2個參數,要添加或修改屬性的對象和一個映射表,包含名稱和屬性描述符。

var book1 = {};
Object.defineProperties(book1,{
   _year:{
       value:'2008'
   },
   editor:{
       enumerable:true,
       value:'2'
   },
   year:{
       get:function () {
           return this._year;
       },
       set:function (newValue) {
           this._year = newValue;
           this.edition += newValue - 2004;
       }
   }
});

4.對象的可擴展性

對象的可拓展性表示是否可以給對象添加新屬性。所有內置對象和自定義對象都是顯式可擴展的,宿主對象的可擴展性是由Javascript引擎定義的。

1.查詢對象可拓展性
var teacher = {age:25};
//true:代表可拓展
console.log(Object.isExtensible(teacher));
2.轉換為不可拓展(“鎖定對象”)
Object.preventExtensions(teacher);
//false
console.log(Object.isExtensible(teacher));
try{
    teacher.subject = 'math';
}catch (e) {
    //TypeError: Cannot add property subject, object is not extensible
    console.log(e);
}

轉換成不可拓展的操作是不可逆的,而且只能影響到對象本身的可拓展性,如果給一個不可拓展對象的原型添加屬性,這個不可拓展對象同樣會繼承這些新屬性。

5.密封對象

密封對象比鎖定對象更高一層,除了不可拓展以外,對象的所有自身屬性都設置成了不可配置的。同樣密封對象操作是不可逆的。

var tea1 = {subject:'math'};
//false:代表未密封
console.log(Object.isSealed(tea1));
Object.seal(tea1);
try{
    Object.defineProperty(tea1,'subject',{
        //enumerable:false,//出錯
        //configurable:true,//出錯
        writable:false//和上面說的一樣,writable從true變成false可以,false變成true則出錯
    });
}catch (e) {
    console.log('出錯..');
    console.log(e);
}
//true:已密封
console.log(Object.isSealed(tea1));

6.凍結對象

凍結比密封對象多的效果是:可以將它自有的所有數據屬性設置為只讀(如果對象的存取器屬性具有setter方法,存取器屬性將不受影響,仍可以通過給屬性賦值調用它們)。

var tea2 = {subject:'Chinese'};
//false:代表未凍結
console.log(Object.isFrozen(tea2));
Object.freeze(tea2);
try{
    tea2.subject = 'math';
}catch (e) {
    //TypeError: Cannot assign to read only property 'subject' of object
    console.log(e);
}
//true:已凍結
console.log(Object.isFrozen(tea2));

7.屬性特性規則總結

  • 如果對象是不可拓展的,則可以編輯已有的自有屬性,但不能給它添加新屬性。
  • 如果屬性是不可配置的,則不能修改它的可配置性和可枚舉性。
  • 如果存取器屬性是不可配置的,則不能修改其getter和setter方法,也不能將它轉換為數據屬性。
  • 如果數據屬性是不可配置的,則不能將它轉換為存取器屬性。
  • 如果數據屬性是不可配置的,則不能將它的可寫性從false修改為true,但可以從true修改為false。
  • 如果數據屬性是不可配置且不可寫的,則不能修改它的值。然而可配置但不可寫屬性的值是可以修改的(做法:先將它標記為可寫的,然後修改它的值,最後轉換為不可寫的)。

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 方法一: 容器確定寬高:知識點:transform只能設置在display為block的元素上。 方法一效果圖: 方法二: ...
  • Day3 Form表單 一.form表單 :提交數據 表單在網頁中主要負責數據採集功能,它用<form>標簽定義。 用戶輸入的信息都要包含在form標簽中,點擊提交後,<form>和</form>裡面包含的數據將被提交到伺服器或者電子郵件里。 所有的用戶輸入內容的地方都用表單來寫,如登錄註冊、搜索框 ...
  • 協議可以實現前後端全雙工通信,從而取代浪費資源的長輪詢。在此協議的基礎上,可以實現前後端數據、多端數據,真正的 實時響應 。在學習 的過程中,實現了一個簡化版群聊,過程和代碼詳細記錄在這篇文章中。 本篇文章來自 "董沅鑫的個人網站" ,引用、轉載請指明出處 。 查看更多知識,或者技術交流:請訪問 " ...
  • react教程(零)—— 安裝 react項目的基本配置,使用create-react-app和webpack構建react-app。主要介紹如何新建一個react-app,並對webpack如何創建react-app做了詳細介紹。 ...
  • Vue.js 組件 模塊化:是從代碼邏輯的角度進行劃分的; 組件化:是從UI界面的角度進行劃分的。 組件(Component)是 Vue.js 最強大的功能之一,組件可以擴展 HTML 元素,封裝可重用的代碼。 組件系統讓我們可以用獨立可復用的小組件來構建大型應用,幾乎任意類型的應用的界面都可以抽象 ...
  • Modal組件 長話不多說,接下來讓我們來動手實現一個react Modal組件。 我們先來看一下 "實際效果" Modal的佈局 首先,讓我們先思考下一個Modal組件的佈局是怎麼樣的。 我們先拿一個基本的Modal樣例來分析下。 如上圖所示,一個Modal組件可以分為mask、header、bo ...
  • Day1 瞭解web前端 一.職業發展路線: 前端頁面製作、前端開發、前端架構師 二.1)前端工程師主要職責: 利用HTML/CSS/JavaScript等各種Web技術進行客戶端產品的開發。完成客戶端程式(也就是瀏覽器端)的開發,同時結合後臺技術模擬整體效果,致力於通過技術改善用戶體驗。 2)和前 ...
  • puppeteer puppeteer 是一個通過DevTools 協議提供高級API 來控制 chrome,chromium 的 NODE庫; puppeteer預設運行在 headless 模式, 也可配置後運行在全模式(non headless). puppeteer可以做什麼 大部分在瀏覽器 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...