虽然说Koishi的插件市场已经十分丰富,能够满足我们大部分的需求,但仍然存在一些个性化的功能,需要我们自己动手写作,丰衣足食。所以接下来这几节会教授编程的基础以及怎么进行插件开发。
编程基础
接下来的部分会讲的非常的详尽,大抵是不用担心听不懂。如果实在觉得存在困难,可以在同好群中寻求帮助或者联系群主或者管理一对一辅导,以及也可以前往Runoob JS教程进行学习,上面有更加详尽的教程。
背景知识
我们现在需要了解的编程背景知识是:
- 我们将使用Javascript以及Typescript进行编程。
- Typescript是Javascript的一个超集,支持更加丰富的功能,同样也意味着Javascript的代码交给Typescript完全能运行。底层原理是,Typescript的编译器会将Typescript代码翻译成Javascript代码再执行。
- 之后Typescript简称TS,Javascript简称JS。
- JS是一门面向对象语言,程序运行的底层逻辑更加关心对象之间的关联、从属、继承关系,从而达到完成任务的目的。相反的,面向过程语言(比如说C语言)关心的是一件事可以拆解成若干个步骤去完成。
环境配置
我们可以先在电脑上安装一下编程环境,包括Node.js和任何一个支持Javascript的IDE,这里推荐VS Code。
- Node.js网址:https://nodejs.org/zh-cn/download
- VS Code网址:https://code.visualstudio.com/

我们打开VS Code(下简称vsc)后会出现如上界面。我们直接点击File->Open Folder,在弹出的窗口中创建一个文件夹用来学习JS基础。

出现以上窗口时,勾选并点击蓝色按钮即可。

上图为我们开发时界面。左侧是资源管理器,用来查看我们存放代码和运行时环境的文件夹,中间是我们写代码的地方,右侧是Copilot,一个专门为编程服务的AI助手。如果需要使用Copilot可以根据上图Welcome页的指引,或者寻求群友或管理的帮助。
JS基础
接下来关闭Welcome页与Copilot,右键资源管理器,点击New File,名称叫做index.js,其中index是文件名,js是JS的源码文件后缀。
初识 JS 之 Hello World
我们输入以下代码:
console.log("Hello World!")

随后按Ctrl+S(Mac下为Command+S)保存文件

点击Terminal->New Terminal新建终端

输入并回车,node指令表示运行JS源代码文件:
node index.js

我们会发现在控制台终端中输出了 Hello World。代码中console.log是一个函数。函数在之前的文章中提到过,是封装了某些功能的工具。而这个函数的作用是在控制台中输出一段文本,括号中代表了函数的参数,参数是由逗号进行隔开的。通常来说,函数会规定它的参数个数,有可能是一个,或者有限个,也有可能是无限个。console.log可以接受无限个参数,表示需要输出的内容,他们在控制台中会以空格进行分割,如下图:

JS 速通 #1
接下来会以尽量清晰,以及尽量短的篇幅介绍我们目前来说最常用的JS功能。
变量的声明
let a=5
console.log(a)
let b=a+3
console.log(a+b+4)
a="你好"
console.log(a)
运行结果是:
PS D:\code\js-learning> node index.js
5
17
你好
上面即为变量的声明方式。变量使用let 来声明,我们可以使用let =[初始值]来对变量进行初始化。其中 = 为赋值符号,请留意这一点,意义为将右侧的值(简称右值或者rv)复制到左侧的变量(简称左值或者lv)上。变量名只可以包含字母数字下划线,并且只能以下划线或者字母开头。
变量有许多类型,在JS中有数字(Number),字符串(String),数组(Array),对象(Object),函数(Function),布尔(Boolean,储存真或者假的类型),空(Null),未定义(Undefined)等等。而以上的一切类型都继承于Object,可以说对象是整个JS的基础,后面会详细教学面向对象编程。
JS拥有动态类型,你可以一个变量初始化为一个类型,比如说数字,后续可以赋值为任何你想要的类型。
可以用typeof获取变量的数据类型,下面例子引用自Runoob:
typeof "John" // 返回 string
typeof 3.14 // 返回 number
typeof false // 返回 boolean
typeof [1,2,3,4] // 返回 object
typeof {name:'John', age:34} // 返回 object 这是Javascript的设计缺陷,这其实是array
变量的运算 & 注释的使用
JS有许多类型的运算符,比如 = + - * / ( ),这些是进行运算的。其中 + 比较特殊,比如说,我们不仅可以对数字进行相加,比如说1+2=3,还可以对字符串进行相加,比如说"1"+"2"="12";还有一些如== != 是对值进行比较的,比如== 为判断相等,!= 为判断不等。所以再次声明,需要注意运算符=和运算符==的区别!下面为运算符以及注释的示例:
//用两个斜杠可以写单行注释
let a=1+2 //也可以跟在行结尾
// 以及我们习惯性会在双斜杠后面跟一个空格以达到美观
// 空行不会影响代码运行
/*
这是多行注释
这是多行注释
*/
// 接下来会在log语句后写这一行运行的答案以便对照
console.log(a) // 3
a="abc"+'abc'
console.log(a) // 'abcabc'
a=1==2
console.log(a) // false
let 中文=1 // 不要写中文名称的变量!!!
常量
常量顾名思义,不可改变的量。我们可以用常量去储存一些常用字面量,比如说在计算圆的面积时可以声明一个PI常量:
const PI=3.14 // 常量的声明
let r=5
console.log(PI*r**2) // 78.5
// 其中**是幂运算符
字符串
"abc"
'abc' // 单引号双引号引起来都是字符串
"'abc'" // 表示字符串'abc' 可以用A引号包含B引号来在字符串中包含B引号
// 不要使用中文引号,无法识别
let a=30
let b=`老王今年:
${a}`
console.log(b) // 老王今年30
// 可以用反引号(即大键盘数字键左侧)包含表达式(比如说一个变量)以及可以包含换行
console.log(b.length) // 6 这是字符串长度
console.log("\n") // 这是换行符\n
函数
function cmp(a,b){
return a<b;
}
/*
具名函数声明格式
function 函数名(参数){
函数体
}
return 代表函数的返回值
*/
console.log(cmp(1,2)) // true
let func=function(a,b){
console.log(a,b);
}
/*
具名函数也可以这样声明
函数也可以没有返回值
*/
let func1=(a,b)=>{
console.log(`这是匿名函数: ${a+b}`)
}
// 匿名函数又称箭头函数,格式为: (参数)=>{函数体}
// 匿名函数在代码写作方面是一种简便写法
// 不要在对象中使用箭头函数,否则将不能使用this,后面会讲解
对象
对象描述一个事物的属性和方法。
let person = {
name: "张三",
age: 18,
speak: function(){
console.log(`我叫
${this.name}`);
// 语句后 可以且推荐 跟一个分号,这是别的语言留下的好习惯
}
};
console.log(person.name); // '张三'
console.log(person["age"]); // 18
let varName = "age"
console.log(person[varName]); // 18
person.speak(); // '我叫张三'
console.log(person.speak); // [Function: speak] 在浏览器环境中会有不同的行为
我们使用大括号包含一些属性和方法(函数),这些属性可以是数字,字符串等等。其中,this指向外层定义域,比如说上面这个例子的this指向的就是person,所以输出的是person.name的值。
访问对象的属性有两种方法,一个是静态访问,比如说person.name,即在代码中写死需要访问的属性名;一个是动态访问,比如说可以根据字面量或者变量的值来确定访问的是什么属性,如上面例子中的person[varName]。
访问对象的方法,加了括号表示调用,会返回这个函数的返回值;不加括号会将一个定义函数的字符串返回。
条件语句
let x = 2;
// if / else if / else:按条件分支执行
if (x > 3) console.log("大");
else if (x === 3) console.log("等于3");
else console.log("小");
// switch:多分支判断,匹配 case 值
switch (x) {
case 1: console.log("一"); break; // break 跳出 switch
case 2: console.log("二"); break;
default: console.log("其他");
}
循环语句
// for(初始化; 条件; 更新)
// 三个部分用分号隔开:
// 1. 初始化:循环开始前执行一次(如定义计数变量)
// 2. 条件:每次循环前判断是否继续
// 3. 更新:每次循环体执行完后执行(通常 i++)
for (let i = 0; i < 3; i++) console.log(i); // 输出 0 1 2
// for...in:遍历对象的键(属性名)
let obj = {a:1, b:2};
for (let key in obj) console.log(key); // a b
// for...of:遍历可迭代对象的值(数组、字符串等)
let arr = [10, 20, 30];
for (let v of arr) console.log(v); // 10 20 30
// break:立即结束整个循环
// continue:跳过本次循环,继续下一次
for (let i = 0; i < 5; i++) {
if (i === 2) continue; // 跳过 2
if (i === 4) break; // 停止循环
console.log(i); // 输出 0 1 3
}
// while(条件)
// 先判断条件,true 时执行循环体;false 时结束循环
let i = 0;
while (i < 3) { // 判断 i<3
console.log(i); // 输出 0 1 2
i++; // 更新变量,防止死循环
}
// do...while(条件)
// 先执行一次循环体,再判断条件(至少执行一次)
let j = 0;
do {
console.log(j); // 先执行,再判断
j++;
} while (j < 3); // 条件为 true 继续,false 结束
类型强制转换
// 类型转换:不同类型间自动或手动变换
// 自动转换(隐式)
console.log(1 + "2"); // "12" 数字转字符串
console.log("5" * 2); // 10 字符串转数字
// 手动转换(显式)
console.log(Number("3")); // 3 转数字
console.log(String(4)); // "4" 转字符串
console.log(Boolean(0)); // false 转布尔
作用域
作用域:变量能被访问的范围。
- 全局作用域:任何地方都能访问。
- 函数作用域:函数内部定义的变量只在函数内有效。
- 块级作用域:
let、const在{}内有效。 - 作用域链:访问变量时,逐层向外查找。
let a = 1; // 全局作用域
function f() { // 函数作用域
let b = 2;
if (true) {
let c = 3; // 块级作用域
console.log(a, b, c); // 1 2 3
}
// console.log(c); // 报错:c 未定义
}
f();
// 作用域链
let a = 1;
function f1() {
let a = 2; // 覆盖外层同名变量
function f2() {
let a = 3; // 再次覆盖
console.log(a); // 输出 3,优先使用最近的作用域
}
f2();
}
f1();
console.log(a); // 输出 1,全局的 a 不受影响
最后
作者困了,速通 #2 明天再写。若有笔误请海涵,熬夜脑子不太清醒。

Comments NOTHING