闭包——破坏第三方库

闭包

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

你可能感兴趣的:(javascript,前端,typescript)