• 闭包——破坏第三方库


    闭包

    1 获取 obj 对象

    1.1 失败获取
    var o = (function () {
      var obj = {
        a: 1,
        b: 2,
      };
      return {
        getObj: function (k) {
          return obj[k];
        },
      };
      
    })();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    const res = o.getObj('a');
    console.log('===>res', res); // ===>res 1
    
    • 1
    • 2
    // 不改变上面代码的情况下,修改 obj 对象。破坏第三方库
    const resValueOf = o.getObj('valueOf');
    console.log('===>resValueOf', resValueOf); // ===>resValueOf [Function: valueOf]
    
    • 1
    • 2
    • 3

    o.getObj('valueOf')() 调用失败;原因: this 指向不对

    const resValueOfObj = o.getObj('valueOf')(); // 返回 obj 对象本身失败,原因:this指向不对
    console.log('===>resValueOfObj', resValueOfObj); // this指向有问题,会报错:TypeError: Cannot convert undefined or null to object
    
    // o.getObj('valueOf')函数的 this 指向全局,严格模式下指向undefined
    // 执行 const resValueOfObj = o.getObj('valueOf')()
    // 相当于执行
    // const valueOf = Object.prototype.valueOf;   
    // valueOf();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1.2 使用函数调用结果获取 obj 对象

    那么如何获取 obj 对象本身呢?可以这样去写

    
    var o = (function () {
      var obj = {
        a: 1,
        b: 2,
      };
      return {
        getObj: function (k) {
          return obj[k](); // 返回函数调用结果
        },
      };
    })();
    
    
    // 不改变上面代码的情况下,修改 obj 对象。破坏第三方库
    
    const resValueOfObj = o.getObj('valueOf'); // 返回 obj 对象本身
    console.log('===>resValueOfObj', resValueOfObj); // ===>resValueOfObj { a: 1, b: 2 }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    1.3 利用 defineProperty,获取 obj 对象

    不通过 “返回函数调用结果”,如何获取对象本身,并且更改 obj 对象,破坏第三方库?

    var o = (function () {
      var obj = {
        a: 1,
        b: 2,
      };
      return {
        getObj: function (k) {
          return obj[k];
        },
      };
      
    })();
    
    const res = o.getObj('a');
    console.log('===>res', res); // ===>res 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    // 不改变上面代码的情况下,修改 obj 对象。破坏第三方库
    
    Object.defineProperty(Object.prototype, 'abc', {
      get() {
        return this;
      }
    })
    const resValueOfObj = o.getObj('abc');
    console.log('===>resValueOfObj', resValueOfObj); // ===>resValueOfObj { a: 1, b: 2 }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    修改 obj 对象;破坏第三方库

    resValueOfObj.c = 2;
    resValueOfObj.a = 'aaa';
    console.log('===>resValueOfObj.a', resValueOfObj.a); // ===>resValueOfObj.a aaa
    console.log('===>resValueOfObj.c', resValueOfObj.c); // ===>resValueOfObj.c 2
    
    console.log('===>o.getObj(a)', o.getObj('a'));  // ===>o.getObj(a) aaa
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2 防止破坏第三方库

    那么如何防止破坏第三方库呢?或者说在写公共模块时,如何防止破坏呢?

    2.1 利用 hasOwnProperty

    var o = (function () {
      var obj = {
        a: 1,
        b: 2,
      };
      return {
        getObj: function (k) {
          if (obj.hasOwnProperty(k)) {
            return obj[k];
          }
          return undefined;
        },
      };
      
    })();
    
    const res = o.getObj('a');
    console.log('===>res', res); // ===>res 1
    
    
    Object.defineProperty(Object.prototype, 'abc', {
      get() {
        return this;
      }
    })
    const resValueOfObj = o.getObj('abc');
    console.log('===>resValueOfObj', resValueOfObj); // ===>resValueOfObj undefined
    
    
    • 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
    2.2 将 obj 对象的原型设为 null

    Object.setPrototypeOf(obj, null)

    var o = (function () {
      var obj = {
        a: 1,
        b: 2,
      };
    
      Object.setPrototypeOf(obj, null); // 将 obj 对象的原型设为 null
      return {
        getObj: function (k) {
          return obj[k];
        },
      };
      
    })();
    
    const res = o.getObj('a');
    console.log('===>res', res); // ===>res 1
    
    
    Object.defineProperty(Object.prototype, 'abc', {
      get() {
        return this;
      }
    })
    const resValueOfObj = o.getObj('abc');
    console.log('===>resValueOfObj', resValueOfObj); // ===>resValueOfObj undefined
    
    
    • 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
  • 相关阅读:
    运维技术linux、nginx
    窗口管理工具 Mosaic mac中文版功能特点
    记十次面试字节/美团失败总结的《520道LeetCode题Java版答案》
    centos常见的命令
    Jmeter基础入门教程【22】--常用功能详解:响应断言
    【数据结构】链表其实并不难 —— 手把手带你实现双向链表
    乾元通多卡聚合路由器的技术解析
    什么是FSDM的九大数据概念
    ModStart系统安全规范建议
    如何排查 Flink Checkpoint 失败问题?
  • 原文地址:https://blog.csdn.net/weixin_45678402/article/details/132922608