要求:
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