发布于 2026-01-06 1 阅读
0

面向 JS 开发者的 Kotlin 入门(第一部分) 好的,但是为什么要选择 Kotlin?快速语言参考(从 JS 到 Kotlin) 接下来该怎么做?

面向 JS 开发人员的 Kotlin(第一部分)

好吧,但是为什么要用 Kotlin 呢?

快速语言参考(从JS到Kotlin)

接下来该怎么办?

JavaScript 是一门神奇的语言:它从最初的“玩具语言”发展成为如今最普及的编程语言——你可以在浏览器、服务器上运行它,你可以构建移动应用程序、可穿戴设备应用程序——甚至你可以用 JavaScript 为 NASA 的太空服编写程序。

Spacesuite 中的节点

不过,学习多种语言仍然有很多机会——我甚至还没提到职业机会:正如大卫·托马斯和安德鲁·亨特在他们的经典著作《程序员修炼之道》中所说:

每年至少学习一门新语言。不同的语言用不同的方式解决相同的问题。通过学习几种不同的方法,你可以拓宽思维,避免陷入思维定势。

简而言之:是的,JavaScript 很棒,但学习一门新语言是一件很强大的事情:它会影响你思考编程的方式,给你带来新的视角,并影响你解决问题的方式,最终使你成为一名更优秀的软件开发人员。

好吧,但是为什么要用 Kotlin 呢?

为什么选择 Kotlin

市面上编程语言成百上千种,为什么偏偏是 Kotlin?原因很简单:Kotlin 的受欢迎程度(以及市场需求)正在飙升;它深受用户喜爱,并吸引了大批 JavaScript 开发者。这并非我的一家之言:GitHub 的Octoverse 报告指出 Kotlin 是其平台上增长最快的语言;而Kotlin 现状报告则显示,JavaScript 开发者是 Kotlin 新开发者的第二大来源。最后, Stack Overflow 的“内部消息”报告也充分体现了人们对 Kotlin 的喜爱

抛开那些花哨的特性不谈,Kotlin 本身就有很多优点,使其成为你下一门编程语言的绝佳选择:

  • 它采用现代语法:优雅、简洁、直接——您可以专注于完成任务。
  • 它明白面向对象编程和函数式编程不是竞争关系,而是正交范式,并同时采用了这两种范式(在这种情况下,它实际上与 JavaScript 有相似之处)。
  • 它是 Android 开发的官方语言,拥有许多库、扩展和优化功能。
  • Kotlin 是跨平台的——它的主要目标是 JVM(Java 虚拟机——用于客户端和服务器应用程序),但您可以将其编译为 JavaScript 以便在 Web 上使用,或者编译为本地二进制文件(例如 Windows、Linux、iOS 和 Mac 库)。

最后但同样重要的是,它用起来很有趣。

快速语言参考(从JS到Kotlin)

接下来的几节中,我们将对 Kotlin 语言的语法和语义进行概览,并将其与 JavaScript 进行对比。当然,新的语法和语义会带来新的模式和构建方式,但我们暂时先不讨论这些(或其他 Kotlin 细节)——学习一门新语言的最佳方法是快速上手实践,这样你就能很快掌握更多内容(也能赶上本系列的下一篇文章 =])。


变量和常量

Kotlin 变量使用var关键字声明。为了防止重新赋值,可以使用`--return`——两者的工作方式val JavaScript 的 `--return` 和 `--return` 非常相似letconst

Kotlin 是一种类型化语言,这意味着在某些情况下,您需要在代码中添加类型注解。不过,大多数情况下,编译器可以自动推断类型:

JavaScript



const name = "Jon Snow";
let isAlive = true;
let role; // Declared but not initialized


Enter fullscreen mode Exit fullscreen mode

Kotlin



// Types can be inferred from initialized variables
val name = "Jon Snow"
var isAlive = true

// If the variable is declared but not initialized, a type annotation is required:
var role: String



Enter fullscreen mode Exit fullscreen mode

字符串

单线和多线字符串

JavaScript



const house = "Stark";
const motto = `
Winter
is
comming
`;



Enter fullscreen mode Exit fullscreen mode

Kotlin



val house = "Stark"
val motto = """
Winter
is
comming
"""


Enter fullscreen mode Exit fullscreen mode

字符串插值

JavaScript



const action = `Attacking using a ${weapon}`;

const result = `Looks like you will ${user.getFate()}`;


Enter fullscreen mode Exit fullscreen mode

Kotlin



const action = "Attacking using a $weapon" 

const result = "Looks like you will ${user.getFate()}" // curly brackets are only necessary to interpolate expressions



Enter fullscreen mode Exit fullscreen mode

函数

命名函数

Kotlin 中的函数使用 `fun` 关键字声明。你需要为每个参数以及函数的返回类型添加类型注解。

JavaScript



function double(num) {
    return num * 2;
}
double(2); // 4


// Default values
function shout(message, postfix = "!!!") {
    return `${message.toUpperCase()}${postfix}`;
}
shout("hey"); // HEY!!!


Enter fullscreen mode Exit fullscreen mode

Kotlin



fun double(num:Int) {
    return num * 2
}

// Default values
fun shout(message: String, postfix = "!!!"): String {
    return "${message.toUpperCase()}$postfix"
}


Enter fullscreen mode Exit fullscreen mode

命名参数

在 Kotlin 中,调用函数时可以为函数参数命名。当函数具有大量参数或默认参数时,这非常方便。

Kotlin



fun reformat(str: String,
             normalizeCase: Boolean = true,
             upperCaseFirstLetter: Boolean = true,
             divideByCamelHumps: Boolean = false,
             wordSeparator: Char = ' ') {
    ... 
}

reformat("SomeString", normalizeCase = false, divideByCamelHumps = true)


Enter fullscreen mode Exit fullscreen mode

函数表达式(Lambda)

Lambda 表达式是“函数字面量”,即未声明的函数,而是直接作为表达式传递。在 JavaScript 中,它们通常被称为“箭头函数”,而在 Kotlin 中,则被称为“lambda 表达式”。

在 Kotlin 中,lambda 表达式始终用花括号括起来,参数的完整语法声明也放在花括号内,并且可以添加可选的类型注解,表达式主体放在一个->符号之后。注意:Kotlin 中不能为 lambda 表达式指定返回类型。大多数情况下,这没有必要,因为类型可以自动推断。

JavaScript



const double = (num) => num * 2; // Single line has implicit return

const square = (num) => {
    const result = num * num;
    return result; // Multi line: No implicit return
}


Enter fullscreen mode Exit fullscreen mode

Kotlin



val double = { num:Int -> num * 2 }

val square = { num: Int -> 
    val result = num * num
    // The last expression in a lambda is always considered the return value:
    result
}


Enter fullscreen mode Exit fullscreen mode

lambda 表达式通常只有一个参数。为了方便起见,Kotlin 会对这种情况进行特殊处理,并自动将该参数声明为 it:

JavaScript



const carModels = cars.map((car) => car.model );
const oldEnough = users.filter((user) => user.age >= 21 );


Enter fullscreen mode Exit fullscreen mode

Kotlin



val carModels = cars.map { it.model }
val oldEnought = users.filter { it.age >= 21 }


Enter fullscreen mode Exit fullscreen mode

流量控制

如果/否则

JavaScript



if (number > 0) {
    console.log("Positive number");
} else {
    console.log("Negative number");
}


Enter fullscreen mode Exit fullscreen mode

Kotlin



if (number > 0) {
    print("Positive number")
} else {
    print("Negative number")
}


Enter fullscreen mode Exit fullscreen mode

与 JavaScript(以及许多其他编程语言)不同,ifKotlin 中的表达式会返回一个值:

JavaScript



let result;
if (number > 0) {
    result = "Positive number";
} else {
    result = "Negative number";
}


Enter fullscreen mode Exit fullscreen mode

Kotlin



val result = if (number > 0) {
    "Positive number"
} else {
    "Negative number"
}


Enter fullscreen mode Exit fullscreen mode

在 Kotlin 中,如果代码写在一行中,可以省略花括号——因此没有三元运算符:

JavaScript



const result = number > 0 ? "Positive number" : "Negative number";


Enter fullscreen mode Exit fullscreen mode

Kotlin



val result = if (number > 0) "Positive number" else "Negative number"


Enter fullscreen mode Exit fullscreen mode

开关(何时)

Kotlin 有一个when可以被视为 JavaScriptswitch语句替代品的结构:

JavaScript



switch (selectedFruit) {
  case "orange":
    console.log("Oranges are 59 cents a pound.");
    break;
  case "apple":
    console.log("Apples are 32 cents a pound.");
    break;
  case "cherry":
    console.log("Cherries are one dollar a pound.");
    break;
  case "mango":
  case "papaya":
    console.log("Mangoes and papayas are 3 dollars a pound.");
    break;
  default:
    console.log(`Sorry, we are out of ${selectedFruit}.`);
}


Enter fullscreen mode Exit fullscreen mode

Kotlin



when(selectedFruit) {
    "orange" -> print("Oranges are 59 cents a pound.")
    "apple" -> print("Apples are 32 cents a pound.")
    "cherry" -> print("Cherries are one dollar a pound.")
    "mango", "papaya" -> print("Mangoes and papayas are 3 dollars a pound.")
    else -> print("Sorry, we are out of $selectedFruit.")
}


Enter fullscreen mode Exit fullscreen mode

实际上,Kotlin 的 Switchwhen功能远比这强大得多,许多人将其形容为“拥有超能力的 Switch”。以下是它的一些when优势:

  • 它可以作为一种表达方式
  • 它可以包含任意条件表达式
  • 它可以自动转换值。
  • 它可以不带论证使用。
  • 它可以用来要求穷尽所有可能的情况(所有可能的条件都需要满足)。

本文不会深入探讨 Kotlin 的语法when,但需要注意的是,它在代码编写中非常有用。如果您准备好了,可以参考这篇文章了解更多信息。


循环

Kotlin 确实提供了for循环,但它只能用于迭代器(例如 List 和 Map)。幸运的是,Kotlin 也提供了范围(range),即可以使用以下..运算符创建的迭代器:

JavaScript



for (let i = 1; i<=10; i++) {
    console.log(i);
}
// 1 2 3 4 5 6 7 8 9 10


const places = ["New York", "Paris", "Rio"];
for (const place of places) {
  console.log(`I Love ${place}`);
}
// I Love New York 
// I Love Paris
// I Love Rio


Enter fullscreen mode Exit fullscreen mode

Kotlin



for (i in 1..10) {
    print(i)
}
// 1 2 3 4 5 6 7 8 9 10


val places = listOf("New York", "Paris", "Rio")
for (place in places) {
    println("I Love $place")
}
// I Love New York 
// I Love Paris
// I Love Rio


Enter fullscreen mode Exit fullscreen mode

收藏

Kotlin 不提供集合字面量(例如数组的 [] 或对象的 {})。相反,它提供可用于创建集合的全局函数。这样做的理由是,如果语言提供集合字面量,就会影响用户使用集合的方式(进而影响用户使用语言本身的方式)。可变与不可变、列表与数组——Kotlin 赋予用户选择的自由。

数组(这里指的是“可以动态增长的内容列表……”)

“数组”是一个含义丰富的术语,在不同的编程语言中可以指代不同的东西——Kotlin 就是如此:它确实有数组,但它们与 JavaScript 数组并不相同(也就是说,它们不是可以动态增长或缩小的列表)。在这种情况下,更合适的集合是 List。

JavaScript



const houses = [ "Stark", "Lannister", "Tyrell", "Arryn", "Targaryen", "Baratheon" ];
houses[2]; // "Tyrell"
houses.push("Martell");
houses.length; //7


Enter fullscreen mode Exit fullscreen mode

Kotlin



val houses = mutableListOf("Stark", "Lannister", "Tyrell", "Arryn", "Targaryen", "Martell", "Baratheon")
houses[2] // "Tyrell"
houses.add("Martell")
houses.size //7


Enter fullscreen mode Exit fullscreen mode

对象(在本例中指的是“键值映射”)

JavaScript 中的对象用途广泛:它既是哈希表,也是除基本类型之外所有类型的基础构造(更不用说它还包含诸如 `Object.assign` 之类的实用方法)。既然我们正在讨论集合,我将以哈希表为例进行说明(存储键值对)。

JavaScript



const colors = {
  "red":  0xff0000,
  "green":  0x00ff00,
  "blue":  0x0000ff,
  "cyan":  0x00ffff,
  "magenta":  0xff00ff,
  "yellow":  0xffff00
};
colors.hasOwnProperty("yellow"); // true
colors.yellow; // 0xffff00


Enter fullscreen mode Exit fullscreen mode

Kotlin



val colors =  mutableMapOf(
  "red" to 0xff0000,
  "green" to 0x00ff00,
  "blue" to 0x0000ff,
  "cyan" to 0x00ffff,
  "magenta" to 0xff00ff,
  "yellow" to 0xffff00
)
colors.contains("yellow") // true
colors.get("yellow") // 0xffff00


Enter fullscreen mode Exit fullscreen mode

关于不变性的简要说明

Kotlin 还提供了其集合的只读版本:

Kotlin



// mapOf is the read-only version of mutableMapof
val colors =  mapOf(
  "red" to 0xff0000,
  "green" to 0x00ff00,
  "blue" to 0x0000ff
)
val updatedColors = colors.plus("teal" to 0x008080) // doesn't change the original - it returns a new map


// listOf is the read-only version of mutableListof
val houses = listOf("Stark", "Lannister", "Tyrell", "Arryn", "Targaryen", "Martell", "Baratheon")

// Methods that return a new list instead of modifying it are still available:
var updatedHouses = houses.take(3).map {it.toUpperCase()} //["STARK", "LANNISTER", "TYRELL"]

// Adding new items requires copying the whole original one and making sure the new copy is also immutable
var updatedHouses = houses.toMutableList().apply{ add("Martell") }.toList()


Enter fullscreen mode Exit fullscreen mode

解构任务

解构声明语法非常方便,可以节省一些代码:当你将一个集合赋值给一个值时,Kotlin 会将集合拆分并匹配,把右侧的值赋给左侧的变量。最简单的情况下,它可以用于并行赋值:

JavaScript



const coordinates = [5, 10, 15];
const [x, y, z] = coordinates;


Enter fullscreen mode Exit fullscreen mode

Kotlin



val coordinates = arrayOf(5, 10, 15)
val (x, y, z) = coordinates


Enter fullscreen mode Exit fullscreen mode

虽然上面的例子看起来有点傻,但这对于处理返回多个值的函数来说尤其方便:

JavaScript



function weatherReport(location) {
  // Make an Ajax request to fetch the weather...
  return [72, "Mostly Sunny"];
}
const [temp, forecast] = weatherReport("Berkeley, CA");


Enter fullscreen mode Exit fullscreen mode

Kotlin



fun weatherReport(location) {
  // Make an Ajax request to fetch the weather...
  return Pair(72, "Mostly Sunny") // Pair is a standard class in Kotlin that represents a generic pair of two values
}
val (temp, forecast) = weatherReport("Berkeley, CA")


Enter fullscreen mode Exit fullscreen mode

课程

与 JavaScript 类似,Kotlin 中的类也是使用关键字声明的class

JavaScript



class Monster {
  constructor(name, color, numEyes) {
    this.name = name;
    this.color = color;
    this.numEyes = numEyes;
  }
  speak(likes) {
      return `My name is ${this.name} and I like ${likes}`;
  }
}
var nhama = new Monster("Nhama", "red", 1);
nhama.speak("guacamole")
// "My name is Nhama and I like guacamole"


Enter fullscreen mode Exit fullscreen mode

Kotlin



class Monster(val name: String, val color: String, val numEyes: Int) {
  fun speak(likes: String):String {
      return "My name is $name and I like $likes"
  }
}
var nhama = Monster("Nhama", "red", 1)
// Kotlin doesn't have a `new` keyword - you instantiate a class by calling it directly
nhama.speak("guacamole")
// "My name is Nhama and I like guacamole"


Enter fullscreen mode Exit fullscreen mode

Kotlin 类也有构造函数,但如果您只想定义类属性,则可以省略该关键字。


数据容器

在 JavaScript 中,通常会创建普通对象来将命名值组合在一起。而在 Kotlin 中,你需要创建数据类——它们同样可以作为数据容器,但更轻量级,字段名称固定,并且类型更加严格。

JavaScript



const movie1 = {
    name: "Back to the Future",
    rating: 5,
    director: "Bob Zemeckis"
}
const movie2 = {
    name: "Star Wars: Episode IV - A New Hope",
    rating: 5,
    director: "George Lucas"
}


Enter fullscreen mode Exit fullscreen mode

Kotlin



data class Movie(
  val name: String, 
  val rating: Int, 
  val director: String
)
val movie1 = Movie("Back to the Future", 5, "Bob Zemeckis")
val movie2 = Movie("Star Wars: Episode IV - A New Hope", 5, "George Lucas")


Enter fullscreen mode Exit fullscreen mode

接下来该怎么办?

本文始终将 Kotlin 语法与 JavaScript 语法进行对比——然而,Kotlin 在某些方面采用了独特的处理方式,与 JavaScript 截然不同——最突出的例子就是 Kotlin 的空值处理方式。在本文的第二部分,我将介绍 Kotlin 的一些独特特性:空安全以及异步编程——敬请期待。

文章来源:https://dev.to/cassiozen/kotlin-for-js-devs-part-1-5bld