浅谈JavaScript 中的延迟加载属性模式

目录
  • 一、前言
  • 二、按需属性模式
  • 三、凌乱的延迟加载属性模式
  • 四、类的唯一自己的延迟加载属性模式
  • 五、对象字面量的延迟加载属性模式
  • 六、结论

一、前言

传统上,开发人员在 JavaScript 类中为实例中可能需要的任何数据创建属性。对于在构造函数中随时可用的小块数据来说,这不是问题。但是,如果在实例中可用之前需要计算某些数据,您可能不想预先支付该费用。例如,考虑这个类:

class MyClass {
    constructor() {
        this.data = someExpensiveComputation();
    }
}

在这里,data属性是作为执行一些昂贵计算的结果而创建的。如果您不确定是否会使用该属性,则预先执行该计算可能效率不高。幸运的是,有几种方法可以将这些操作推迟到以后。

二、按需属性模式

优化执行昂贵操作的最简单方法是等到需要数据后再进行计算。例如,您可以使用带有 getter 的访问器属性来按需进行计算,如下所示:

class MyClass {
    get data() {
        return someExpensiveComputation();
    }
}

在这种情况下,直到有人第一次读取该data属性时,您的昂贵计算才会发生,这是一种改进。但是,每次data读取属性时都会执行相同的昂贵计算,这比之前的示例更糟糕,其中至少只执行了一次计算。这不是一个好的解决方案,但您可以在此基础上创建一个更好的解决方案。

三、凌乱的延迟加载属性模式

只有在访问属性时才执行计算是一个好的开始。您真正需要的是在该点之后缓存信息并仅使用缓存版本。但是您将这些信息缓存在哪里以便于访问?最简单的方法是定义一个具有相同名称的属性并将其值设置为计算数据,如下所示:

class MyClass {
    get data() {
        const actualData = someExpensiveComputation();

        Object.defineProperty(this, "data", {
            value: actualData,
            writable: false,
            configurable: false,
            enumerable: false
        });

        return actualData;
    }
}

在这里,该data属性再次定义为类上的 getter,但这次它缓存了结果。调用Object.defineProperty()创建一个名为的新属性data,该属性具有固定值actualData,并且设置为不可写、可配置和不可枚举(以匹配 getter)。之后,返回值本身。下次data访问该属性时,它将从新创建的属性中读取而不是调用 getter:

const object = new MyClass();

// calls the getter
const data1 = object.data;

// reads from the data property
const data2 = object.data;

实际上,所有计算仅在第一次data读取属性时完成。对该data属性的每次后续读取都返回缓存的版本。

这种模式的一个缺点是data属性开始是不可枚举的原型属性,最终是不可枚举的自己的属性:

const object = new MyClass();
console.log(object.hasOwnProperty("data"));     // false

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

虽然这种区别在很多情况下并不重要,但理解这种模式很重要,因为它在传递对象时可能会导致微妙的问题。幸运的是,使用更新的模式很容易解决这个问题。

四、类的唯一自己的延迟加载属性模式

如果您有一个用例,其中延迟加载的属性始终存在于实例中很重要,那么您可以使用Object.defineProperty()在类构造函数中创建属性。它比前面的例子有点混乱,但它会确保该属性只存在于实例上。下面是一个例子:

class MyClass {
    constructor() {

        Object.defineProperty(this, "data", {
            get() {
                const actualData = someExpensiveComputation();

                Object.defineProperty(this, "data", {
                    value: actualData,
                    writable: false,
                    configurable: false
                });

                return actualData;
            },
            configurable: true,
            enumerable: true
        });

    }
}

在这里,构造函数data使用Object.defineProperty().该属性是在实例上创建的(通过使用this)并定义一个 getter 并指定该属性为可枚举和可配置的(典型的自己的属性)。将data属性设置为可配置特别重要,以便您可以Object.defineProperty()再次调用它。

然后 getter 函数进行计算并再次调用Object.defineProperty()。该data属性现在被重新定义为具有特定值的数据属性,并且不可写和不可配置以保护最终数据。然后,计算数据从 getter 返回。下次data读取属性时,它将从存储的值中读取。作为奖励,该data财产现在仅作为自己的财产存在,并且在第一次阅读之前和之后的行为都相同:

const object = new MyClass();
console.log(object.hasOwnProperty("data"));     // true

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

对于类,这很可能是您要使用的模式;另一方面,对象文字可以使用更简单的方法。

五、对象字面量的延迟加载属性模式

如果您使用对象字面量而不是类,则过程要简单得多,因为在对象字面量上定义的 getter 被定义为可枚举的自身属性(而不是原型属性),就像数据属性一样。这意味着您可以对类使用凌乱的延迟加载属性模式而对于对象来说不会凌乱:

const object = {
    get data() {
        const actualData = someExpensiveComputation();

        Object.defineProperty(this, "data", {
            value: actualData,
            writable: false,
            configurable: false,
            enumerable: false
        });

        return actualData;
    }
};

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

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

六、结论

在 JavaScript 中重新定义对象属性的能力提供了一个独特的机会来缓存可能计算成本很高的信息。通过从重新定义为数据属性的访问器属性开始,您可以将计算推迟到第一次读取属性时,然后缓存结果以供以后使用。这种方法既适用于类,也适用于对象字面量,并且在对象字面量中更简单一些,因为您不必担心您的 getter 会在原型上结束。

提高性能的最佳方法之一是避免重复执行相同的工作,因此任何时候您可以缓存结果以供以后使用,都可以加快程序的运行速度。延迟加载属性模式等技术允许任何属性成为缓存层以提高性能。

以上就是浅谈JavaScript 中的延迟加载属性模式的详细内容,更多关于JS 延迟加载属性模式的资料请关注我们其它相关文章!

(0)

相关推荐

  • JS同步、异步、延迟加载的方法

    本文讲述了JS同步.异步.延迟加载的方法.分享给大家供大家参考,具体如下: 一:同步加载 我们平时使用的最多的一种方式. <script src="http://yourdomain.com/script.js"></script> 同步模式,又称阻塞模式,会阻止浏览器的后续处理,停止后续的解析,只有当当前加载完成,才能进行下一步操作.所以默认同步执行才是安全的.但这样如果js中有输出document内容.修改dom.重定向等行为,就会造成页面堵塞.所以一般建议

  • js图片延迟加载(Lazyload)三种实现方式

    延迟加载也称为惰性加载,即在长网页中延迟加载图像. 用户滚动到它们之前,视口外的图像不会加载. 这与图像预加载相反,在长网页上使用延迟加载将使网页加载更快. 在某些情况下,它还可以帮助减少服务器负载. 延迟加载的优点: 提升用户的体验,如果图片数量较大,打开页面的时候要将将页面上所有的图片全部获取加载,很可能会出现卡顿现象,影响用户体验.因此,有选择性地请求图片,这样能明显减少了服务器的压力和流量,也能够减小浏览器的负担. 方法一 将页面上所有图片的src属性设置为loading.gif,而图片

  • js实现延迟加载的几种方法

    js的延迟加载有助与提高页面的加载速度,以下是延迟加载的几种方法: 1.使用setTimeout延迟方法的加载时间 延迟加载js代码,给网页加载留出更多时间 <script type="text/javascript" > function A(){ $.post("/lord/login",{name:username,pwd:password},function(){ alert("Hello"); }); } $(functio

  • js图片加载效果实例代码(延迟加载+瀑布流加载)

    主要做了两种图片加载的效果 一种是遇到页面图片比较多的时候,带读条效果的加载提示(为了验证正确加载,设置了1秒钟的加载间隔时间) 另外一种是根据滑块的位置进行图片的预加载,在用户不察觉的情况下,实现瀑布流的加载效果 一 延迟加载 主要思路: HTML的img标签中,将正确的地址存在data-src属性中,给所有图片设置一个转圈圈的loading图片作为background js中,依次读取每一个img,将data-src中的地址替换到src中,去掉background 每成功加载一张图片,进度条

  • JavaScript图像延迟加载库Echo.js

    Echo 是一个独立的 JavaScript 懒加载图像的工具,快速.体积小(不足1k)和使用 HTML5 的 data- 属性.Echo 支持 IE8+ . 插件描述:和 Lazy Load 一样,Echo.js 也是一个用于图像延迟加载 JavaScript.不同的是 Lazy Load 是基于 jQuery 的插件,而 Echo.js 不依赖于 jQuery 或其他 JavaScript 库,可独立使用.并且 Echo.js 非常小巧,压缩后不足 1KB. 兼容性 Echo.js 使用了

  • jquery插件lazyload.js延迟加载图片的使用方法

    如果一个网页很长并且有很多图片的话,下载图片就需要很多时间,那么就会影响整个网页的加载速度,而这款延迟加载插件,会通过你的滚动情况来加载你需要看的图片,然后它才会从后台请求下载图片,最后显示出来.通过这个插件,可以在需要显示图片的时候,才下载图片,从而可以减少服务器的压力,提高页面加载速度. Lazy Load 插件原理 修改目标img元素的src属性为orginal属性,从而中断图片的加载.检测滚动状态,然后把网页可视区域中的img的src属性还原然后加载图片,从而制造了一种缓冲加载的效果.代

  • Jquery图片延迟加载插件jquery.lazyload.js的使用方法

    最新版的jquery.lazyload.js已不再是伪的延迟加载了 一.请按照基本使用方法说明设置 复制代码 代码如下: //载入JavaScript 文件<script src="jquery.js" type="text/javascript"></script><script src="jquery.lazyload.js" type="text/javascript"></sc

  • JS实现图片延迟加载并淡入淡出效果的简单方法

    话不多说,直接看示例 首先是图片标记的写法 <img data-src="/images/image.jpg" alt=""> 需要将图片的地址放到 data-src 属性里,而src值不需要,直接将src属性去掉. CSS代码 所有具有data-src属性的图片,我们将其初始显示状态为不可见,通过透明度来调节: img { opacity: 1; transition: opacity 0.3s; } img[data-src] { opacity:

  • js实现延迟加载的几种方法详解

    这是一个面试经常问到的问题:js的延迟加载方法 (js的延迟加载有助于提高页面的加载速度) 主要考察对程序的性能方面是否有研究,程序的性能是一个项目不断地追求的,通常也是项目完成后需要长期做的一件事情,像腾讯QQ依然对程序的性能不断地做优化,让用户的体验更好,性能优化的核心思想就是快,可以预先准备数据(如缓存的使用),可以按需获取,可以分段获取等都是常见的优化手段. 解题思路 : 1.defer属性 <script src="file.js" defer> </scr

  • ECHO.js 纯javascript轻量级延迟加载的实例代码

    ECHO.js 纯javascript轻量级延迟加载的实例代码 演示 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <title>简单的JavaScript图像延迟加载库Echo.js</title> <style> .demo img { width: 736px; height: 490px;

随机推荐