zoukankan      html  css  js  c++  java
  • js动态加载脚本之实用小技巧

      最近我们公司的iClient产品需要改动,由于我们的包大概有1M了,用户在使用的过程中如果网速不是很好的话,加载的就比较慢,用户体验就不好,上面要求用户初始化的时候只有基础包,比较小,当用户用到哪一块功能就加载哪块的功能,这样体验上要好得多,但是我们的用户已经有很多了,那么我们就不能让用户改变以前的代码,只能让用户把包替换一下,这里研究了几天研究了一种办法和大家分享一下。对于做产品的朋友可能会有帮助吧!

      对于产品包来说,无非就是N多的类。用户一般使用的时候都是new一个对象,然后开始使用它!比如我们有一个Person类,这里就会涉及到当浏览器运行到var person = new Person()这里时,其实内存里面还没有这个类,我们并没有在一开始就导进来,但是如果没有的话浏览器肯定会报错,那我们在new之前加一句代码来导包,这样不就是需要更改用户的源代码了吗?肯定不可取。我们需要在浏览器new对象的时候把对应的类导进来,而又不改变任何源代码,如何做到?

      我们可以在基础包里面对每一个类写一个假的类,但是命名空间、类名必须都是一样的,但类里面除了构造函数什么都没有,这样假类就很小,基本不会使基础包的大小改变多少,这样在浏览器运行到如var person = new Person()这一句的时候至少不会报告错误,但是生成的对象person是假的,不可用的,我们得想办法让它变成真的,怎么才能让new出的对象不是自己而是其他的对象呢?

      我尝试了很多种办法,比如在构造函数里面改变过this.__proto__.constructor、this.__proto__、this等手段,希望最后new出来的对象不是自身,而和new Person(真的)一样,但是你可以调试发现没法做到一模一样,最后无意间发现在构造函数里面使用return就可以改变new出来的对象,如下面new Person()出一个对象。

            function Person()
            {
                return new Date();
            }

      你会发现new出来的不是Person的对象,而是一个Date对象,而且和new Date()出来的对象一模一样,这是js这门语言故意这样设计吧!也不知道最开始的目的是啥!如果使用return;或者return null;最后new出来的对象还是本身。这样第一个问题就解决了,可以new出一个非自身的对象。

      继续讨论,现在我们new出来的对象需要时真的那个类,而不是那个假的类,但是两个类的命名空间和类名都是一样的,这可怎么办,其实大家都知道所有的类无非就是window的属性而已,其实都是指针,我把指向的部分改变后不久实现了吗?

      我们先需要写一个真的类,创建一个Person.js文件,打开后写入如下代码:

    function Person(name,age){
        this.name =  name;
        this.age = age;
        this.getName = function(){
            return this.name;
        }
        this.getAge = function(){
            return this.age;
        }
    }

      这是一个真的类,有name和age两个属性以及getName()和getAge()两个方法。在在同样的文件夹下创建一个html文件,代码如下:

    <html>
    <head>
        <title></title>
        <script type="text/javascript" src="loadJS.js"></script>
        <script type="text/javascript">
            function init()
            {
                var person = new Person("Bill",23);
                var name = person.getName();
                var age = person.getAge();
                alert(name + "_" + age);
            }
            function Person(name,age)
            {
                loadJS("idPerson","Person.js");
                return  new Person(name,age);
            }
        </script>
    </head>
    <body>
        <button onclick="init()">测试</button>
    </body>
    </html>

      这里有一个loadJS.js文件,这是一个动态同步加载js文件的一个包,我自己写的,很简单,里面的内容详见《js动态加载脚本》里面的第六种方法里有源代码,其实就一个方法loadJS(id,url)。上面代码已经有一个假的Person存在了,里面有两句代码,第一句是加载真的Person,第二句是返回一个Person对象,当我们调试的时候你会惊奇的发现,当真的Person加载进来后Person这个类就变成了真的类,而假的类在new以后就没有了,因为没有指针指向它了,它接下来就会被回收机制给回收掉,new玩后发现person就成为了真的那个Person的对象,当你再次new Person()的时候发现直接就是真的Person对象了,因为已经加载过一次了。

      我们仔细思考一下,如果Person这个类用到了我们其他没加载的类,浏览器也会先寻找到假的那个类,再次去加载需要的类,这就形成了一个循环,需要什么类的时候再加载什么,不会多加载任何一个多余的类。前提是你得每一个类对应一个js文件。你也可以分成多少个模块,每个模块里面有多个类,那么每一次去加载就会加载一个模块,一个模块加载进来后会替换掉其中一部分假类。无论怎么设计都很方便。

      好了,所有问题都解决了,我们需要把假的类封装进我们的产品包,然后让用户把这个包替换掉,用户不需要改变任何以前项目的源代码,就可以做到动态加载需要的脚本。这个办法是不是很好用?好用就帮我顶一下!

  • 相关阅读:
    你好,这里有一份2019年目标检测指南
    谷歌2019 学术指标发榜:CVPR首次进入Top 10,何恺明论文引用最高!
    魔图互联:知识图谱推荐系统-给人们带来更个性化的推荐
    NLPer入门指南 | 完美第一步
    一文总结数据科学家常用的Python库(下)
    一文总结数据科学家常用的Python库(上)
    一文看懂NLP神经网络发展历史中最重要的8个里程碑!
    如何为计算机视觉任务选择正确的标注类型
    C. Queen Codeforces Round #549 (Div. 2) dfs
    D. Equalize Them All Codeforces Round #550 (Div. 3)
  • 原文地址:https://www.cnblogs.com/zhuimengdeyuanyuan/p/2949920.html
Copyright © 2011-2022 走看看