2020-05-18 5 kyu Using closures
2020-05-18 本文已影响0人
苦庭
https://www.codewars.com/kata/53583765d5493bfdf5001b35/javascript
参考:
- 如何用IIFE正确构造一个包含私有变量的类
-
闭包、IIFE和私有变量
*IIFE:Immediately-invoked Function Expressions,即时调用的函数表达式
My answer / AC
var Cat = (function (name, weight) {
var totalCount = 0;
var mapping = {};
function Cat(name, weight) {
var avg;
Object.defineProperty(Cat, "averageWeight", {value:function(){
return (Object.values(mapping).length?Object.values(mapping).reduce((a,b)=>a+b):0)/totalCount;
}, writable:true})
if(!name || !weight) throw Error;
Object.defineProperty(this, "weight", {
get: function(){
return mapping[name];
},
set: function(w){
mapping[name] = w;
}
})
mapping[name] = weight;
++totalCount;
}
return Cat;
}());
基本做对了,一开始用的数组也没错,后来采用了对象mapping更好地处理名字相同的Cat
Best answer
// Let's make a Cat constructor!
var Cat = (function () {
var cats = {
count: 0,
totalWeight: 0,
avgWeight: 0
}
function Cat (name, weight) {
if (!name || !weight) {
throw new Error('Both `name` and `weight` should be provided');
}
cats.count++;
this.name = name;
Object.defineProperty(this, 'weight', {
get: function () {
return this._weight || 0;
},
set: function (val) {
cats.totalWeight = cats.totalWeight - this.weight + val;
cats.avgWeight = cats.totalWeight / cats.count;
return this._weight = val;
}
});
this._weight = weight;
}
Cat.averageWeight = function () {
return cats.avgWeight;
}
return Cat;
}());
好在哪里?
- 用cats对象来存取和多个猫相关的变量,显得条理清晰。
-
_weight
被用来表示私有的weight,前面的下划线表示私有 -
Cat.averageWeight()
并不需要用Object.defineProperty()
来定义,直接写就行。
Recap
这是一道关于闭包、构造器、IIFE(Immediately-invoked Function Expression)、Object.defineProperty()的题
-
掌握了关于闭包和IIFE的使用
简单来说,IIFE就是在js函数的定义后面直接加上小括号,当场调用。
//通常写法
(function(){
alert("Hi");
}()) //最末一对小括号表示当场调用
/* 最外面必须套上小括号,否则将会导致“函数定义”的语法错误 */
//不加小括号的写法
void function() {
alert("Hello from IIFE!");
}(); //最末一对小括号表示当场调用
以上void(或者换成~、!、-、+)的使用和~!-+这四个算术运算符做的事情都是一样的,就是让function变成一个表达式而不是函数声明/定义。
-
掌握了构造器的写法
var Class = (function ClassModule() {
var counter = 0;
function Class() {}
Class.prototype = {
count: function() {
return counter++;
}
};
return Class;
}());
var class1 = new Class();
var class2 = new Class();
console.log(class1.count()); //=> 0
console.log(class2.count()); //=> 1
注:Class里面还能有Class,外面的Class负责存储整个表达式原地调用所返回出来的结果,里面的Class是定义构造器函数的名称。
-
Object.defineProperty(obj, prop, descriptor)
一个显式定义对象的属性存取的静态方法,有三个参数。
obj:要定义属性的对象
prop: 属性名
descriptor:描述符,是一个对象,用来描述添加/修改的这个属性的getter、setter、value、writable、enumerable、configurable等