Swift吊装?
Swift Hoisting?
众所周知,JavaScript "Hoists" 将变量放在文件或作用域的顶部。但是根据我的理解,使用 let
与 var
相同,只是 let
被限制在它定义的范围内。
作为编译语言而不是解释语言,我们可以假设 Swift 不会这样做吗?
例如:
x = 10
var y = x + 10
var x
'let' 和 'var' 在范围上没有区别。
Global variables are variables that are defined outside of any
function, method, closure, or type context. Local variables are
variables that are defined within a function, method, or closure
context.
can we assume Swift does NOT do this?
你可以假设任何你想要的,但无论编程语言如何,你绝对最好的选择是尝试一下并找出答案。如果您将示例代码粘贴到 Playground 或任何支持 Swift 的 IDE 中,或者只是通过命令行尝试 运行 它,您很快就会发现这很简单不起作用。
你的问题有点令人困惑,但我想我可以解决你所有或至少大部分的问题。
x = 10
var y = x + 10
var x
假设您的原始示例没有其他代码,它根本无法编译。三行都有问题
前两行抱怨使用了未解析的标识 'x'。在英语中,这意味着 Swift 无法弄清楚你在说什么变量。 Swift 中的变量必须在使用前声明,因此第三行的声明对接下来的两行没有帮助。
第三行抱怨它无法弄清楚 x
应该是什么类型。 "Type annotation missing in pattern"。在某些情况下,Swift 可以计算出我们的变量应该是什么类型。比如var x = 10
,Swift可以算出x
的类型应该是Int
。如果我们想要别的东西,我们必须指定。但是如果我们没有在声明中赋值,Swift 就不知道了,必须被告知:var x: Int?
如果 x
存在于不同的范围呢?
好吧,Swift 允许变量阴影。也就是说,在一个作用域声明的变量隐藏了在另一个作用域声明的变量。
因此,例如:
class Foo {
let x = 10
func foo(value: Int) -> Int {
let a = value * self.x
let x = 10
return a * x
}
}
现在我们可以在声明局部作用域 x
之前使用 some x
,但这些是不同的变量。另外,也许最重要的是,请注意此处 x
前面的 self.
。这是必需的。没有它,Swift 将拒绝编译此代码并会抱怨:"Use of local variable 'x' before its declaration."
然而,在 类 的函数中并不是我们可以隐藏变量的唯一地方。我们也可以在 if
个块(以及其他地方)内完成,这会使事情变得更加混乱。考虑一下:
class Foo {
let x = 10
func foo(value: Int) -> Int {
print(x)
if x > 3 {
let x = 2
print(x)
}
return x
}
}
在这里,我们在声明它之前使用了两次 x
。而且我们不必使用 self.
并且它不会抱怨并且编译得非常好。但需要注意的是 outside if
块(包括 x > 3
条件)我们引用的 x
是实例变量,但是在 if
块中,我们创建了一个名为 x
的新变量,它隐藏了实例变量。我们还可以使用 if let
和 if var
构造(但不是 guard let
)来创建相同类型的阴影。
调用这个函数的结果是打印值10
,我们进入if
块,打印2
的值,然后退出if
块并返回 10
的值。
现在让我们通过 var
进入混音。首先,如果您还不知道,您应该从阅读 this 开始,它解释了 let
和 var
之间的区别(一个是常量,另一个不是)。
让我们将 let
与 var
与作用域和变量阴影结合起来,看看它是如何影响事物的。
class Foo {
let x = 10
func foo(value: Int) -> Int {
print(x)
if x > 3 {
var x = 2
while x < 10 {
print(x)
x += 3
}
return x
}
return x
}
}
好的,这与以前相同,但 if
块中的位稍微复杂一些。
在这里,我们的局部范围变量声明为 var
,而我们的实例变量保持常量 let
。我们不能修改实例变量,但是我们可以修改局部变量。我们这样做,在 while
循环的每次迭代中。
但重要的是,这个变量是一个与实例变量完全不同的变量。它也可能有一个完全不同的名称(实际上,它基本上总是 应该 有一个不同的名称)。所以修改我们的局部变量 x
不会改变我们范围更广的实例变量 x
的任何内容。它们是驻留在不同内存位置的不同变量。一旦变量声明为 let
或 var
,该变量就不能更改为另一个。
众所周知,JavaScript "Hoists" 将变量放在文件或作用域的顶部。但是根据我的理解,使用 let
与 var
相同,只是 let
被限制在它定义的范围内。
作为编译语言而不是解释语言,我们可以假设 Swift 不会这样做吗?
例如:
x = 10
var y = x + 10
var x
'let' 和 'var' 在范围上没有区别。
Global variables are variables that are defined outside of any function, method, closure, or type context. Local variables are variables that are defined within a function, method, or closure context.
can we assume Swift does NOT do this?
你可以假设任何你想要的,但无论编程语言如何,你绝对最好的选择是尝试一下并找出答案。如果您将示例代码粘贴到 Playground 或任何支持 Swift 的 IDE 中,或者只是通过命令行尝试 运行 它,您很快就会发现这很简单不起作用。
你的问题有点令人困惑,但我想我可以解决你所有或至少大部分的问题。
x = 10
var y = x + 10
var x
假设您的原始示例没有其他代码,它根本无法编译。三行都有问题
前两行抱怨使用了未解析的标识 'x'。在英语中,这意味着 Swift 无法弄清楚你在说什么变量。 Swift 中的变量必须在使用前声明,因此第三行的声明对接下来的两行没有帮助。
第三行抱怨它无法弄清楚 x
应该是什么类型。 "Type annotation missing in pattern"。在某些情况下,Swift 可以计算出我们的变量应该是什么类型。比如var x = 10
,Swift可以算出x
的类型应该是Int
。如果我们想要别的东西,我们必须指定。但是如果我们没有在声明中赋值,Swift 就不知道了,必须被告知:var x: Int?
如果 x
存在于不同的范围呢?
好吧,Swift 允许变量阴影。也就是说,在一个作用域声明的变量隐藏了在另一个作用域声明的变量。
因此,例如:
class Foo {
let x = 10
func foo(value: Int) -> Int {
let a = value * self.x
let x = 10
return a * x
}
}
现在我们可以在声明局部作用域 x
之前使用 some x
,但这些是不同的变量。另外,也许最重要的是,请注意此处 x
前面的 self.
。这是必需的。没有它,Swift 将拒绝编译此代码并会抱怨:"Use of local variable 'x' before its declaration."
然而,在 类 的函数中并不是我们可以隐藏变量的唯一地方。我们也可以在 if
个块(以及其他地方)内完成,这会使事情变得更加混乱。考虑一下:
class Foo {
let x = 10
func foo(value: Int) -> Int {
print(x)
if x > 3 {
let x = 2
print(x)
}
return x
}
}
在这里,我们在声明它之前使用了两次 x
。而且我们不必使用 self.
并且它不会抱怨并且编译得非常好。但需要注意的是 outside if
块(包括 x > 3
条件)我们引用的 x
是实例变量,但是在 if
块中,我们创建了一个名为 x
的新变量,它隐藏了实例变量。我们还可以使用 if let
和 if var
构造(但不是 guard let
)来创建相同类型的阴影。
调用这个函数的结果是打印值10
,我们进入if
块,打印2
的值,然后退出if
块并返回 10
的值。
现在让我们通过 var
进入混音。首先,如果您还不知道,您应该从阅读 this 开始,它解释了 let
和 var
之间的区别(一个是常量,另一个不是)。
让我们将 let
与 var
与作用域和变量阴影结合起来,看看它是如何影响事物的。
class Foo {
let x = 10
func foo(value: Int) -> Int {
print(x)
if x > 3 {
var x = 2
while x < 10 {
print(x)
x += 3
}
return x
}
return x
}
}
好的,这与以前相同,但 if
块中的位稍微复杂一些。
在这里,我们的局部范围变量声明为 var
,而我们的实例变量保持常量 let
。我们不能修改实例变量,但是我们可以修改局部变量。我们这样做,在 while
循环的每次迭代中。
但重要的是,这个变量是一个与实例变量完全不同的变量。它也可能有一个完全不同的名称(实际上,它基本上总是 应该 有一个不同的名称)。所以修改我们的局部变量 x
不会改变我们范围更广的实例变量 x
的任何内容。它们是驻留在不同内存位置的不同变量。一旦变量声明为 let
或 var
,该变量就不能更改为另一个。