kangduu / front-end-camps

Front-end learning, interviews, question banks, algorithm camps.
https://kangduu.github.io/front-end-camps
MIT License
2 stars 0 forks source link

Q:如何修改闭包中的对象? #22

Open kangduu opened 1 year ago

kangduu commented 1 year ago

你是否认为第三方库的代码是不可更改的?你是否认为闭包可以保护内部对象的完整性?

let data = (function () {
  let source = {
    a: 10,
    b: 99,
  };

  return {
    get: function (key) {
        return source[key];
    },
  };
})(); 

请问,在不修改上面代码的情况下,如何修改source对象?

kangduu commented 1 year ago

为什么 valueOf 无法获取 source ?

首先,我们获取data的valueOf值

data.get('valueOf') // [Function: valueOf]

可以看到是一个函数,对吧,好的直接执行啦?

data.get('valueOf')()

image

咦?为什么不行啦?

因为 ‘data.get('valueOf')()’ 等同于下面操作

const vo = Object.prototype.valueOf;
vo();

所以,根本原因是this指向问题。

kangduu commented 1 year ago

正解:属性访问器

我们知道,访问一个属性时,是可以通过属性访问器返回的。getter

好的,下面我们使用defineProperty在现有对象上定义 getter

// 在data的原型上添加一个 _get 方法
Object.defineProperty(data.__proto__, '_get', {
  // 将这个属性变为一个访问器
  // 之后读取这个属性,就会执行get这个函数
  get() {
    // 直接返回this
    return this;
  },
});

console.log(data.get('_get'));

image

完美,成功获取到闭包中的对象了。

const source = data.get('_get');

source.b = 100;
console.log(data.get('b')); // 100

source.b = 10;
console.log(data.get('b')); //10
kangduu commented 1 year ago

如何预防?

sowelly commented 8 months ago

https://www.bilibili.com/video/BV136421V7vQ/?spm_id_from=333.1007.tianma.3-1-7.click&vd_source=7a885242570772230601e857841dee14