美文网首页
2020-05-18 5 kyu Using closures

2020-05-18 5 kyu Using closures

作者: 苦庭 | 来源:发表于2020-05-18 22:26 被阅读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;
      
    }());
    

    好在哪里?

    • 用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等

    相关文章

      网友评论

          本文标题:2020-05-18 5 kyu Using closures

          本文链接:https://www.haomeiwen.com/subject/ywxmohtx.html