JavaScript中的类和创建它们的模式

分享于 

7分钟阅读

Web开发

  繁體 雙語

介绍

本文将讨论如何在 JavaScript 中模拟 class 结构,以便将相关的状态和行为封装为模块/类。

Background

在创建JavaScript类之前,我们需要知道什么是闭包以及它们如何在创建类时进行救援。

一个关于闭包的名言- ".. ... Nested functions have access to vars and parameters of parent function event after parent function is executed/returned" ,现在的意思是:

让我们看看一个例子。 如果函数返回milliseconds毫秒,在调用相同函数时,输出会与以前的函数不同,因此,输出不会在两个调用中保留,因此状态不会保持在2 毫秒。

非关闭演示

function time(){
 var timeNow = new Date();
 return timeNow.getMilliseconds();
};

现在,当你按如下方式调用 上面 函数两次时:

alert(time());
setTimeout(function(){
 alert(time());
},220);

它会提醒不同的毫秒,因为每次调用函数新的Date() 对象时都会实例化并给出不同的毫秒。 如何解决这个问题? 这里是闭包。

当函数返回parent函数时,嵌套函数仍然可以访问父函数,因为当你第一次调用函数时,嵌套函数仍然可以访问父函数,该函数将存储存储在持久函数中的状态。

关闭演示

function timeClosure(){
 var timeNow = new Date();
 returnfunction(){
 return timeNow.getMilliseconds();
 }
};

现在调用 timeClosure() 并将它的赋给变量时,timeClosure函数返回一个嵌套函数,该函数可以访问保存的timeNow变量。 因此,当你使用指定变量两次时,延迟也会得到相同的毫秒,返回嵌套函数的访问时间,nested函数,因此,我们将得到相同的毫秒数,因此我们将两次使用相同的milliseconds对象"。

现在,当调用 上面 函数两次时,延迟如下:

var nestedFunc = timeClosure(); //This will return the nested func.alert(nestedFunc());
setTimeout(function(){
 alert(nestedFunc());
},220);

两者都将弹出与解释的上面 相同的毫秒。 现在这个类似于结构不是真的,因为状态是持久的,但是你不能将它的新的结构实例。 所以这里的模式。

在本文中,我们将讨论两种模式:

  • Revealing module pattern
  • Revealing prototype pattern

显示模块模块:

在这个 Pattern 中,我们encapusalate字段和成员 inside 返回一个函数,并返回一个对象文本来公开这些成员。 这里的对象文字的返回在成员周围创建一个闭包。

让我们看一个pratical示例来获取上下文:

function Circle(radius){
 var radius=radius;
 var pi=Math.PI;
 var area=function(){
 return pi*(Math.pow(radius,2));
 };
 return{
 area:area
 }
}

现在是类模拟,现在你可以按如下所示 instansiate 上面 类:

var circle1 = new Circle(10);
alert(circle1.area());

这将弹出圆形的圆,半径 10 i。e。314.1592653589793

这个 Pattern 有一个,我们创建的内部方法将复制到每个与 C# 或者Java世界有点不同的实例中。 为了拯救它,我们将展示Prototype模式,其中使用了显示模块 Pattern 特性和Prototype特征。

显示Prototype的收费:

在这个模块中我们有两个部分

  • 构造函数部分。
  • Prototype部分。

你在构造函数和 private 字段中指定了所有的public 字段和Prototype部分中的方法。

让我们看一个pratical示例来获取上下文:

function Circle(radius){
 this.radius=radius;
}
Circle.prototype=function(){var pi = Math.PI;var area = function(){
 return pi*(Math.pow(this.radius,2));
};return {
 area:area
}
}();

现在,你可以按如下方式实例化和访问圆的面积:

var circle1 = new Circle(10);
alert(circle1.area());

这将弹出半径 10的圆区域,半径与 上面: ) 相同。

我们已经创建了一个构造函数和 Prototype,Prototype允许你在所有实例中共享方法,而不是对类的每个实例拥有单独的副本。 我们已经使用self匿名函数添加了 propType Pattern,使它的具备 encapusulate private 字段的能力,并且只公开了 public 方法。 所以Prototype模式中的返回和成员在你的类中创建了闭包。

这个 Pattern 有一个 of,它使用 "this" 关键字,因为这种变化的上下文相当有用。

让我们看一个实际示例,并解决这个问题,以解决这个问题:

Problem:

function Triangle(a,b,c){
 this.a=a;
 this.b=b;
 this.c=c;
}
Triangle.prototype=function(){var perimeter=function(){
 returnthis.a+this.b+this.c; //This here has different context so this won't work}var area = function(){
 var s=(perimeter())/2;
 return Math.sqrt(s*(s-this.a)*(s-this.b)*(s-this.c));
};return {
 area:area
}
}();var triangle1=new Triangle(10,10,10);
alert(triangle1.area());
}

因为在区域方法调用周长函数,所以这里更改将发生更改,所以区域没有a,所以区域中的区域没有b。b,perimeter函数中的This。 因此,围绕着perimter函数传递它并使用它。

Solution:

function Triangle(a,b,c){
 this.a=a;
 this.b=b;
 this.c=c;
}
Triangle.prototype=function(){var perimeter=function(thisob){
 return thisob.a+thisob.b+thisob.c; //this will work as this here is the Triangle inst}var area = function(){
 var s=(perimeter(this))/2; //passing this to perimeterreturn Math.sqrt(s*(s-this.a)*(s-this.b)*(s-this.c));
};return {
 area:area
}
}();var triangle1=new Triangle(10,10,10);
alert(triangle1.area());
}

这将弹出三角形 IE 三边的三角形区域。 43.30127018922193

感谢你阅读:)


相关文章