乐趣区

关于前端:前端学-Ruby熟悉-Ruby-语法

写在后面

咱们当然心愿能在本地中执行代码,如果你还没有只是看看,还没装置 ruby,能够在 try ruby 或者 replit 在线编写代码

本文目录

Ruby 是什么

根本语法

  • 变量
  • 算术操作
  • 位运算符
  • 打印输出
  • 正文

条件语句:控制流

循环 / 迭代器

数据结构

  • String
  • Integer/Float
  • Array
  • Hash
  • Set
  • Range

函数(办法)

面向对象编程

  • 对象

Ruby 是什么

弱类型语言

Ruby 是一门弱类型语言,和 JavaScript 一样

a = 5;
a = 'Hello'
puts a # Hello

命名格调

像变量(variable)、符号(symbol)、办法(method),通常应用 snake_case 格调

snake_case 格调即短语内的各个单词之间以下划线做距离

像常数(constant),应用 CONST_FOO 格调

类名(class name),应用骆驼(CamelCase)格调

文件名(file name),应用 snake_case 格调

“$”结尾的变量:全局变量

“@”结尾的变量:实例变量

“@@”结尾的变量:类变量

小写字母或者下划线(_)结尾的变量:局部变量

根本语法

Ruby 的赋值不须要加任何关键字,间接一个 变量名 = 值 即可

变量

x = 25 # => 25
x # => 25

留神赋值语句返回了赋的值,这意味着你能够用多重赋值语句

x = y = 10 # => 10
x # => 10
y # => 10

# 除了整数,咱们还能够应用 booleans、string、symbol、float 等数据类型
# booleans
true_boolean = true
false_boolean = false

# string 
my_name = 'johnny'

# symbol
a_symbol = :my_symbol

# float 
book_price = 15.80

算术操作

1 + 1 # =>2
7 - 1 # => 6
10 * 9 # => 90
42 / 7 # => 6
2 ** 5 # => 32 2 的 5 次方
5 % 3 # => 2

位运算符

3 & 5 # => 1
3 | 5 # => 7
3 ^ 5 # => 6

打印输出

puts "I'm printing!" # 打印输出,并在开端加换行符
#=> I'm printing!
#=> nil

print "I'm printing!" # 打印输出,不加换行符
#=> I'm printing! => nil

# ⭐除此之外,还能够用缩写 p
p "I'm printing!"

正文

# 单行正文
=begin
    多行正文
=end

条件语句:控制流

通过 if...else... 做条件判断。如果为真,它会执行语句中的内容。例如:

if true
    puts "Hello Ruby If"
end

if 2 > 1
    puts "2 大于 1"
end

与 JavaScript 相比,它没有更多的括号,只写必要的货色,然而因为没有中括号,所以当要完结时,须要用 end 来做拆散

后续的 def(函数标识符)、class(类标识符)都会有 end 来做完结

除此之外,还有 if...else...

if 2 > 1
    puts "2 大于 1"
else
    puts "2 小于 1"
end

还有 elsif 语法,留神不是 elseif,而是elsif,它,缩写了

if 2 > 1
    puts "2 大于 1"
elsif 2 < 1
    puts "2 小于 1"
else
    puts "2 等于 1"
end

咱们还能够用「倒装句」来写 if 语句

def hey_ho?
    true
end

puts "let's go" if hey_ho?

循环 / 迭代器

在 Ruby 中,咱们能够以多种不同的形式进行迭代。这里咱们探讨三个迭代器:while、for 和 each

while 循环

只有语句为真,代码块中的代码就会被执行,如打印 1 到 10 的数字:

num = 1

while num <= 10
    puts num
    num += 1
end

看看,Ruby 的代码整洁的难看

For 循环

将变量 num 传递给块,for 语句将迭代它:

for num in 1...10
    puts num
end

Each 迭代器

与其余两种不同,这种写法更像调用办法

[1, 2, 3, 4, 5].each do |num|
    puts num
end

其中 each 迭代器和 for 循环有什么不同呢?each 迭代器只保护迭代块内的变量,而 for 循环容许变量存在于块外

# for vs each

# for looping
for num in 1...5
    puts num
end

puts num # => 5

# each iterator
[1, 2, 3, 4, 5].each do |num|
    puts num
end

put num # => undefined local variable or method `num' for main:Object (NameError)

这里就牵扯到 block(块)了,在用 each 的时候也用到了 do 关键字,它会定义块,块会造成作用域,作用域外部的变量,内部不能方面(这里能够联想到 ES6 中的块级作用域)

数据类型

Ruby 的数据类型有很多,很细分,有 String、Number、Float、Array、Hash、Set、Range、Symbol、Boolean、Nil 等等。咱们通过 x.class 能得悉它的数据类型,通过object_id 得悉它的内存地址

String(字符串)

a = 'asdf' # asdf 将 asdf 赋值给 a
a[0] = 'b' # ruby 中所有皆对象
a.object_id # 70123455667 
a[1] = 'c' # c
a.object_id # 70123455667,a 不变
b = 'asdf' # 与 a 的值一样
b.object_id # 72343954534,但 object_id 不一样,阐明他们的内存地址不一样,和 JavaScript 的援用类型一样,每次赋值都存在堆内存里,所以说 ruby 性能差
# 在 Ruby 中,所有皆对象,比 JavaScript 更加彻底
a.class # String class 办法是判断它的类型

字符串的多种赋值形式

a = 'asdf' # 用单引号
"something#{a}" # somethingasdf 双引号相当于 javascript 中的模板字符串(``)
%q('asddas'dasda'') #"'asddas'dasda''"  保留你输出的任何值
%Q("sadsd") # "\"\"sadsd\"\"" 本义 
<<-Text
sdsd
dsadsad
dsdas
TEXT # 多行
"asdfgh".reverse # hgfdsa 反转
"hello".include?('o') # true 是否存在字母 o
"hello".index('l') # 2
"asdf".sub('s', 'b') # "adbf" 将 s 替换成 b
"asdf".sub!('s', 'b') # "abdf" 
! 有什么用呢,它能扭转原值
a = 'asdf' # asdf
a.sub('s', 'b') # abdf
a # asdf  a 的值没有变动
a.sub!('s', 'b') # abdf
a # abdf  a 的值产生扭转
a.size # 字符串长度

Integer(整数)/Float(浮点数)

66 # 66
66.class # Integer 整数
3.2 # 3.2
3.2.class # Float 浮点数
3.even? # 是否为偶数
3.odd? # 是否为奇数
283.to_s # 转化为 string 
3.times {p 'love'} # 打印三次 love
3 & 1 # 1 
3.232323.round(2) # 小数点保留 2 位

如果想把数字 1 存储在名为 one 的变量中:

one = 1

同理,如果要赋值数字 2,数字 1000,就能够如此:

two = 2
some_number = 10000

数组

array = [1, 2, 3, 4, 5] # => [1, 2, 3, 4, 5]

数组能够蕴含不同类型的元素

[1, "hello", false] # => [1, "hello", false]

数组能够被索引,从后面开始

array[0] # => 1
array.first # => 1 # 牛逼,这样都能够,array.second 是不是 hello,不妨一试
array[12] # => nil # nil 就是 js 中的 null 的意思吧

往数组中增加新值最常见的办法是 push 和 <<

array = []
array.push("1")
array.push("2")
puts array[0] # 1
puts array[1] # 2

<< 办法略有不同:

array = []
array << "3"
array << "4"
puts array[0] # 3
puts array[1] # 4

当然,还能够把 << 当作办法来应用,我的意思是说能够用. 来调用

array = []
array.<<("5")

puts array[0] # 5

数组是对象,援用类型

a = [] # []
a.object_id # 7012434563
b = a # []
b.object_id # 7012434563 与 a 一样,援用的是同一个内存地址
a << 'foo' # ["foo"]
a # ["foo"]
a.object_id # 7012434563
b # ["foo"]
b.object_id # 7012434563

# 创立形式:对象字面量[]、还有 Array.new
a = Array.new # []
a = Array.new(3) # [nil, nil, nil] 
a = Array.new(3, 0) # [0,0,0]

特地留神

a = Array.new(3, 'asdf') # ["asdf", "asdf", "asdf"]
a[0] # "asdf"
a[0][0] = 'b' # b
a[0] # "bsdf"
a # ["bsdf", "bsdf", "bsdf"]
a[0].object_id # 7012838949
a[1].object_id # 7012838949
a[2].object_id # 7012838949
# 因为它们是援用对象,指向同一个援用
# 如何只扭转数组中的第一项,不扭转其余的,应用 block(块)a = Array.new(3) {'asdf'} # ["asdf", "asdf", "asdf"]
a[0].object_id # 7022838393
a[1].object_id # 7323856575
a[2].object_id # 7342657667

第三种创立数组的办法

arr = %w(foo, bar, baz) # ["foo", "bar", "baz"]

数组的罕用办法

# 以下面 arr 为例子
arr[0] # "foo"
arr[-1] # "baz"
arr[1..2] # 取区间["bar", "baz"]
arr.fetch(0) # foo
arr.fetch(4) # 报错 
arr.fetch(4, "asdf") # "asdf"
arr.length # 3
arr.include?("sdad") # 是否存在 sdad,false
arr.include?('foo') # true
arr.empty?() # 是否为空 false
arr.push('ber') # ["foo", "bar", "baz", "ber"]
arr[7] = 'asdf' # ["foo", "bar", "baz", "ber", nil, nil, nil, "asdf"]
arr.delete("ber") # ["foo", "bar", "baz", nil, nil, nil, "asdf"]
arr.push("bar") # ["foo", "bar", "baz", nil, nil, nil, "asdf", "bar"]
arr.uniq # 取惟一,删除多余的值 ["foo", "bar", "baz", nil, "asdf"]
# arr.uniq! ! 会扭转原数组
arr.shuffle # 颠倒 ["asdf", nil, nil, nil, "baz", "bar", "foo"]
arr1 = [[1,2,3], [4, 5]]
arr.flatten # 扁平化 [1, 2, 3, 4, 5]

数组的遍历办法

arr = [1, -1, 2, 3, -4]
arr.each {|e| p e} # e 为数组中的每一项,p 为 put 打印,p e 打印每一项值
# 1, -1, 2, 3, -4
arr.reverse_each {|e| p e} # 倒着遍历 -4, 3, 2, -1, 1
arr.each_width_index {|e, i| p [e, i] } # [1, 0] [-1, 1] [2, 2] [3, 3] [-4, 4]
arr.sort # [-4, -1, 1, 2, 3]
arr.select {|e| e > 0} # 抉择大于 0 的元素,[1, 2, 3]

哈希表:Key-Value 数据结构 / 字典汇合

JavaScript 的数据类型中是没有 hash 的,但在 Ruby 中有。它的特点是以键 / 值对示意

因为在数组中咱们用数字索引来获取到值,而 hash 数据结构中能够应用数字、字符串或者其余类型来做索性

轻易一说,JavaScript 中尽管没有 hash,然而它的 object 的性能就是 hash

哈希就键值对的联合,例如:

hash = {"color" => "green", "number" => 5}

hash.keys #=> ['color', 'number']

# 哈希表能够通过键疾速地查问
hash['color'] # => 'green'
hash['number'] # => 5

# 查问一个不存在的键会返回 nil
hash['nothing here'] # => nil

# 增加数据
hash['print'] = 27.6 # => 27.6

{} 字面量示意 hash

a = {key: 'value'} # {:key => "value"}
b = a # {:key => "value"}
b.object_id # 91860
a.object_id # 91860
a[:key] = 'foo' # foo
a # {:key => "foo"}
b # {:key => "foo"}

另一种创立 hash 的办法,new

Hash.new # {}
h = Hash.new(3) # {}
h[0] # 3
h[1] # 3

哈希的办法

h = {a: 1, b: 2}
h[:c] = 3
h # {:a=>1, :b=>2, c=>3}
h[:a] # 1
h.delete(:a) # 1
h # {:b=>2, c=>3}
h.assoc(:b) # 获取 key 和 value [:b, 2]
h.empty?() false 
h.has_value?(2) # 是否有值 2, true
h.has_key?(:b) # 是否有值:b, true
h.keys # [:b, :c]
h.values  # [2, 3]
h.to_a # 变成 array [[:b, 2], [:c, 3]]
h2 = {d: 4}
h.merge(h2) # {:b=>2,:c=>3,:d=>4}

hash 的遍历办法

h.each {|key, value| p [key, value]} # [:b, 2] [:c, 3]
h.each_key {|key| p key} # :b :c
h.each_value {|v| p v} # 2 3
h.select {|key| key == :b} # {:b=>2}

汇合(Set)

require 'set' # 命令行中默认不援用 set
a = Set.new [1, 2] # <Set: {1, 2}>
a.add("foo") # Set: {1, 2, "foo"}>
b = Set.new [2, 3, 4] #Set: {2, 3, 4}>
a & b # Set: {2}>
a | b # Set: {1, 2,”foo","3","4"}>
a <= b # b 是否是 a 的子集,false
b <= a # a 是否是 b 的子集,false

范畴(Range)

闭区间,应用两个点(..)来示意

r = 1..5 # 1, 2, 3, 4, 5 
r.include?(2) # true
a = [1, 2, 3, 4]
a[1..2] # [2, 3]

开区间,应用三个点(…)来示意

r = 1...5 # 包含 1, 2, 3, 4

其余数据类型

当然,还有一些会用但比较简单的数据类型,这里简略带过

Symbol:符号:不可变类型。长处,查找速度快,毛病是不会被垃圾回收,造成内存不够的可能

Boolean:布尔值

Nil:空值

Regexp:正则表达式

函数(办法)

def double(x)
    x * 2
end

# 函数(以及所在的块)隐式地返回最初语句的值
double(2) # => 4

# 当不存在歧义的时候括号可有可无
double 3 # => 6

double double 3 # => 12

def sum(x, y)
    x + y
end

# 办法的参数通过逗号分隔
sum 3, 4 #=> 7

sum sum(3, 4), 5 => 12

# yield 
# 所有的办法都有一个隐式的,可选的块参数
# 能够用‘yield’关键字调用

def surround
    puts "{"
    yield
    puts "}"
end

surround {puts "hello world"}

# {
# hello world
# }
# => nil

面向对象编程

对象

在 Ruby 中,(简直)所有货色都是对象

# 数字是对象
3.class #=> Interger
3.to_s #=> "3"

# 字符串是对象
"Hello".class #=> String

# 办法也是对象
"Hello".method(:class).class => Method

类(Class)

类 = 属性 + 办法

在后面,咱们谈到了 Ruby 的对象,咱们说 Ruby 中的任何货色都是对象。而作为一种面向对象的编程语言,Ruby 应用了类和对象的概念

“类”是一种定义对象的办法,如图书、狗、自行车

“对象”有两个次要特色:数据(属性)和行为(办法)

语法很简略,例如:

class Book
end

咱们用 class 语句定义 Book 并以 end 完结

对象是类的实例。咱们通过调用 .new 办法创立一个实例

book = Book.new

这里的书 是 书类 的 一个对象(或实例)

咱们定义书类将具备 4 个属性:书名、作者、星、价格

咱们从新定义咱们的类 Book:

class Book
    def initialize(title, author, star, price)
        @title = title
        @author = author
        @star = star
        @price = price
    end
end

咱们将 initialize 办法成为构造方法,当咱们要应用这个类时,就能够这样:

book1 = Book.new('金瓶梅', '兰陵笑笑生', '五星', 16.8)

咱们还能够定义书的行为:读书

class Book
    def initialize(title, author, star, price)
        @title = title
        @author = author
        @star = star
        @price = price
    end
    
    def read
        puts "我读 #{@title},这本书的作者是 #{@author},举荐指数 #{@star},价格 #{@parice} 元"
    end
end

应用该类创建对象的实例代码如下:

book1 = Book.new('金瓶梅', '兰陵笑笑生', '五星', 16.8)
book2 = Book.new('南回归线', '亨利·米勒', '五星', 66.6)

book1.read # 我读金瓶梅,这本书的作者是兰陵笑笑生,举荐指数五星,价格 16.8 元
book12.read # 我读南回归线,这本书的作者是亨利·米勒,举荐指数五星,价格 66.6 元

参考资料

  • Y 分钟速成 X
  • Learning Ruby: From Zero to Hero

系列文章

  • 前端学 Ruby:前言
  • 前端学 Ruby:装置 Ruby、Rails
退出移动版