1、闭包基本实现
/**
* 让外部方法使用内部局部变量,防止全局变量被污染;
* 但仅限于使用,不建议对局部变量进行修改
*/
const obj = function() {
let o = {
name: "zhangsan",
age: "18"
}
return function (key) {
return o[key];
}
} ()
console.log(obj("age")); // 18
2、问题简述
上述方式并不能完全实现闭包,可以通过原型链拿取对象信息并加以修改
// 在原型上添加方法,获取当前对象,并能修改对象内部name属性的值
Object.defineProperty(Object.prototype,'getAll', {
// 访问该属性时,将不带参地调用此函数,**并将 this 设置为通过该属性访问的对象**
get() {
return this;
},
// 当该属性被赋值时,将调用此函数,并带有一个参数(要赋给该属性的值)
// **并将 this 设置为通过该属性分配的对象**
set(value) {
this["name"] = value;
}
})
// 获取对象信息
console.log(obj("getAll")); // { name: 'zhangsan', age: '18' }
// 修改对象内容
obj("getAll").getAll = "lisi";
console.log(obj("getAll")); // { name: 'lisi', age: '18' }
3、优化
3.1 空原型链
const obj = function() {
// 指定原型链为null(参数只能为 null 或 Object)
let o = Object.create(null);
o.name = "zhangsan",
o.age = "18";
return function (key) {
return o[key];
}
} ()
// 验证原型链
Object.defineProperty(Object.prototype,'getAll', {
get() {
return this;
}
})
console.log(obj("getAll")); // undefined
3.2 断开原型链(原有Object链上的方法无法使用-不建议
const obj = function() {
let o = {
name: "zhangsan",
age: "18"
}
o.prototype = null;
return function (key) {
return o[key];
}
} ()
3.3 限定key范围
const obj = function() {
let o = {
name: "zhangsan",
age: "18"
}
return function (key) {
// 判断是否是对象自有属性,非继承属性;可用 Object.hasOwn(对象名,属性名) 代替
if(o.hasOwnProperty(key)) {
return o[key];
}
throw new Error("key is not exist!")
}
} ()
// 验证原型链
Object.defineProperty(Object.prototype,'getAll', {
get() {
return this;
},
})
console.log(obj("getAll")); // Error: key is not exist!
PS. Object.hasOwn()
旨在取代 Object.prototype.hasOwnProperty()
。