闭包
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