闭包——破坏第三方库

闭包

1 获取 obj 对象

1.1 失败获取
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
// 不改变上面代码的情况下,修改 obj 对象。破坏第三方库
const resValueOf = o.getObj('valueOf');
console.log('===>resValueOf', resValueOf); // ===>resValueOf [Function: valueOf]

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 使用函数调用结果获取 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.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
// 不改变上面代码的情况下,修改 obj 对象。破坏第三方库

Object.defineProperty(Object.prototype, 'abc', {
  get() {
    return this;
  }
})
const resValueOfObj = o.getObj('abc');
console.log('===>resValueOfObj', resValueOfObj); // ===>resValueOfObj { a: 1, b: 2 }

修改 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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值