英文版PDF下载地址http://download.csdn.net/detail/tsingheng/7480427

依照传统学习程序语言都是从hello,world開始,在Swfit里面仅仅须要一行代码即可了

println("Hello, world")

你要是学过C语言或者OC。这样的语法应该非常熟悉。可是在Swfit里面这单独一行代码就是一个完整的程序。

你都不须要再去导入什么库,比方input/output或者string之类的。

全局作用范围内(global scope)的代码用来作为程序的入口。所以连main方法都不须要了。甚至语句结尾连分号都不用写了。

这份观光手冊展示了怎么用swift去完毕各种各样的编程任务。要是有什么看不懂的也不要怕,这里介绍的东西到后面都还会有具体介绍。

NOTE:为了获得最好的学习体验,建议打开XCode建个playgrounds,写完代码立刻就能看到结果了。

1.简单值

let用来定义常量,var用来定义变量。

常亮的值在编译的时候能够是未知的,可是你仅仅能赋值一次。

你能够定义一个常亮给他赋个值。然后其它地方随便用可是不改他的值。

var myVariable = 42
myVariable = 5
let myConstant = 42

无论是常量还是变量,赋值的时候值类型跟常量或者变量的类型必须同样。可是我们不必每次都把类型明白写出来。当你声明的时候就给他赋个值,编译器就能判断出来是什么类型了。上面这个样例中,编译器能判断出来myVarible是integer由于初始化的值是integer。要是依据初始化值不能判断出来是什么类型。或者没有初始化值,拿在变量名称后面就必须加上: 类型。比方以下的样例

let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70

值从来不会自己主动转换成其它类型。假设你要转换,就用值再创建一个你须要的类型,比方

let label = "The width is "
let width = 94
let widthLabel = label + String(width)

事实上有更简单的方法能在字符串里加其它类型,把变量名放在括号中,再在括号前面加个\即可了。

比方

let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples"
left fruitSummary = "I have \(apples+oranges) pieces of fruit"

如要要创建数组类型或者字典类型就用中括号[]。假设要获取当中的节点就在[]中写节点的下标或者key值

var shoppingList = ["catfish", "water", "tulips", "blue paint"]
shoppingList[1] = "bottle of water" var occupations = [
"Malcolm": "Captain",
"Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations”

要创建空数组或者空字典就要用实例化的语法了。

let emptyArray = String[]()
let emptyDictionary = Dictionary<String, Float>()

要是类型能够判断出来,就能够用[]和[:]来替换了。比方说上面已经定义过shoppingList数组了。编译器能够判断出shoppingList是一个字符串数组,这个时候我想让他变成空数组,就仅仅须要写shoppingList = []就能够了。字典类型就不用说了吧。

2.控制流

if和switch做条件控制,for-in,for,while。和do-while做循环控制。条件或者循环变量外面的括号可有可无。可是代码段的大括号是必须的。

let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores {
if score > 50 {
teamScore += 3
} else {
teamScore += 1
}
}
teamScore

在if语句中,条件表达式必须是一个Boolean表达式,所以上面样例中假设写成if score {...}就是错的。

对于有些可能丢失的值,你能够使用If和let的组合。这样的值后面会介绍,叫做可选类型(optional),一个可选类型值要么有一个确切的值。要么就是nil也就是值丢失了。假设要定义可选类型的值,就在变量类型后面加一个问号。

var optionalString: String? = "Hello"
optionalString == nil var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
greeting = "Hello, \(name)"
}

EXPERIMENT 试试把optionalName的值换成nil,给if语句加一个else分支,else里面给greeting还有一个字符串,看看最后的greeting是什么。

注意条件语句let name = optionalName,假设optionalName的值是nil,那这个条件语句返回的就是false。大括号中的语句也就不会运行了。否则optionalName的值就被赋给常量name,而且在后面大括号中面能够使用name的值。

switch语句支持不论什么类型的数据和各种各样的比較运算,不仅仅是比較integer的值是不是相等。

let vegetable = "red pepper"
switch vegetable {
case "celery":
let vegetableComment = "Add some raisins and make ants on a log."
case "cucumber", "watercress":
let vegetableComment = "That would make a good tea sandwich."
case let x where x.hasSuffix("pepper"):
let vegetableComment = "Is it a spicy \(x)? "
default:
let vegetableComment = "Everything tastes good in soup."
}

EXPERIMENT 试试去掉default,看看会得到什么错误。

假设在switch里面匹配到某个case,运行完case的这段代码以后程序就会跳出这个switch。这里可不会像其它语言一样继续向后匹配。所曾经面样例中都找不到一个breakl。。

for-in能够用来遍历字典里面的各个项目

let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
}
}
}
largest

EXPERIMENT 加入另外一个变量来记录最大数字的kind。也就是最大的那个数字是什么。(拿上面这个样例来说结果应该是Square)

使用while能够反复运行一段代码,知道判断条件改变。

循环条件语句也能够放在循环体后面,这样能保证循环体至少被运行一次。

var n = 2
while n < 100 {
n = n * 2
}
n var m = 2
do {
m = m * 2
} while m < 100
m

在for循环中能够有两种方式使用下标,一种是使用..(两个点)来创建一个下标的范围,或者明白地写初始值,条件表达式,还有增长表达式(非常经典的for(int i = 0; i <= n; i++){})。

两种方式效果一样

var firstForLoop = 0
for i in 0..3 {
firstForLoop += i
}
firstForLoop var secondForLoop = 0
for var i = 0; i < 3; ++i {
secondForLoop += 1
}
secondForLoop

用..(两点儿)的范围是半开半闭区间的。用...(三点儿)的范围两边儿都是闭区间。

3.函数和闭包

函数使用keywordfunc来声明。调用函数的时候在方法名称后面加个括号,括号中加上參数值列表。函数返回值类型和參数列表中间用->隔开。

func greet(name: String, day: String) -> String {
return "Hello \(name), today is \(day)."
}
greet("Bob", "Tuesday")

EXPERIMENT 把參数day去掉。加入另外一个參数在返回的问候语里加上今天的午餐。

能够使用元组返回多个值

func getGasPrices() -> (Double, Double, Double){
return (3.59, 3.69, 3.79)
}
getGasPrices()

方法也能够使用变长參数,參数存储在数组中。

func sumOf(numbers: Int...) -> Int {
var sum = 0
for number in numbers {
sum += number
}
return sum
}
sumOf()
sumOf(42, 597, 12)

EXPERIMENT 写个函数求參数平均值。

在Swift里函数能够嵌套。内部函数能够訪问外层函数定义的变量。假设有些代码比較长或者非常复杂,你能够使用内部函数来简化。

func returnFifteen() -> Int {
var y = 10
func add() {
y += 5
}
add()
return y
}
returnFifteen()

函数也是一种类型,所以函数的返回值也能够是一个函数。

func makeIncrementer() -> (Int -> Int) {
func addOne(number: Int) -> Int {
return 1 + number
}
return addOne
}
var increment = makeIncrementer()
increment(7)

当然,函数也能够作为还有一个函数的參数。

func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool {
for item in list {
if condition(item) {
return true
}
}
return false
}
func lessThanTen(number: Int) -> Bool {
return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(numbers, lessThanTen)

函数实际上是闭包的一种特殊情况。

你能够写个闭包不要名字,仅仅须要把代码放到大括号中面。在代码里面用in分隔參数与返回类型跟函数体。

numbers.map({
(number: Int) -> Int in
let result = 3 * number
return result
})

EXPERIMENT 写个闭包,对于全部的奇数都返回0。

另外还有几个选项能够让你更方便的来写闭包。

假设说一个闭包的类型已经知道了,比方是托付的一个回调函数,那你能够省略他的參数类型或者返回类型,都省略了也行。仅仅有单独一行语句的闭包返回的是那条语句的计算结果。

numbers.map({number in 3*number})

你要是不想用參数名来使用參数,也能够用数字,这玩意儿在超短闭包里面非常有用。

一个闭包作为函数的最后一个參数能够放在括号后面。

sort([1, 5, 3, 12, 2]){$0 > $1}

4.对象和类

使用keywordclass后面加类名,就能创建一个类了。类里面的属性声明跟前面提到的常量或者变量的声明方式一样。除非是类变量。相似的,类里面的函数跟方法的声明也是一样的。

class Shape {
var numberOfSides = 0
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}

EXPERIMENT 用let加入一个常量属性,再加入一个带參数的方法。

假设要创建类的实例。在类名后面加上括号即可了。用点操作符来获取实例的属性或者调用实例的方法。

var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()

上面定义的Shape类缺了个非常重要的东东。就是初始化,当创建类的实例的时候须要初始化的。初始化方法的名字是init

class NamedShape {
var numberOfSides: Int = 0
var name: String
init(name: String) {
self.name = name
}
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}

注意上面init里面有个self,跟java里面的this应该是一个意思,这里是用来区分等号左边的name是对象的name属性。右边的name是初始化方法的參数name。

实例化方法參数传递跟普通方法传递是一样的。对象的每个属性都必须要实例化,要么实在声明的地方赋值(比方numberOfSide)。要么就在init里面(比方name)。

假设想在对象被回收的时候做一些其它操作,能够用deinit方法来创建析构函数。

类继承的方法是在子类后面加上冒号。再加上父类。

Swift没有规定说一个类必须要继承哪个类,所以不须要继承的时候冒号跟父类就能够省略了。(好像OC必须至少要继承NSObject)

子类假设要重写父类的方法就要在子类方法前面加override,为了防止你不小心又一次了哪个方法。假设你不写。编译器是要报错的。假设子类的方法父类里面没有,你还加个override,编译器照样报错。

class Square: NamedShape {
var sideLength: Double
init(sideLength: Double, name: String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 4
}
func area() -> Double {
return sideLength * sideLength
}
override func simpleDescription() -> String {
return "A square with sides of length \(sideLength)."
}
}
let test = Square(sideLength: 5.2, name: "my test square")
test.area()
test.simpleDescription()

EXPERIMENT 创建一个Circle类,继承NameShape。初始化方法參数有半径跟名称。实现Circle的area和describe方法。

属性除了像上面那样的以外,还能够有getter和setter。

class EquilateralTriangle: NamedShape {
var sideLength: Double = 0.0 init(sideLength: Double, name: String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 3
} var perimeter: Double {
get {
return 3.0 * sideLength
}
set {
sideLength = newValue / 3.0
}
} override func simpleDescription() -> String {
return "An equilateral triagle with sides of length \(sideLength)."
}
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
triangle.perimeter
triangle.perimeter = 9.9
triangle.sideLength

在perimeter的setter方法里面,參数名称默认是newValue,你也能够在set后面加上括号指定參数的名称。

上面样例中的EquilateralTriangle的初始化方法做了三件事情

1.给子类定义的属性赋值。

2.调用父类的初始化方法。

3.改变父类中定义的属性的值。这里就能够调用对象的各种方法了,包含getter,setter。

假设你不须要去计算某个属性的值。可是想在属性赋值之前和之后做点儿事情,那你能够用willSet和didSet。有点儿像java里面的回调方法。比方以下的样例能确保三角形周长跟正方形周长相等。

class TriangleAndSquare {
var triangle: EquilateralTriangle {
willSet {
square.sideLength = newValue.sideLength
}
}
var square: Square {
willSet {
triangle.sideLength = newValue.sideLength
}
}
init(size: Double, name: String) {
square = Square(sideLength: size, name: name)
triangle = EquilateralTriangle(sideLength: size, name: name)
}
}
var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
triangleAndSquare.square.sideLength
triangleAndSquare.triangle.sideLength
triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
triangleAndSquare.triangle.sideLength

函数跟类里面的方法是有个非常重要的差别的。函数的參数名仅仅能在函数里面使用,可是方法的參数名在方法调用的时候也要用到(除了第一个參数)。当你调用方法的时候。默认调用的參数名跟方法里的參数名是一样的。你也能够给參数再额外定义一个名字。这个名字仅仅在方法里面能够用。

class Counter {
var count: Int = 0
func incrementBy(amount: Int, numberOfTimes times: Int) {
count += amount * times
}
}
var counter = Counter()
counter.incrementBy(2, numberOfTimes: 7)

假设你在用可选值,问号后面能够加方法操作或者属性或者下标操作。假设问号前面的值是nil,那么问号后面的表达式就不会被运行,整个表达式返回的也是nil,假设是第二种情况,可选值是个展开的值(unwrapped value不知道怎么翻译),那跟在问号后面的也是个展开的值。

两种情况下整个表达式返回的都是个可选值。

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength

5.枚举和结构类型

enum用来创建枚举类型。跟类一样,枚举也能够定义方法。

enum Rank: Int {
case Ace = 1
case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
case Jack, Queen, King
func simpleDescription() -> String {
switch self {
case .Ace:
return "ace"
case .Jack:
return "jack"
case .Queen:
return "queen"
case .King:
return "king"
default:
return String(self.toRaw())
}
}
}
let ace = Rank.Ace
let aceRawValue = ace.toRaw()

EXPERIMENT 写个方法依据原始数据比較两个Rank类型的大小。

上面样例中,枚举类型的原始类型是Int,这样的类型你能够仅仅指出第一个枚举的原始值。

剩下的将会按顺序递增。

当然原始值类型也能够用浮点数或者字符串。

toRaw和fromRaw两个函数能够分别获取原始值和枚举值。

if let convertedRank = Rank.fromRaw(3) {
let threeDescription = convertedRank.simpleDescription()
}

成员值是枚举的实际的值,而不是枚举的原始值。

实际上要是枚举没有什么实际有意义的原始值,大可不要了。

enum Suit {
case Spades, Hearts, Diamonds, Clubs
func simpleDescription() -> String {
switch self {
case .Spades:
return "spades"
case .Hearts:
return "hearts"
case .Diamonds:
return "diamonds"
case .Clubs:
return "clubs"
}
}
}
let hearts = Suit.Hearts
let heartsDescription = hearts.simpleDescription()

EXPERIMENT 加入一个方法color,假设是黑桃或者梅花,返回"这牌是黑色的",假设是红桃儿或者方片儿返回“这牌是红色儿的”。

注意到上面样例中有两种方式来获取枚举值Hearts。

当要赋值给常量hearts的时候是要用Suit.Heart的。由于这个时候常亮还不知道自己到底是什么类型。可是在switch里面,就省略了点前面的Suit。由于self知道自己就是个Suit。

仅仅要变量或者常量知道自己是那种枚举类型,就能用这样的缩写形式。

struct用来创建结构类型。预计做行政的都知道。

struct支持非常多类的特性,包含方法。初始化器。他跟类最大得差别就是在赋值的时候,class对象是传递引用。结构类型是值传递。假设你是做JAVA的,能够觉得结构类型就好比java里面的基本数据类型一样。

struct Card {
var rank: Rank
var suit: Suit
func simpleDescription() -> String {
return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
}
}
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()

EXPERIMENT 给Card加入一个方法,创建一副牌。不要俩王的。

以下这两句有点儿难理解。对着后面的样例看看就能明白了。枚举的一个成员的能够相应非常多个实例。而这非常多个实例又能够相应不同的值。怎么做到呢。要在你创建枚举成员实例的时候给他提供相应的值。

这个值跟原始值还是不一样的。对已同一个成员的多个实例来说他们的原始值都是一样的,都是在定义枚举成员的时候指定的。

比方说要从一台服务器获取日出和日落的时间。

服务端要么返回一段日落或者日出时间的信息,要么返回一个错误消息。

enum ServerResponse {
case Result(String, String)
case Error(String)
} let success = ServerResponse.Result("6:00 am", "8:09 pm")
let failure = ServerResponse.Error("Out of cheese.") switch success {
case let .Result(sunrise, sunset):
let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)."
case let .Error(error):
let serverResponse = "Failure... \(error)"
}

EXPERIMENT 给ServerResponse和后面的switch再加入一个case。比方表示今儿没出太阳。

注意上面日出跟日落时间是怎么从ServerResponse中取出来而且在switch里面匹配的。

6.接口和拓展

protocol用来声明接口。

protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()
}

类,枚举,结构,都能实现接口。

class SimpleClass: ExampleProtocol {
var simpleDescription: String = "A very simple class."
var anotherProperty: Int = 69105
func adjust() {
simpleDescription += " Now 100% adjusted."
}
}
var a = SimpleClass()
a.adjust()
let aDescription = a.simpleDescription struct SimpleStructure: ExampleProtocol {
var simpleDescription: String = "A simple structure"
mutating func adjust() {
simpleDescription += " (adjusted)"
}
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription

EXPERIMENT 写个实现上面接口的枚举。

注意上面SimpleStructure里面有个方法前面加了个mutating。表明这种方法要改动结构体。那为什么上面的class里面的方法没加呢。由于类里面的方法总是会改变类的类型。

extension用来给已有的类型加入新的功能。

比方加入方法。属性啊之类的。你还能够用extension给其它随意地方定义的类型加入接口,甚至是导入的第三方库或者框架都行。

extension Int: ExampleProtocol {
var simpleDescription: String {
return "The number \(self)"
}
mutating func adjust() {
self += 42
}
}
7.simpleDescription

EXPERIMENT 用extension给Double类型加个求绝对值的方法。

使用接口名称的方式跟使用其它类型方式几乎相同的。

比方说创建一堆对象。对象类型不一样,可是都实现了同一个接口。当你使用类型是接口的对象时,在接口里面未定义的方法是不能调用的。

let protocolValue: ExampleProtocol = a
protocolValue.simpleDescription
// protocolValue.anotherProperty // Uncomment to see the error

上面样例中即使protocolValue实际上是一种SimpleClass的对象,可是编译器仅仅能把他当成ExampleProtocol。所以说没在接口里面定义的方法你是调用不到的。

(话说JAVA不是能够强制类型转换吗)。

7.泛型

泛型的用法是在尖括号中加上类型名称。

func repeat<ItemType>(item: ItemType, times: Int) -> ItemType[] {
var result = ItemType[]()
for i in 0..times {
result += item
}
return result
}
repeat("knock", 4)

函数。方法。类。枚举,结构,都能用到泛型。

// Reimplement the Swift standard library's optional type
enum OptionalValue<T> {
case None
case Some(T)
}
var possibleInteger: OptionalValue<Int> = .None
possibleInteger = .Some(100)

wherekeyword放在类型名称后面用来声明一些条件。

比方类型必须实现某个接口,或者两个类型必须同样,或者类型必须是某个类的子类。

跟java里面的概念一样的。

func anyCommonElements <T, U where T: Sequence, U: Sequence, T.GeneratorType.Element: Equatable, T.GeneratorType.Element == U.GeneratorType.Element> (lhs: T, rhs: U) -> Bool {
for lhsItem in lhs {
for rhsItem in rhs {
if lhsItem == rhsItem {
return true
}
}
}
return false
}
anyCommonElements([1, 2, 3], [3])

EXPERIMENT 改动上面的anyCommonElements函数。返回两个序列里面同样元素组成的数组。

一般简单情况下能够省略where,仅仅在类型名后面加上冒号和父类或者接口的名称。比方<T: Equatable>跟<T where T : Equatable>效果是一样的。

本章完。下章地址 3.Swift基础知识

2.Swift教程翻译系列——Swift概览的更多相关文章

  1. 4.Swift教程翻译系列——Swift基本运算符

    英文版PDF下载地址http://download.csdn.net/detail/tsingheng/7480427 运算符是指一个特殊的符号,能够用来查看.更改值或者相加.比方说加法运算符+能够讲 ...

  2. 5.Swift教程翻译系列——Swift字符串和字符

    英文版PDF下载地址http://download.csdn.net/detail/tsingheng/7480427 字符串是一组字符的有序序列,比方"hello,china"或 ...

  3. 6.Swift教程翻译系列——Swift集合类型

    英文版PDF下载地址http://download.csdn.net/detail/tsingheng/7480427 Swift提供数组和字典两种集合类型.用来存储很多值的情况.数组有序的存储一组同 ...

  4. 1.Swift教程翻译系列——关于Swift

    英文版PDF下载地址http://download.csdn.net/detail/tsingheng/7480427 我本来是做JAVA的.可是有一颗折腾的心,苹果公布Swift以后就下载了苹果的开 ...

  5. 8.Swift教程翻译系列——控制流之条件

    3.条件语句 常常会须要依据不同的情况来运行不同的代码. 你可能想要在错误发生的时候运行一段额外的代码,或者当某个值变得太高或者太低的时候给他输出出来.要实现这些需求,你能够使用条件分支. Swift ...

  6. 中文版 Apple 官方 Swift 教程《The Swift Programming Language》

    简介 欢迎使用 Swift 关于 Swift 版本兼容性 Swift 初见 Swift 版本历史记录 Swift 教程 基础部分 基本运算符 字符串和字符 集合类型 控制流 函数 闭包 枚举 类和结构 ...

  7. Entity Framework教程翻译 ---- 系列教程

    Entity Framework教程(第二版) (翻译)Entity Framework技巧系列之十四 - Tip 56 (翻译)Entity Framework技巧系列之十三 - Tip 51 - ...

  8. RHadoop教程翻译系列 _Mapreduce(1)_第一个Mapreduce任务

    如果单从概念上来说,Mapreduce和R中的函数lapply, tapply并无差别,它们都是把元素转化成列,然后计算索引(Mapreduce中的键),最后合并成一个定义好的组合.首先,让我们看一个 ...

  9. Swift教程之运算符重载

    http://blog.csdn.net/mengxiangyue/article/details/43437797 原文地址:http://www.raywenderlich.com/80818/o ...

随机推荐

  1. PIE SDK与Matlab结合说明文档

    1.功能简介 Matlab是三大数学软件之一,它在数学类科技应用软件中在数值计算方面首屈一指.Matlab可以进行矩阵运算.绘制函数和数据.实现算法.创建用户界面.连接其他编程语言的程序等,主要应用于 ...

  2. AWS Intro - Static IP with ssh

    Notes:  Please config static ip when launch instance. Because change dynamic public ip to static ip, ...

  3. linux下memcached的启动/结束的方式

    当前项目中,linux下memcached的启动/结束的方式 默认情况下memcached安装到/usr/local/bin下. 进入安装目录,启动memcached:/usr/local/memca ...

  4. 基础知识之 - C# Using的用法

    C#里面Using有两种用法: 1.作为指令. using+命名空间,导入其他命名空间中定义的类型,这样可以在程序中直接用命名空间中的类型,不必指定命名空间: 命名空间是.NET程序在逻辑上的组织结构 ...

  5. Eclipse error: “The import XXX cannot be resolved”

    解决 Eclipse error: “The import XXX cannot be resolved” eclipse中修改: 1. 项目-->Properties-->java bu ...

  6. POJ 3468——A Simple Problem with Integers——————【线段树区间更新, 区间查询】

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 86780   ...

  7. nginx反向代理使用网址速度变慢

    最近公司网址加载静态文件的速度总是跟不上于是试着用带端口的ip来访问, 发现速度快不少于是将nginx的代理修改为ip的如: location / { proxy_pass http://localh ...

  8. 深入理解JavaScript系列(12):变量对象(Variable Object)

    介绍 JavaScript编程的时候总避免不了声明函数和变量,以成功构建我们的系统,但是解释器是如何并且在什么地方去查找这些函数和变量呢?我们引用这些对象的时候究竟发生了什么? 原始发布:Dmitry ...

  9. Python contextlib.contextmanager

    看着代码又发现了一个奇怪的东西: @contextlib.contextmanager def __call__(self, incoming): result_wrapper = [] yield ...

  10. dhtml

    网页换肤:<div> <button>red</button> <button>blue</button> <button>bl ...