可变范围Javascript

时间:2018-05-10 19:44:02

标签: javascript



var x = true;

if (x == true) {
  console.log(typeof(x));
  let x = false;
};

console.log(x);




很抱歉新编程并收到此错误: 错误:未定义x。

我非常困惑。

3 个答案:

答案 0 :(得分:4)

它看起来不像,但你声明的两个变量是不同的。您的var声明就是其中之一,而let声明则不同。你通过用同一个变量命名它们而感到困惑。

let x严格存在于if区块内。此let x是该块中唯一可以存在的x,您在尝试x时声明它之前尝试使用console.log

在用var声明变量之前,你可以使用变量,但是让const不会让你。

此外,我强烈建议您不要在代码中混用varlet。如果你这样做,你必须真正理解发生了什么。

var x = true; // first x variable

if (x == true){ // first x variable
  console.log(typeof(x)); // second x variable, used before declaration
  let x = false; // second x variable created in `if` block
};

console.log(x); // first x variable

编辑: 您的后续问题仍然是两个不同的变量。你唯一做的就是强制代码让它看起来更像是同一个变量。

var x = true; // first x
if (x == true) { // first x
    let x = false; // second x
    console.log(x); // second x, false
};
console.log(x) // first x, true

答案 1 :(得分:1)

这个解释有点棘手,但我会试试;

var x = true;

if (x == true) {
  console.log(typeof(x)); // <-- Error: x is not defined.
  let x = false;
};

console.log(x); // true

最后一行实际上很好,因为你在前面定义了x

if声明中发生的事情是,JavaScript向前看并看到您已在该范围内的某处声明xletconst),但它尚未到达那条线。

因此仅仅在同一范围内的某个地方letconst只会导致该变量无法定义。

如果你把它向上移动,一切都很好:

var x = true;

if (x == true) {
  let x = false;
  console.log(x); // false
};

console.log(x); // true

如果您不重新声明x,那也没关系:

var x = true;

if (x == true) {
  let y = false; // different variable name (won't "shadow" the `x` from above)
  console.log(x,y); // true false
};

console.log(x); // true

var表现不同:

if (true) {
  console.log(y); // undefined
  var y = false; // `var` is less strict. The declaration of `y` is hoisted to the top of the scope, but it's not assigned until this line
  console.log(y); // false
};

答案 2 :(得分:-1)

每个人都缺少的解释部分是声明是hoisted,这意味着宣言被带到了开头。

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myfirstapp"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name="com.example.myfirstapp.MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="com.example.myfirstapp.DisplayMessageActivity" android:parentActivityName="com.example.myfirstapp.MainActivity"> <!--The meta-data tag is required if you support API level 15 and lower --> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.example.myfirstapp.MainActivity"/> </activity> </application> </manifest> 尤其如此。对于<?xml version="1.0" encoding="utf-8"?> <resources> <!--<color name="colorPrimary">#087609</color> <color name="colorPrimaryDark">#002900</color> <color name="colorAccent">#327f4f</color>--> </resources> 来说,事情有点不同,而且提升一词并不是最准确的。但了解正在发生的事情很有用。

执行时,您的代码将看起来像这样(不完全但是提出了想法)

<resources>

    <!-- Base application theme. -->

    <style name="AppTheme" parent="Theme.AppCompat">
        <!-- Customize your theme here. -->

        <!--<item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        -->
    </style>

</resources>

现在一切都应该有意义:var是指letvar x = true; if (x == true) { let x // hoisted at top of scope, for let scope is this if block console.log(typeof(x)); x = false; }; console.log(x); 一起声明但尚未初始化。

为了更清楚,这就是typeof(x)x引用下面一行中声明的let而不是开头的x的原因:因为声明了该块内部的x存在于此块的开头