JavaScript中延迟加载属性模式有什么用

本篇内容主要讲解“JavaScript中延迟加载属性模式有什么用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JavaScript中延迟加载属性模式有什么用”吧!

成都创新互联公司专注为客户提供全方位的互联网综合服务,包含不限于成都网站建设、成都网站制作、绿园网络推广、成都微信小程序、绿园网络营销、绿园企业策划、绿园品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们最大的嘉奖;成都创新互联公司为所有大学生创业者提供绿园建站搭建服务,24小时服务热线:18982081108,官方网址:www.cdcxhl.com

一、前言

传统上,开发人员在 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中延迟加载属性模式有什么用”有了更深的了解,不妨来实际操作一番吧!这里是创新互联网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!


网页标题:JavaScript中延迟加载属性模式有什么用
网站URL:http://azwzsj.com/article/jpijgh.html