<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          深入了解對象屬性標(biāo)志以及描述符

          共 6372字,需瀏覽 13分鐘

           ·

          2021-03-10 10:19

          屬性標(biāo)志以及描述符

          正如我們所知,對象可以存儲(chǔ)屬性。

          到目前為止,屬性對我們來說只是一個(gè)簡單的“鍵-值”對。但對象屬性實(shí)際上是一個(gè)更靈活和強(qiáng)大的東西。

          本章我們將學(xué)習(xí)額外的配置選項(xiàng),下一章我們將看到如何無形地將它們轉(zhuǎn)換為getter/setter函數(shù)。

          屬性標(biāo)志

          652/5000 對象屬性除了值之外,還有三個(gè)特殊的屬性(所謂的“標(biāo)志”):

          • writable—如果為true,該值可以修改,否則為只讀。

          • enumerable——如果為true,則在循環(huán)中列出,否則不列出。

          • configurable-如果為true,屬性可以被刪除,這些屬性可以被修改,否則不。

          我們還沒看到他們,因?yàn)樗麄兺ǔ2粫?huì)出現(xiàn)。當(dāng)我們以“通常的方式”創(chuàng)建一個(gè)屬性時(shí),它們都是正確的。但我們也可以隨時(shí)改變它們。

          首先,讓我們看看如何獲得這些標(biāo)志。

          Object.getOwnPropertyDescriptor允許查詢關(guān)于屬性的完整信息。

          語法是:

          let descriptor = Object.getOwnPropertyDescriptor(obj, propertyName);

          obj:

          要從中獲取信息的對象。

          propertyName:

          屬性的名稱。

          返回值是一個(gè)所謂的“屬性描述符”對象:它包含值和所有標(biāo)記。

          例如:

          let user = {
            name"John"
          };

          let descriptor = Object.getOwnPropertyDescriptor(user, 'name');

          alert( JSON.stringify(descriptor, null2 ) );
          /* property descriptor:
          {
            "value": "John",
            "writable": true,
            "enumerable": true,
            "configurable": true
          }
          */

          要更改標(biāo)記,我們可以使用Object.defineProperty。

          語法是:

          Object.defineProperty(obj, propertyName, descriptor)

          obj, propertyName

          用于應(yīng)用描述符的對象及其屬性。

          descriptor

          要應(yīng)用的屬性描述符對象。

          如果該屬性存在,defineProperty將更新其標(biāo)記。否則,它將創(chuàng)建具有給定值和標(biāo)志的屬性;在這種情況下,如果沒有提供標(biāo)志,則假定它為假。

          例如,這里創(chuàng)建了一個(gè)帶有所有假標(biāo)志的屬性名:

          let user = {};

          Object.defineProperty(user, "name", {
            value"John"
          });

          let descriptor = Object.getOwnPropertyDescriptor(user, 'name');

          alert( JSON.stringify(descriptor, null2 ) );
          /*
          {
            "value": "John",
            "writable": false,
            "enumerable": false,
            "configurable": false
          }
           */

          與上面的“正常創(chuàng)建的”user.name比較一下:現(xiàn)在所有的標(biāo)志都是假的。如果這不是我們想要的那么我們最好在descriptor中將它們設(shè)為真。

          現(xiàn)在讓我們通過例子來看看標(biāo)記的效果。

          不可寫

          讓我們通過改變writable標(biāo)志使user.name不可寫(不能被重新分配):

          let user = {
            name"John"
          };

          Object.defineProperty(user, "name", {
            writablefalse
          });

          user.name = "Pete"// Error: Cannot assign to read only property 'name'

          現(xiàn)在沒有人可以更改我們的用戶名,除非他們應(yīng)用自己的defineProperty來覆蓋我們的用戶名。

          下面是相同的例子,但屬性是從頭創(chuàng)建的:

          let user = { };

          Object.defineProperty(user, "name", {
            value"John",
            // for new properties we need to explicitly list what's true
            enumerabletrue,
            configurabletrue
          });

          alert(user.name); // John
          user.name = "Pete"// Error

          不可枚舉

          現(xiàn)在讓我們?yōu)?code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">user添加一個(gè)自定義toString。

          通常,對象的內(nèi)置toString是不可枚舉的,它不會(huì)出現(xiàn)在for..in。但如果我們添加自己的toString,那么默認(rèn)情況下它會(huì)出現(xiàn)在for..in,是這樣的:

          let user = {
            name"John",
            toString() {
              return this.name;
            }
          };

          // By default, both our properties are listed:
          for (let key in user) alert(key); // name, toString

          如果我們不喜歡它,那么可以設(shè)置enumerable:false。那么它就不會(huì)出現(xiàn)在for..in循環(huán),就像內(nèi)置的一樣:

          let user = {
            name"John",
            toString() {
              return this.name;
            }
          };

          Object.defineProperty(user, "toString", {
            enumerablefalse
          });

          // Now our toString disappears:
          for (let key in user) alert(key); // name

          不可枚舉屬性也被排除在Object.keys之外:

          alert(Object.keys(user)); // name

          不可配置

          不可配置的標(biāo)志(configurable:fals)有時(shí)是內(nèi)置對象和屬性的預(yù)置標(biāo)志。

          不能刪除不可配置的屬性。

          例如,Math.PI是不可寫、不可枚舉和不可配置的:

          let descriptor = Object.getOwnPropertyDescriptor(Math'PI');

          alert( JSON.stringify(descriptor, null2 ) );
          /*
          {
            "value": 3.141592653589793,
            "writable": false,
            "enumerable": false,
            "configurable": false
          }
          */

          因此,程序員無法改變Math.PI的值。或者重寫它。

          Math.PI = 3// Error

          // delete Math.PI won't work either

          使屬性不可配置是一條單行道。我們不能用defineProperty把它改回來。

          確切地說,不可配置性在defineProperty上強(qiáng)加了幾個(gè)限制:

          • 無法更改可配置標(biāo)志。

          • 不能改變enumerable標(biāo)志。

          • 不能將writable: false改為true(反過來也可以)。

          • 不能更改訪問器屬性的get/set(但如果沒有,可以分配它們)。

          “configurable:false”的思想是為了防止屬性標(biāo)記的更改和刪除,同時(shí)允許更改其值。

          這里user.name是不可配置的,但是我們?nèi)匀豢梢孕薷乃?因?yàn)樗强蓪懙?:

          let user = {
            name"John"
          };

          Object.defineProperty(user, "name", {
            configurablefalse
          });

          user.name = "Pete"// works fine
          delete user.name; // Error

          這里我們將user.name設(shè)為“永久密封”常數(shù):

          let user = {
            name"John"
          };

          Object.defineProperty(user, "name", {
            writablefalse,
            configurablefalse
          });

          // won't be able to change user.name or its flags
          // all this won't work:
          user.name = "Pete";
          delete user.name;
          Object.defineProperty(user, "name", { value"Pete" });

          Object.defineProperties

          有一個(gè)方法Object.defineProperties(obj, descriptors)允許一次定義許多屬性。

          語法是:

          Object.defineProperties(obj, {
            prop1: descriptor1,
            prop2: descriptor2
            // ...
          });

          例如:

          Object.defineProperties(user, {
            name: { value"John"writablefalse },
            surname: { value"Smith"writablefalse },
            // ...
          });

          Object.getOwnPropertyDescriptors

          要一次性獲得所有屬性描述符,我們可以使用Object.getOwnPropertyDescriptors(obj)方法。

          object.defineproperties一起,它可以作為一種“識(shí)別標(biāo)志”的方式來克隆對象:

          let clone = Object.defineProperties({}, Object.getOwnPropertyDescriptors(obj));

          通常,當(dāng)我們克隆一個(gè)對象時(shí),我們使用賦值來復(fù)制屬性,像這樣:

          for (let key in user) {
            clone[key] = user[key]
          }

          但這不會(huì)復(fù)制標(biāo)記。因此,如果我們想要一個(gè)“更好的”克隆,那么Object.defineProperties是首選。

          另一個(gè)區(qū)別是for…in會(huì)忽略符號(hào)屬性,但Object.getOwnPropertyDescriptors返回所有屬性描述符,包括符號(hào)描述符。

          全局密封對象

          屬性描述符在單個(gè)屬性的級(jí)別上工作。

          還有一些方法可以限制對整個(gè)對象的訪問:

          Object.preventExtensions(obj)

          禁止向?qū)ο筇砑有聦傩浴?/p>

          Object.seal(obj)

          禁止添加/刪除屬性。設(shè)置configurable: false為所有現(xiàn)有的屬性。

          Object.freeze(obj)

          禁止添加/刪除/更改屬性。設(shè)置configurable: false,writable: false所有現(xiàn)有的屬性。

          對他們也有一些測試:

          Object.isExtensible(obj)

          如果禁止添加屬性,則返回false,否則返回true。

          Object.isSealed(obj)

          如果禁止添加/刪除屬性,則返回true, 并且所有現(xiàn)有屬性都是configurable: false。

          Object.isFrozen(obj)

          如果禁止添加/刪除/更改屬性,則返回true,并且當(dāng)前所有屬性都是configurable: false, writable: false


          瀏覽 36
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  伊人色情网 | 乱伦一级片| 无套中出丰满人妻无码99 | 成人国产一区二区三区精品麻豆 | 操色逼网|