2020-05-18 5 kyu Using closures

2020-05-18  本文已影响0人  苦庭

https://www.codewars.com/kata/53583765d5493bfdf5001b35/javascript

参考:

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;
  
}());

好在哪里?

Recap

这是一道关于闭包、构造器、IIFE(Immediately-invoked Function Expression)、Object.defineProperty()的题

简单来说,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是定义构造器函数的名称。

一个显式定义对象的属性存取的静态方法,有三个参数。

obj:要定义属性的对象
prop: 属性名
descriptor:描述符,是一个对象,用来描述添加/修改的这个属性的getter、setter、value、writable、enumerable、configurable等

上一篇下一篇

猜你喜欢

热点阅读