迅速吊装?

dev*_*ech -2 hoisting swift

众所周知,JavaScript"将"变量"提升"到文件或范围的顶部.但根据我的理解,使用let是相同的,var只是let局限于它所定义的范围.

作为一种编译语言而不是解释,我们可以假设Swift不这样做吗?

例如:

x = 10

var y = x + 10

var x
Run Code Online (Sandbox Code Playgroud)

nhg*_*rif 7

我们可以假设Swift不这样做吗?

你可以假设你想要的任何东西,但无论编程语言如何,你绝对最好的选择只是试一试并找出答案.如果您将示例代码粘贴到Playground或任何支持Swift的IDE中,或者只是尝试通过命令行运行它,您很快就会发现这根本不起作用.


你的问题有些令人困惑,但我想我可以解决你的所有或至少大部分问题.

x = 10    
var y = x + 10
var x
Run Code Online (Sandbox Code Playgroud)

假设没有其他代码可以与原始样本一起使用,它只是不编译.这三条线都有问题.

前两行抱怨使用未解析的'x'.在英语中,这意味着Swift无法弄清楚你在说什么变量.Swift中的变量必须在使用之前声明,因此第三行的声明对接下来的两行没有帮助.

第三行抱怨它无法弄清楚x应该是什么类型."在模式中输入缺少的注释".在某些情况下,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
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我们可以在声明本地范围之前使用一些 ,但这些是不同的变量.此外,也许最重要的是,请注意这里的前提.这是必需的.没有它,Swift将拒绝编译此代码,并会抱怨:"在声明之前使用局部变量'x'."xxself.x


但是,在类的函数内并不是我们可以影子变量的唯一地方.我们也可以在if块(在其他地方)内进行,这可能会让事情变得更加混乱.考虑一下:

class Foo {
    let x = 10

    func foo(value: Int) -> Int {
        print(x)
        if x > 3 {
            let x = 2
            print(x)
        }
        return x
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里,我们x在声明之前已经使用了两次.而且我们没有必要使用self.它并且它没有抱怨和编译完全正常.但重要的是要注意,我们引用的块(包括条件)之外是实例变量,但是在块内部,我们创建了一个新的变量,该变量调用实例变量.我们也可以通过使用和构造(但不是)来创建相同类型的阴影.ifx > 3xifxif letif varguard let

调用此函数的结果将10是打印值,我们输入if块,2打印值,然后我们退出if块并10返回值.


现在让我们来看看var这里的混音.首先,如果你是不是已经知道,你应该开始阅读其中解释之间的差异letvar(一个是恒定的,另一种是不).

让我们结合letvs 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
    }
}
Run Code Online (Sandbox Code Playgroud)

好的,所以这和以前一样,但是在if块内稍微复杂一点.

这里,我们的本地范围变量被声明为varwhile,我们的实例变量保持不变let.我们不能修改实例变量,但我们可以修改局部变量.我们在while循环的每次迭代中都这样做.

但重要的是,这个变量是一个与实例变量完全不同的变量.它可能有一个完全不同的名称(在实践中,它基本上应该有一个不同的名称).因此修改我们的局部变量x不会改变我们更广泛范围的实例变量x.它们是位于不同内存位置的不同变量.一旦变量声明为a let或a var,该变量就不能更改为另一个变量.