<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>

          JavaScript中延遲加載屬性模式

          共 9358字,需瀏覽 19分鐘

           ·

          2021-04-28 11:56

          (給前端大學(xué)加星標(biāo),提升前端技能.

          譯者:飄飄 作者:Nicholas C. Zakas

          https://humanwhocodes.com/blog/2021/04/lazy-loading-property-pattern-javascript/

          You can defer computationally-expensive operations until needed using an accessor property.

          你可以使用訪問器屬性將計(jì)算量大的操作推遲到需要時(shí)進(jìn)行。

          Traditionally, developers have created properties inside of JavaScript classes for any data that might be needed within an instance. This isn’t a problem for small pieces of data that are readily available inside of the constructor. However, if some data needs to be calculated before becoming available in the instance, you may not want to pay that cost upfront. For example, consider this class:

          傳統(tǒng)意義上,開發(fā)人員在JavaScript類內(nèi)部為實(shí)例可能需要的任何數(shù)據(jù)創(chuàng)建屬性。對(duì)于在構(gòu)造函數(shù)內(nèi)部隨時(shí)可用的小數(shù)據(jù)而言,這不是問題。但是,如果在實(shí)例可用之前需要計(jì)算一些數(shù)據(jù),你可能不希望預(yù)先支付這個(gè)成本。例如,考慮這個(gè)類。

          1. class MyClass {

          2. constructor() {

          3. this.data = someExpensiveComputation();

          4. }

          5. }

          Here, the data property is created as the result of performing some expensive computation. It may not be efficient to perform that calculation upfront if you aren’t sure the property will be used. Fortunately, there are several ways to defer these operations until later.

          這里,由于執(zhí)行一些昂貴的計(jì)算而創(chuàng)建了數(shù)據(jù)屬性。如果你不確定該屬性會(huì)被使用,則提前執(zhí)行該計(jì)算可能并不高效。幸運(yùn)的是,有幾種方法可以將這些操作推遲到以后。

          按需屬性模式 The on-demand property pattern

          The easiest way to optimize performing an expensive operation is to wait until the data is needed before doing the computation. For example, you could use an accessor property with a getter to do the computation on demand, like this:

          最優(yōu)化執(zhí)行昂貴操作的最簡(jiǎn)單方法是,等到需要數(shù)據(jù)時(shí)再進(jìn)行計(jì)算。例如,你可以使用一個(gè)帶有g(shù)etter的accessor屬性來按需進(jìn)行計(jì)算,如下所示。

          1. class MyClass {

          2. get data() {

          3. return someExpensiveComputation();

          4. }

          5. }

          In this case, your expensive computation isn’t happening until the first time someone reads the data property, which is an improvement. However, that same expensive computation is performed every time the data property is read, which is worse than previous example where at least the computation was performed just once. This isn’t a good solution, but you can build upon it to create a better one.

          在這種情況下,只有當(dāng)有人第一次讀取data屬性時(shí),昂貴的計(jì)算才會(huì)發(fā)生,這是一個(gè)改進(jìn)。但是,每次讀取data屬性時(shí)都執(zhí)行相同昂貴的計(jì)算,這比之前的例子(其中該計(jì)算至少執(zhí)行一次)的效果差。這不是一個(gè)好的解決方案,但你可以在此基礎(chǔ)上創(chuàng)建一個(gè)更好的解決方案。

          混亂的延遲加載屬性模式 The messy lazy-loading property pattern

          Only performing the computation when the property is accessed is a good start. What you really need is to cache the information after that point and just use the cached version. But where do you cache that information for easy access? The easiest approach is to define a property with the same name and set its value to the computed data, like this:

          只在在訪問該屬性時(shí)才執(zhí)行計(jì)算是一個(gè)好的開始。你真正需要的是在那之后對(duì)信息進(jìn)行緩存,然后僅使用緩存的版本。但是你將信息緩存在哪里方便訪問呢?最簡(jiǎn)單的方法是定義一個(gè)同名的屬性,并將其值設(shè)置為計(jì)算的數(shù)據(jù),像這樣。

          1. class MyClass {

          2. get data() {

          3. const actualData = someExpensiveComputation();


          4. Object.defineProperty(this, "data", {

          5. value: actualData,

          6. writable: false,

          7. configurable: false,

          8. enumerable: false

          9. });


          10. return actualData;

          11. }

          12. }

          Here, the data property is once again defined as a getter on the class, but this time it caches the result. The call to Object.defineProperty() creates a new property called data that has a fixed value of actualData, and is set to not be writable, configurable, and enumerable (to match the getter). After that, the value itself is returned. The next time the data property is accessed, it will be reading from the newly created property rather than calling the getter:

          在這里,data屬性再次被定義為類的getter,但這一次它緩存了結(jié)果。對(duì)Object.defineProperty()的調(diào)用會(huì)創(chuàng)建了一個(gè)名為data的新屬性,該屬性的固定值為actualData,并設(shè)置為不可寫、可配置和可枚舉(以匹配getter)之后,將返回值本身。下次訪問data屬性時(shí),它將從新創(chuàng)建的屬性讀取,而不是調(diào)用getter。

          1. const object = new MyClass();


          2. // calls the getter

          3. const data1 = object.data;


          4. // reads from the data property

          5. const data2 = object.data;

          Effectively, all of the computation is done only the first time the data property is read. Each subsequent read of the data property is returning the cached the version.

          實(shí)際上,所有的計(jì)算都是在第一次讀取數(shù)據(jù)屬性時(shí)才完成的。之后每次讀取數(shù)據(jù)屬性都會(huì)返回緩存的版本。

          The one downside to this pattern is that the data property starts out as a non-enumerable prototype property and ends up as a non-enumerable own property:

          這種模式的一個(gè)缺點(diǎn)是,data屬性開始時(shí)是不可枚舉的原型屬性,最后是一個(gè)不可枚舉的自有屬性。

          1. const object = new MyClass();

          2. console.log(object.hasOwnProperty("data")); // false


          3. const data = object.data;

          4. console.log(object.hasOwnProperty("data")); // true

          While this distinction isn’t important in many cases, it is an important thing to understand about this pattern as it can cause subtle issues when the object is passed around. Fortunately, it’s easy to address this with an updated pattern.

          雖然這種區(qū)別在很多情況下并不重要,但了解這種模式很重要,因?yàn)楫?dāng)對(duì)象傳遞時(shí),這種模式可能會(huì)引起細(xì)微的問題。幸運(yùn)的是,用一個(gè)更新的模式可以輕松解決此問題。

          類的唯一的延遲加載屬性模式 The only-own lazy-loading property pattern for classes

          If you have a use case where it’s important for the lazy-loaded property to always exist on the instance, then you can using Object.defineProperty() to create the property inside of the class constructor. It’s a little bit messier than the previous example, but it will ensure that the property only ever exists on the instance. Here’s an example:

          如果你有一個(gè)實(shí)例,對(duì)于該實(shí)例始終存在延遲加載的屬性很重要,那么你可以使用Object.defineProperty()在類的構(gòu)造函數(shù)內(nèi)部創(chuàng)建該屬性。這比前面的例子要混亂一些,但它能確保該屬性只存在于實(shí)例上。下面是一個(gè)例子。

          1. class MyClass {

          2. constructor() {

          3. const instance = this;

          4. Object.defineProperty(this, "data", {

          5. get() {

          6. const actualData = someExpensiveComputation();

          7. Object.defineProperty(instance, "data", {

          8. value: actualData,

          9. writable: false,

          10. configurable: false

          11. });

          12. return actualData;

          13. },

          14. configurable: true,

          15. enumerable: true

          16. });

          17. }

          18. }

          Here, the constructor creates the data accessor property using Object.defineProperty(). The property is created on the instance (by using this) and defines a getter as well as specifying the property to be enumerable and configurable (typical of own properties). It’s particularly important to set the data property as configurable so you can call Object.defineProperty() on it again.

          在這里,構(gòu)造函數(shù)使用Object.defineProperty()創(chuàng)建數(shù)據(jù)訪問器屬性。該屬性是在實(shí)例上創(chuàng)建的(通過使用此屬性),并定義了一個(gè)getter,并指定該屬性為可枚舉和可配置(典型的自有屬性)。將data屬性設(shè)置為可配置尤其重要的,這樣你就可以再次調(diào)用Object.defineProperty()了。

          The getter function then does the computation and calls Object.defineProperty() a second time. The data property is now redefined as a data property with a specific value and is made non-writable and non-configurable to protect the final data. Then, the computed data is returned from the getter. The next time the data property is read, it will read from the stored value. As a bonus, the data property now only ever exists as an own property and acts the same both before and after the first read:

          然后getter函數(shù)進(jìn)行計(jì)算并再次調(diào)用Object.defineProperty()。注意,第一個(gè)參數(shù)是instance,因?yàn)樗趃etter函數(shù)內(nèi)部有著不同的含義--它引用申明了getter函數(shù)的對(duì)象,而不是MyClass的實(shí)例。現(xiàn)在將data屬性重新定義為具有特定值的data屬性,并且將其變成不可寫和不可配置的,以保護(hù)最終數(shù)據(jù)。然后,計(jì)算好的數(shù)據(jù)從getter返回。下次讀取數(shù)據(jù)屬性時(shí),它將從存儲(chǔ)的值中讀取。另外,data屬性現(xiàn)在只作為一個(gè)自己的屬性存在,在第一次讀取之前和之后的行為都是一樣的。

          1. const object = new MyClass();

          2. console.log(object.hasOwnProperty("data")); // true


          3. const data = object.data;

          4. console.log(object.hasOwnProperty("data")); // true

          For classes, this is most likely the pattern you want to use; object literals, on the other hand, can use a simpler approach.

          對(duì)于類來說,這很可能是你想使用的模式;另一方面,對(duì)象字面量可以使用更簡(jiǎn)單的方法。

          對(duì)象字面量的延遲加載屬性模式 The lazy-loading property pattern for object literals

          If you are using an object literal instead of a class, the process is must simpler because getters defined on object literals are defined as enumerable own properties (not prototype properties) just like data properties. That means you can use the messy lazy-loading property pattern for classes without being messy:

          如果你使用的是一個(gè)對(duì)象字面量,而不是一個(gè)類,那么這個(gè)過程肯定更簡(jiǎn)單,因?yàn)樵趯?duì)象字面量上定義的getters與data屬性一樣被定義為可枚舉的自有屬性(而不是原型屬性)。這意味著你可以對(duì)類使用混亂的延遲加載屬性模式,而不會(huì)造成混亂。

          1. const object = {

          2. get data() {

          3. const actualData = someExpensiveComputation();


          4. Object.defineProperty(this, "data", {

          5. value: actualData,

          6. writable: false,

          7. configurable: false,

          8. enumerable: false

          9. });

          10. return actualData;

          11. }

          12. };


          13. console.log(object.hasOwnProperty("data")); // true

          14. const data = object.data;

          15. console.log(object.hasOwnProperty("data")); // true

          結(jié)束語 Conclusion

          The ability to redefine object properties in JavaScript allows a unique opportunity to cache information that may be expensive to compute. By starting out with an accessor property that is redefined as a data property, you can defer computation until the first time a property is read and then cache the result for later use. This approach works both for classes and for object literals, and is a bit simpler in object literals because you don’t have to worry about your getter ending up on the prototype.

          在JavaScript中重新定義對(duì)象屬性的能力為緩存信息(計(jì)算起來可能會(huì)很貴)提供了獨(dú)特的機(jī)會(huì)。通過從重新定義為data屬性的訪問器屬性開始,你可以將計(jì)算推遲到第一次讀取該屬性時(shí),然后將結(jié)果緩存起來以備后用。這種方法既適用于類,也適用于對(duì)象字面量,而且在對(duì)象字面量中更簡(jiǎn)單一些,因?yàn)槟悴槐負(fù)?dān)心你的getter最終會(huì)出現(xiàn)在原型上。

          One of the best ways to improve performance is to avoid doing the same work twice, so any time you can cache a result for use later, you’ll speed up your program. Techniques like the lazy-loading property pattern allow any property to become a caching layer to improve performance.

          改善性能的最好方法之一是避免兩次做同樣的工作,所以任何時(shí)候你可以緩存結(jié)果供以后使用,就可以加快程序運(yùn)行速度。諸如延遲加載屬性模式之類的技術(shù)使任何屬性都可以成為緩存層以提高性能。

          點(diǎn)贊和在看就是最大的支持??

          瀏覽 93
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(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>
                  黄在线观看视频 | 色悠综合| 男人露大鸡巴无遮挡免费视频 | 91美女操| 综合+++夜夜 |