在JavaScript中实现循环构造函数,无需ES6类

在JavaScript中实现循环构造函数,无需ES6类,javascript,ecmascript-6,Javascript,Ecmascript 6,Eric Faust在以下关于ES6类的文章中键入了一个循环构造函数: 我想知道: 他为什么使用defineProperty?我们不能直接在构造函数中实现行为吗。例如:Circle.draw=函数draw(){..} 为什么要使用get/set而不只是在普通属性中使用状态:Circle.circleCount 哪些属性应该通过构造函数中的this直接在新实例对象上实现,而不是通过constructor.prototype上的直接在新实例对象上实现(给定两者如何使属性可用于新实例) Eric的代码

Eric Faust在以下关于ES6类的文章中键入了一个循环构造函数:

我想知道:

  • 他为什么使用
    defineProperty
    ?我们不能直接在构造函数中实现行为吗。例如:
    Circle.draw=函数draw(){..}
  • 为什么要使用
    get
    /
    set
    而不只是在普通属性中使用状态:
    Circle.circleCount
  • 哪些属性应该通过构造函数中的
    this
    直接在新实例对象上实现,而不是通过
    constructor.prototype上的
    直接在新实例对象上实现(给定两者如何使属性可用于新实例)
  • Eric的代码:

    功能圆(半径){
    这个半径=半径;
    Circle.circlesMake++;
    }
    Circle.draw=函数draw(圆,画布){/*画布绘图代码*/}
    Object.defineProperty(圆圈,“圆圈制造”{
    get:function(){
    return!this.\u count?0:this.\u count;
    },
    设置:功能(val){
    这个。_count=val;
    }
    });
    圆圈。原型={
    区域:功能区(){
    返回Math.pow(this.radius,2)*Math.PI;
    }
    };
    Object.defineProperty(Circle.prototype,“radius”{
    get:function(){
    返回这个;
    },
    设置:功能(半径){
    如果(!Number.isInteger(半径))
    抛出新错误(“圆半径必须是整数”);
    这个。_半径=半径;
    }
    });
    设c1=新的圆(10);
    console.log(c1.area());
    
    控制台。日志(圆形。圆形)对于将与实例共享的函数,我更喜欢使用构造函数的原型对象,而不是在每个实例上定义新函数。这可以节省内存,因为对于创建的每个实例,您只有一个函数实例,而不是一个新副本

    您还可以在原型上定义
    circleCount
    ,因为所有实例都需要相同的编号。您只需要稍微小心地更改它,以确保不会在每个实例上创建阴影属性。然后每个实例可以通过原型链直接提供计数

    这样做会使函数复杂化,但会简化其余代码:

    功能圆(_半径){
    this.radius=_radius;
    //创建实例会增加每个人的计数
    Circle.prototype.circleCount++//不是这个.circleCount++,它将在实例上创建一个新属性
    }
    Circle.prototype.draw=函数绘制(圆,画布){
    /*画布绘图代码*/
    };
    Circle.prototype.area=函数(){
    返回Math.pow(this.radius,2)*Math.PI;
    }
    Circle.prototype.circleCount=0
    设c1=新的圆(10);
    控制台日志(c1.循环计数);
    console.log(c1.area());
    设c2=新的圆(20);
    控制台日志(c2.循环计数);
    
    console.log(c2.area())谢谢标记,重新分配内存并切换到原型是有意义的。对问题1有什么想法吗。和2。?他试图捍卫类的创建,但他所写的可以简化为您的代码。最新的编辑谈到了1和2。我认为es6课程可以很好地满足这一要求,而且可能会走这条路线。它将允许您在类声明中设置所有方法,我认为这是非常可读的。您还可以在类上设置getter和setter,以使其生效。但在这一切之下,它仍然归结为函数和原型。是的,但我想让我有点困扰的是,他使用所有复杂的代码来证明类,而事实上根本不需要getter/setter。因此,两者都不是定义属性。这是我们可以在构造函数定义本身中添加原型方法的类的唯一情况(我猜它不会为每个实例重新创建吗?)。这对我来说似乎没有什么好处。他让他的原始代码过于复杂,所以看起来这是一个很大的收获。当然,我认为公平地说,如果你不需要类简化的东西,那么你可以同样轻松地使用函数。如果您确实想要getter/setter、简单的继承、快速的函数声明快捷方式,那么类是非常好的。1)继承不是像设置构造函数的.prototype那样简单吗?2) 您发送的列表基本上是它试图改进的吗?这个示例似乎完全是为了显示ES5的全部残暴,以及ES6
    class
    语法将使同样的事情变得多么简单。当然,在真正的ES5中,人们编写的方式可能会非常不同(简单得多),但与之完全等效的内容(如原始静态属性)不可能在ES6中表示。
    Circle.draw
    是一个静态属性,绝对不应该在构造函数中赋值。同样适用于
    Circle.circleCount
    -您应该在构造函数外部将其初始化为
    0
    ,并在创建InstanceHanks@Bergi时将其递增。正如您所指出的,在构造函数本身内部声明属于构造函数自身属性的属性是一个明显的错误。我们显然不希望每次创建新对象时都重新声明它。对于
    circleCount
    我在那里进行了检查,以避免多次重新声明,但我想最好是在外部进行检查,从而避免任何检查。据我所知,
    在实现良好的ES5基础上增加的唯一改进是1)将所有相关代码放在一个块下的能力,以及2)静态属性继承。是的,还有来自ES5对象文本的getter和setter的
    get
    /
    set
    语法(如果您不想替换原型对象,但要对原型对象进行变异,则需要在之前定义属性