闭包 - 记录一个漏洞问题

70 阅读1分钟

问题:在不修改下面代码的情况下,如何修改 obj 对象?

var o = (() => {
  var obj = {
    a: 1,
    b: 2,
  };
  return {
    get: (n) => {
      return obj[n];
    },
  };
})();

思路:尝试拿到 obj 对象本身。

方法1:通过 valueOf 方法

Object.prototype.valueOf() 方法返回:转换成对象的 this 值。

var o = (() => {
  var obj = {
    a: 1,
    b: 2,
  };
  return {
    get: (n) => {
      return obj[n];
    },
  };
})();

console.log(o.get("valueOf")());
// Uncaught TypeError: Cannot convert undefined or null to object
// 报错;此时调用 valueOf 的不是 obj,this 指向不是 obj

方法2:通过 Object.defineProperty() 给对象原型添加一个访问器属性

var o = (() => {
  var obj = {
    a: 1,
    b: 2,
  };
  return {
    get: (n) => {
      return obj[n];
    },
  };
})();

Object.defineProperty(Object.prototype, "xxx", {
  get() {
    return this;
  },
});

const obj2 = o.get("xxx");
console.log(obj2); // {a: 1, b: 2}

obj2.a = 100;
console.log(o.get("a")); // 100

解决该漏洞的方法

var o = (() => {
  // 1. 将 obj 对象的原型链切断
	// obj = Object.create(null) 或 Object.setPrototypeOf(obj, null)
  var obj = {
    a: 1,
    b: 2,
  };
  return {
    get: (n) => {
      // return obj[n];
      // 2. 判断是否是该对象自身的属性
      if (obj.hasOwnProperty(n)) {
        return obj[n];
      }
    },
  };
})();