Javascript模块中的变量在它外面可见?

时间:2016-07-25 19:08:33

标签: javascript module scope global-variables static-classes

首先,我来自.NET世界,那里有静态类(C#,也称为VB中的模块)和实例类 - 可以实例化的那些。

这个问题是关于Javascript的,我试图重新创建我已经知道的模式并制作模块/静态类。这是代码:

<SolidColorBrush x:Key="Expander.MouseOver.Circle.Stroke" Color="#FF3C7FB1"/>
            <SolidColorBrush x:Key="Expander.MouseOver.Circle.Fill" Color="Transparent"/>
            <SolidColorBrush x:Key="Expander.MouseOver.Arrow.Stroke" Color="#222"/>
            <SolidColorBrush x:Key="Expander.Pressed.Circle.Stroke" Color="#FF526C7B"/>
            <SolidColorBrush x:Key="Expander.Pressed.Circle.Fill" Color="Transparent"/>
            <SolidColorBrush x:Key="Expander.Pressed.Arrow.Stroke" Color="#FF003366"/>
            <SolidColorBrush x:Key="Expander.Disabled.Circle.Stroke" Color="DarkGray"/>
            <SolidColorBrush x:Key="Expander.Disabled.Circle.Fill" Color="Transparent"/>
            <SolidColorBrush x:Key="Expander.Disabled.Arrow.Stroke" Color="#666"/>
            <SolidColorBrush x:Key="Expander.Static.Circle.Fill" Color="Transparent"/>
            <SolidColorBrush x:Key="Expander.Static.Circle.Stroke" Color="DarkGray"/>
            <SolidColorBrush x:Key="Expander.Static.Arrow.Stroke" Color="#666"/>
            <Style x:Key="ExpanderRightHeaderStyle" TargetType="{x:Type ToggleButton}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ToggleButton}">
                            <Border Padding="{TemplateBinding Padding}">
                                <Grid Background="Transparent" SnapsToDevicePixels="False">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="19"/>
                                        <RowDefinition Height="*"/>
                                    </Grid.RowDefinitions>
                                    <Grid>
                                        <Grid.LayoutTransform>
                                            <TransformGroup>
                                                <TransformGroup.Children>
                                                    <TransformCollection>
                                                        <RotateTransform Angle="-90"/>
                                                    </TransformCollection>
                                                </TransformGroup.Children>
                                            </TransformGroup>
                                        </Grid.LayoutTransform>
                                        <Ellipse x:Name="circle" Fill="{StaticResource Expander.Static.Circle.Fill}" HorizontalAlignment="Center" Height="19" Stroke="{StaticResource Expander.Static.Circle.Stroke}" VerticalAlignment="Center" Width="19"/>
                                        <Path x:Name="arrow" Data="M 1,1.5 L 4.5,5 L 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="false" Stroke="{StaticResource Expander.Static.Arrow.Stroke}" StrokeThickness="2" VerticalAlignment="Center"/>
                                    </Grid>
                                    <ContentPresenter HorizontalAlignment="Center" Margin="0,4,0,0" Grid.Row="1" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Top"/>
                                </Grid>
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsChecked" Value="true">
                                    <Setter Property="Data" TargetName="arrow" Value="M 1,4.5  L 4.5,1  L 8,4.5"/>
                                </Trigger>
                                <Trigger Property="IsMouseOver" Value="true">
                                    <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Stroke}"/>
                                    <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Fill}"/>
                                    <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.MouseOver.Arrow.Stroke}"/>
                                </Trigger>
                                <Trigger Property="IsPressed" Value="true">
                                    <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Stroke}"/>
                                    <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
                                    <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Fill}"/>
                                    <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Pressed.Arrow.Stroke}"/>
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="false">
                                    <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Stroke}"/>
                                    <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Fill}"/>
                                    <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Disabled.Arrow.Stroke}"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            <Style x:Key="ExpanderUpHeaderStyle" TargetType="{x:Type ToggleButton}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ToggleButton}">
                            <Border Padding="{TemplateBinding Padding}">
                                <Grid Background="Transparent" SnapsToDevicePixels="False">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="19"/>
                                        <ColumnDefinition Width="*"/>
                                    </Grid.ColumnDefinitions>
                                    <Grid>
                                        <Grid.LayoutTransform>
                                            <TransformGroup>
                                                <TransformGroup.Children>
                                                    <TransformCollection>
                                                        <RotateTransform Angle="180"/>
                                                    </TransformCollection>
                                                </TransformGroup.Children>
                                            </TransformGroup>
                                        </Grid.LayoutTransform>
                                        <Ellipse x:Name="circle" Fill="{StaticResource Expander.Static.Circle.Fill}" HorizontalAlignment="Center" Height="19" Stroke="{StaticResource Expander.Static.Circle.Stroke}" VerticalAlignment="Center" Width="19"/>
                                        <Path x:Name="arrow" Data="M 1,1.5 L 4.5,5 L 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="false" Stroke="{StaticResource Expander.Static.Arrow.Stroke}" StrokeThickness="2" VerticalAlignment="Center"/>
                                    </Grid>
                                    <ContentPresenter Grid.Column="1" HorizontalAlignment="Left" Margin="4,0,0,0" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Center"/>
                                </Grid>
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsChecked" Value="true">
                                    <Setter Property="Data" TargetName="arrow" Value="M 1,4.5  L 4.5,1  L 8,4.5"/>
                                </Trigger>
                                <Trigger Property="IsMouseOver" Value="true">
                                    <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Stroke}"/>
                                    <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Fill}"/>
                                    <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.MouseOver.Arrow.Stroke}"/>
                                </Trigger>
                                <Trigger Property="IsPressed" Value="true">
                                    <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Stroke}"/>
                                    <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
                                    <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Fill}"/>
                                    <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Pressed.Arrow.Stroke}"/>
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="false">
                                    <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Stroke}"/>
                                    <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Fill}"/>
                                    <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Disabled.Arrow.Stroke}"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            <Style x:Key="ExpanderLeftHeaderStyle" TargetType="{x:Type ToggleButton}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ToggleButton}">
                            <Border Padding="{TemplateBinding Padding}">
                                <Grid Background="Transparent" SnapsToDevicePixels="False">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="19"/>
                                        <RowDefinition Height="*"/>
                                    </Grid.RowDefinitions>
                                    <Grid>
                                        <Grid.LayoutTransform>
                                            <TransformGroup>
                                                <TransformGroup.Children>
                                                    <TransformCollection>
                                                        <RotateTransform Angle="90"/>
                                                    </TransformCollection>
                                                </TransformGroup.Children>
                                            </TransformGroup>
                                        </Grid.LayoutTransform>
                                        <Ellipse x:Name="circle" Fill="{StaticResource Expander.Static.Circle.Fill}" HorizontalAlignment="Center" Height="19" Stroke="{StaticResource Expander.Static.Circle.Stroke}" VerticalAlignment="Center" Width="19"/>
                                        <Path x:Name="arrow" Data="M 1,1.5 L 4.5,5 L 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="false" Stroke="{StaticResource Expander.Static.Arrow.Stroke}" StrokeThickness="2" VerticalAlignment="Center"/>
                                    </Grid>
                                    <ContentPresenter HorizontalAlignment="Center" Margin="0,4,0,0" Grid.Row="1" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Top"/>
                                </Grid>
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsChecked" Value="true">
                                    <Setter Property="Data" TargetName="arrow" Value="M 1,4.5  L 4.5,1  L 8,4.5"/>
                                </Trigger>
                                <Trigger Property="IsMouseOver" Value="true">
                                    <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Stroke}"/>
                                    <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Fill}"/>
                                    <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.MouseOver.Arrow.Stroke}"/>
                                </Trigger>
                                <Trigger Property="IsPressed" Value="true">
                                    <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Stroke}"/>
                                    <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
                                    <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Fill}"/>
                                    <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Pressed.Arrow.Stroke}"/>
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="false">
                                    <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Stroke}"/>
                                    <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Fill}"/>
                                    <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Disabled.Arrow.Stroke}"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            <Style x:Key="ExpanderHeaderFocusVisual">
                <Setter Property="Control.Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <Border>
                                <Rectangle Margin="0" SnapsToDevicePixels="true" Stroke="Black" StrokeThickness="1" StrokeDashArray="1 2"/>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            <Style x:Key="ExpanderDownHeaderStyle" TargetType="{x:Type ToggleButton}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ToggleButton}">
                            <Border Padding="{TemplateBinding Padding}">
                                <Grid Background="Transparent" SnapsToDevicePixels="False">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="19"/>
                                        <ColumnDefinition Width="*"/>
                                    </Grid.ColumnDefinitions>
                                    <Ellipse x:Name="circle" Fill="{StaticResource Expander.Static.Circle.Fill}" HorizontalAlignment="Center" Height="19" Stroke="{StaticResource Expander.Static.Circle.Stroke}" VerticalAlignment="Center" Width="19"/>
                                    <Path x:Name="arrow" Data="M 1,1.5 L 4.5,5 L 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="false" Stroke="{StaticResource Expander.Static.Arrow.Stroke}" StrokeThickness="2" VerticalAlignment="Center"/>
                                    <ContentPresenter Grid.Column="1" HorizontalAlignment="Left" Margin="4,0,0,0" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Center"/>
                                </Grid>
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsChecked" Value="true">
                                    <Setter Property="Data" TargetName="arrow" Value="M 1,4.5  L 4.5,1  L 8,4.5"/>
                                </Trigger>
                                <Trigger Property="IsMouseOver" Value="true">
                                    <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Stroke}"/>
                                    <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Fill}"/>
                                    <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.MouseOver.Arrow.Stroke}"/>
                                </Trigger>
                                <Trigger Property="IsPressed" Value="true">
                                    <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Stroke}"/>
                                    <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
                                    <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Fill}"/>
                                    <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Pressed.Arrow.Stroke}"/>
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="false">
                                    <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Stroke}"/>
                                    <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Fill}"/>
                                    <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Disabled.Arrow.Stroke}"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            <Style x:Key="MatchExpanderStyle" TargetType="{x:Type Expander}">
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
                <Setter Property="Background" Value="Transparent"/>
                <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                <Setter Property="VerticalContentAlignment" Value="Stretch"/>
                <Setter Property="BorderBrush" Value="Transparent"/>
                <Setter Property="BorderThickness" Value="1"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type Expander}">
                            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="3" SnapsToDevicePixels="true">
                                <DockPanel>
                                    <ToggleButton x:Name="HeaderSite" Visibility="Hidden" ContentTemplate="{TemplateBinding HeaderTemplate}" ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}" Content="{TemplateBinding Header}" DockPanel.Dock="Top" Foreground="{TemplateBinding Foreground}" FontWeight="{TemplateBinding FontWeight}" FocusVisualStyle="{StaticResource ExpanderHeaderFocusVisual}" FontStyle="{TemplateBinding FontStyle}" FontStretch="{TemplateBinding FontStretch}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" MinWidth="0" MinHeight="0" Padding="{TemplateBinding Padding}"  VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                    <ContentPresenter x:Name="ExpandSite" DockPanel.Dock="Bottom" Focusable="false" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" Visibility="Collapsed" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                </DockPanel>
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsExpanded" Value="true">
                                    <Setter Property="Visibility" TargetName="ExpandSite" Value="Visible"/>
                                </Trigger>
                                <Trigger Property="ExpandDirection" Value="Right">
                                    <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Right"/>
                                    <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Left"/>
                                    <Setter Property="Style" TargetName="HeaderSite" Value="{StaticResource ExpanderRightHeaderStyle}"/>
                                </Trigger>
                                <Trigger Property="ExpandDirection" Value="Up">
                                    <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Top"/>
                                    <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Bottom"/>
                                    <Setter Property="Style" TargetName="HeaderSite" Value="{StaticResource ExpanderUpHeaderStyle}"/>
                                </Trigger>
                                <Trigger Property="ExpandDirection" Value="Left">
                                    <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Left"/>
                                    <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Right"/>
                                    <Setter Property="Style" TargetName="HeaderSite" Value="{StaticResource ExpanderLeftHeaderStyle}"/>
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="false">
                                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

请解释为什么命名空间内声明的方法不可见,但变量是什么?另外,有没有办法阻止这些变量在var MyModule = { variable1: 0, variable2: 1, method1: function() { //code goes here }, method2: function() { //mode code goes here }, method3: function() { //and some more just to prove the pattern } } method1(); //error - no such method - ok, good, I expect that variable1 = 5; //silently assigns a variable inside MyModule to 5 ? 之外可见,即使在同一个脚本中也是如此?

2 个答案:

答案 0 :(得分:7)

我将首先尝试解决一些误解 - 您的模块实际上是使用文字初始化的plain JavaScript object。对象不会隐藏任何信息 - JavaScript没有privatepublic范围,就像Java一样。此外,访问对象属性的唯一方法是通过它访问它们

method1();

这会失败,因为您正在尝试获取名为method1的变量并执行它。这不存在,因此错误。但 可以做的是MyModule.method1()。这是因为MyModule是一个实际的对象。在Java中,这与Object MyModule = new Object()类似。因此,您可以在其上调用方法,例如MyModule.toString() - 唯一的&#34;非传统的&#34;事实上,实例是用大写字母命名的 - Java和JavaScript中的变量通常以小写字母开头,但只能按惯例开头 - 没有任何语言功能可以强制执行。

接下来,有这一行:

variable1 = 5; //silently assigns a variable inside MyModule to 5 ?

要回答该行的评论 - 不,它没有。上述行等同于执行window.variable1 = 5。你在那里所拥有的被称为&#34;隐含的全球&#34;。这个名称是相当自我描述性的,但只是为了澄清window.foo = 42是一个明确的全局foo = 42 暗示,因为它回退到window对象。但是,var foo = 42 是全局的 - var关键字不会附加或使用全局window对象。如果使用"use strict"指令,则会导致JavaScript引擎在遇到隐含的全局时抛出错误。

现在,除了这些误解之外,还有另一个小问题,我只会掩饰它,但它实际上是一件大事 - MyModule.method1依旧是函数而不是比方法。方法是用于子例程的面向对象的术语,该子例程还带有隐含状态,该隐含状态是它被分配给的对象。但是,函数是一个自由浮动的可执行代码,它本身并不属于#34;到一个对象。这种区别似乎相当具有学术性,但它具有很大的影响。但是,我会请求您相信我,因为这里涉及的主题太广泛了。

那么,这是错误的。我们如何使它正确?首先,关于范围,其余部分需要:

JavaScript有两个范围 - 全局和功能。这就是这意味着:

var foo = 42;

function bar(input) {
    var foo = input;
    return foo;
}

console.log(bar(5)); //5
console.log(foo); //42

我们也有一些名为foo的变量 - 一个不在函数内。分配一个不会改变另一个 - 它是因为它们在不同的范围内。这要归功于var关键字 - 如果在函数内省略了,那么我们将访问相同的东西

var foo = 42;

function bar(input) {
    foo = input;
    return foo;
}

console.log(bar(5)); //5
console.log(foo); //5

这是因为内部foo未声明在功能范围内,因此它访问外部(并且没有外部 - window.foo属性)。

这很简单。但是,这里有一个隐藏的方面并不是很明显,但值得一提的是:只有两个范围。这就是我的意思

function bar(condition) {
    var foo = 5;
    if (condition) {
        var foo = 42;
    }
    return foo;
}

console.log( bar(false) ); //5
console.log( bar(true) ); //42

所以,即使我们似乎在if语句中声明了一个新的foo属性,它实际上与第一个属性相同。其他语言在{ }内有一个块范围,所以在那里声明的变量就在那里。在JavaScript中不正确。容易错过,所以需要注意。

现在,解决你的问题。有关JavaScript模块模式的优秀资源,仅举几例:Addy Osmani's "Learning JavaScript Design Patterns" book有一个非常好的描述,Todd Motto也有,我相信,这是一篇适合初学者的好文章{{3}更深入,但它仍然可以访问。它们都涵盖了模块模式。实际上,您将在这些资源和Web上找到许多模块模式。该模块允许您执行的操作与其他语言的publicprivate类似。我不会试图解释它,因为我认为其他人已经做得比我更好。但是,我将简要解释一下模块是什么。同样,其他资源可以更好地涵盖这一点。

模块利用名为Closure的JavaScript功能更多信息the Adequately Good posthere(最受欢迎的StackOverflow问题之一)。还记得我说过,JavaScript中有两个范围吗?简单地说,一个闭包提供了一个功能范围。这是它的样子:

 (function() { /* your code goes here */ })()

要简要剖析一下,您的代码函数将包含在(/* function goes here */)()中。实际上,这样做是执行函数所以内部的所有内容都被放入功能范围。然而,这是非常强大的,这是一个例子

var closure = (function() { 
    var privateVar = "secret";
    return {
       publicVar: 42,
       getPrivateVar() { return privateVar; }
    }
})()

console.log(closure.publicVar); //42
console.log(closure.getPrivateVar()); //"secret"
//let's change this
closure.publicVar = 5;
closure.privateVar = "changed";

console.log(closure.publicVar); //5
console.log(closure.getPrivateVar()); //"secret"

就像我们拥有(类似的东西)私人领域一样。同样,var privateVar将保持&#34;装瓶&#34;在功能范围内,不能在外面访问。顺便提一下,这是模块模式的一个例子。而不是var closure我可以称之为myModule。这是一个相当简单的看法,但是,事情就是这样 - 它并没有变得更复杂。所有不同的模块归结为非常相似的东西 - 您只是以不同的方式公开数据。然而,这个概念是相似的 - &#34;私人&#34;田野留在里面,&#34;公共&#34;那些,你可以从其他地方访问。

这很长,但希望能涵盖你需要的基础知识。

答案 1 :(得分:0)

在向Stack Overflow询问问题之前,I created a JSFiddle附上问题,之后的几个步骤确定了问题所在。这实际上经常发生。但这次我想与公众分享我的发现。 JS大师可能已经知道这一点,而一些经验不足的开发人员可能会发现这些信息很有帮助。

I had two instances of variable MyModule,一个属于variable1,另一个属于MyModule(全局范围)。当我将鼠标悬停在window调试器中时,即使它位于variable1内,调试器也会显示全局值。看起来像Visual Studio 2015中的一个错误,但这是它的工作原理。然后我在MyModule的一个函数中放了一个断点,并注意到如果一个变量以MyModule为前缀,它会显示一个不同的值。显然,JS语法不允许在声明this期间放置this,所以只需要了解JS调试器在Visual Studio中的工作方式。

如果我的解释没有意义,请尝试将鼠标悬停在C#项目内任何类定义顶部的变量上。在调试过程中的任何时候,无论谁声明了什么,您都会在那里看到最新和正确的值。 IDE行为的不同之处在于给我带来了困惑。另外,如果你对变量声明不够谨慎,那么Javascript就有创建全局变量的倾向。