要求:
1. 私有变量无法被直接读写,只能通过 `getter/setter` 进行读写。
2. 不能使用任何三方工具
const People = (function() {
// 此处编写你的代码
})();
// 测试用例
const p1 = new People('Lily');
const p2 = new People('Lucy');
const p1 = new People('Lily');
const p2 = new People('Lucy');
console.log(p1.name === undefined);
console.log(p1.getName() === 'Lily');
console.log(p2.name === undefined);
console.log(p2.getName() === 'Lucy');
p1.setName('Tom')
console.log(p1.getName()==='Tom');
题目本身不长,也很好理解,js并没有对变量进行权限的控制,任何人都可以修改class内部变量,如果要封装一个class,并且可以set、get,要如何操作呢?
说到封装,那么就自然而然想到了闭包,看下面一段代码:
const People = (function() {
// 此处编写你的代码
let _name = '';
let Person = function (name) {
_name = name;
};
Person.prototype.getName = function () {
return _name;
};
Person.prototype.setName = function (newName) {
_name = newName;
}
return Person;
})();
const p1 = new People('Lily');
const p2 = new People('Lucy');
console.log(p1.name === undefined);//true
console.log(p1.getName() === 'Lily');//false
console.log(p2.name === undefined);//true
console.log(p2.getName() === 'Lucy');//true
p1.setName('Tom');
console.log(p1.getName()==='Tom');//true
此处,p1.getName()===‘Lily’为false,输出查看后发现p1的name变为Lucy了,查看代码后,发现p1、p2共享了一个闭包内的变量_name。
修改为:
const People = (function () {
// 此处编写你的代码
let Person = function (name) {
let _name = name;
this.getName = function () {
return _name;
};
this.setName = function (newName) {
_name = newName;
}
};
return Person;
})();
就输出5个true了。
我又有了一个新的疑问:new出来的,怎么就是个对象了?
查看红宝书,书中说new操作有4个步骤:
- 创建一个新对象
- 将构造函数的作用域赋给新对象
- 执行构造函数中的代码
- 返回新对象
尝试修改代码模拟上面的过程:
let People = function (name) {
let people_name = name;
let obj = {};
// obj.__proto__ = People.prototype;
obj.getName = function () {
return people_name;
};
obj.setName = function (newName) {
people_name = newName;
}
return obj;
};
const p1 = new People('Lily');
p1 instanceof People;//false
此时p1具有getName()、setName()的方法,但并不是People的实例(废话,原型链中没有People.prototype怎么能是People的实例呢?)
将上面代码注释部分取消注释,输出
p1 instanceof People;//true