• 前端学习笔记--模拟call和apply以及沙盒模型


    模拟call
    • 第一个参数为null或者undefined时,this指向全局对象window,值为原始值的指向该原始值的自动包装对象,如 StringNumberBoolean
    • 为了避免函数名与上下文(context)的属性发生冲突,使用Symbol类型作为唯一值
    • 将函数作为传入的上下文(context)属性执行
    • 函数执行完成后删除该属性
    • 返回执行结果
    Function.prototype.myCall = function (context, ...args) {
        context = (context ?? window) || new Object(context)
        const key = Symbol()
        context[key] = this
        const result = context[key](...args)
        delete context[key]
        return result
    }
    function myfunc1() {
        this.name = 'Lee';
        this.myTxt = function (txt) {
            console.log('i am', txt);
        }
    }
    function myfunc2() {
        myfunc1.myCall(this);
    }
    var myfunc2Instance = new myfunc2();
    console.log(myfunc2Instance);
    myfunc2Instance.myTxt('Geing'); // i am Geing
    console.log(myfunc2Instance.name);	// Lee
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    注:ES2020新特性,Null判断符 ??

    模拟apply
    • 前部分与call一样
    • 第二个参数可以不传,但类型必须为数组或者类数组
    Function.prototype.myApply = function (context) {
        context = (context ?? window) || new Object(context);
        const key = Symbol();
        const args = arguments[1];
        context[key] = this;
        let result;
        if (args) {
            result = context[key](...args);
        } else {
            result = context[key]();
        }
        return result;
    }
    function myfunc1() {
        this.name = 'Lee';
        this.myTxt = function (txt) {
            console.log('i am', txt);
        }
    }
    function myfunc2() {
        myfunc1.myApply(this);
    }
    var myfunc2Instance = new myfunc2();
    console.log(myfunc2Instance);
    myfunc2Instance.myTxt('Geing'); // i am Geing
    console.log(myfunc2Instance.name);	// Lee
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    注:代码实现存在缺陷,当第二个参数为类数组时,未作判断

    沙盒模型
    1.代理沙盒
    window = global
    function proxySanbox() {
        const originalWindow = window;
        this.fackWindow = {}
        this.proxy = new Proxy(this.fackWindow, {
            set(target, p, value) {
                target[p] = value;
                return true;
            },
            get(target, p) {
                return target[p] || originalWindow[p];
            }
        })
    }
    const sanbox1 = new proxySanbox();
    const sanbox2 = new proxySanbox();
    window.a = 'a in window';
    console.log(window.a);//a in window
    ((window) => {
        window.a = 'a in sanbox1';
        console.log(window.a);//a in sanbox1
    })(sanbox1.proxy);
    ((window) => {
        window.a = 'a in sanbox2';
        console.log(window.a);//a in sanbox2
    })(sanbox2.proxy);
    console.log(window.a);//a in window
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    2.快照沙盒
    window = global
    class snapshotSanbox {
        constructor() {
            this.snapshot = {}
            this.modifyProps = {};
        }
        active() {
            for (const prop in window) {
                if (window.hasOwnProperty(prop)) {
                    this.snapshot[prop] = window[prop];
                }
            }
            Object.keys(this.modifyProps).forEach((prop) => {
                window[prop] = this.modifyProps[prop]
            })
        }
        inActive() {
            for (const prop in window) {
                if (window.hasOwnProperty(prop)) {
                    if (window[prop] !== this.snapshot[prop]) {
                        this.modifyProps[prop] = window[prop];
                        window[prop] = this.snapshot[prop];
                    }
                }
            }
        }
    }
    const sanbox1 = new snapshotSanbox();
    const sanbox2 = new snapshotSanbox();
    window.a = 'a in window';
    console.log(window.a); //a in window
    sanbox1.active()
    window.a = 'a in sanbox1';
    console.log(window.a);//a in sanbox1
    sanbox1.inActive()
    console.log(window.a);//a in window
    sanbox2.active()
    window.a = 'a in sanbox2';
    console.log(window.a);//a in sanbox2
    sanbox2.inActive()
    console.log(window.a);//a in window
    sanbox1.active()
    console.log(window.a);//a in sanbox1
    sanbox2.active()
    console.log(window.a);//a in sanbox2
    sanbox2.inActive()
    console.log(window.a);//a in sanbox1
    sanbox1.inActive()
    console.log(window.a);//a in window
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
  • 相关阅读:
    Type-c接口及其协议介绍
    java基本微信小程序的心理服务平台 uniapp 小程序
    【Python】第五课 函数
    数据分析入门全攻略:从新手到专家
    【数据结构】查找— —树表的查找(二叉排序树、平衡二叉树)
    Camera-3A AE/AWB/AF
    MySQL精髓:如何使用ALL一次找到最大值
    香港裸机云多IP服务器都有哪些配置?
    上位机图像处理和嵌入式模块部署(树莓派4b进行自动化测试)
    【从头构筑C#知识体系】1.9 特性
  • 原文地址:https://blog.csdn.net/DeepLearning_/article/details/134406135