Minecraft(我的世界)中文论坛

 找回密码
 注册(register)

!header_login!

只需一步,立刻登录

查看: 2029|回复: 17

[教程] [原创][NPS] Nukkit模组 零基础入门到精通

[复制链接]
幻影影 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
4389
钻石
性别
保密
注册时间
2017-11-14
查看详细资料
发表于 2018-8-17 06:53:45 | 显示全部楼层
JS文件吗! JS不是Nukkit吧 是原版MOD
回复

使用道具 举报

wode490390 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
7841
钻石
性别
保密
注册时间
2014-6-21
查看详细资料
发表于 2018-8-17 07:02:17 | 显示全部楼层 |阅读模式

您尚未登录,立即登录享受更好的浏览体验!

您需要 登录 才可以下载或查看,没有帐号?注册(register)

x
本帖最后由 wode490390 于 2018-10-12 02:33 编辑
排版后期再优化吧,有误请指出,部分内容参考MDN

§0 入坑准备

§0.1 服务端环境

需要插件:http://www.mcbbs.net/thread-813311-1-1.html

§0.2 开发环境

任意文本编辑器

小项目推荐用Notepad++:http://notepad-plus-plus.org/download/

§1 ECMAScript 语言

目前的NK模组加载器可能不兼容部分高级JS语法,请自行测试。

Q:目前暂时不支持的语法为什么还要写在帖内呢?
A:未来新版本的模组加载器可能会支持,所以先写在帖子内。

如果你对JavaScript已经了解,可以跳过本大章节内容。

§1.1 变量

声明变量

  1. var 变量a;
复制代码


行末的分号表示语句结束

另外大小写敏感,以下例子声明了两个不同的变量

  1. var 变量a;
  2. var 变量A;
复制代码


定义一个变量之后,你可以赋予它一个值:

  1. 变量a = '我是变量';
复制代码


你也可以将这些操作写在同一行:

  1. var 变量a = '我是变量';
复制代码


你可以通过变量名称读取变量的值:

  1. 变量a;
复制代码


在给变量赋值之后,你可以更改这个变量的值:

  1. var 变量a = '我是变量';
  2. 变量a = '吾乃变量也';
复制代码


§1.1.1 var 变量

  1. var 变量1 [= 值1 [, 变量2 [, 变量3 ... [, 变量N]]]];
复制代码


变量声明,无论发生在何处,都在执行任何代码之前进行处理。用var声明的变量的作用域是它当前的执行上下文,它可以是嵌套的函数,也可以是声明在任何函数外的变量。如果你重新声明一个 JavaScript 变量,它将不会丢失其值。

将赋值给未声明变量的值在执行赋值时将其隐式地创建为全局变量(它将成为全局对象的属性)。声明和未声明变量之间的差异是:

1. 声明变量的作用域限制在其声明位置的上下文中,而非声明变量总是全局的。

  1. function x() {
  2.   y = 1;
  3.   var z = 2;
  4. }
  5. x();
  6. console.log(y); // 打印"1" 。
  7. console.log(z); // 抛出ReferenceError: z未在x外部声明。
复制代码


2. 声明变量在任何代码执行前创建,而非声明变量只有在执行赋值操作的时候才会被创建。

  1. console.log(a);                // 抛出ReferenceError。
  2. console.log('still going...'); // 永不执行。
复制代码

  1. var a;
  2. console.log(a);                // 打印"undefined"或"")。
  3. console.log('still going...'); // 打印"still going..."。
复制代码


3. 声明变量是它所在上下文环境的不可配置属性,非声明变量是可配置的(如非声明变量可以被删除)。

  1. var a = 1;
  2. b = 2;
  3. delete this.a;
  4. delete this.b;
  5. console.log(a, b); // 抛出ReferenceError。
  6. // 'b'属性已经被删除。
复制代码


由于这三个差异,未能声明变量将很可能导致意想不到的结果。因此,建议始终声明变量,无论它们是在函数还是全局作用域内。

§1.1.1.1 变量提升

由于变量声明(以及其他声明)总是在任意代码执行之前处理的,所以在代码中的任意位置声明变量总是等效于在代码开头声明。这意味着变量可以在声明之前使用,这个行为叫做“hoisting”。“hoisting”就像是把所有的变量声明移动到函数或者全局代码的开头位置。

  1. bla = 2
  2. var bla;
  3. // ...
  4. // 可以理解为:
  5. var bla;
  6. bla = 2;
复制代码


因此,建议始终在作用域顶部声明变量(全局代码的顶部和函数代码的顶部),这可以清楚知道哪些变量是函数作用域(本地),哪些变量在作用域链上解决。

重要的是,提升将影响变量声明,而不会影响其值的初始化。当到达赋值语句时,该值将确实被分配:

  1. function do_something() {
  2.   console.log(bar); // undefined
  3.   var bar = 111;
  4.   console.log(bar); // 111
  5. }
  6. // is implicitly understood as:
  7. function do_something() {
  8.   var bar;
  9.   console.log(bar); // undefined
  10.   bar = 111;
  11.   console.log(bar); // 111
  12. }
复制代码


§1.1.1.2 例子

声明并初始化两个变量:

  1. var a = 0, b = 0;
复制代码


给两个变量赋值成字符串值:

  1. var a = "A";
  2. var b = a;
  3. // 等效于:
  4. var a, b = a = "A";
复制代码


留意其中的顺序:

  1. var x = y, y = 'A';
  2. console.log(x + y); // undefinedA
复制代码


在这里,x和y在代码执行前就已经创建了,而赋值操作发生在创建之后。当"x = y"执行时,y已经存在,所以不抛出ReferenceError,并且它的值是'undefined'。所以x被赋予 undefined 值。然后,y被赋予'A'。于是在执行完第一行之后,x === undefined && y === 'A'才出现了这样的结果。

多个变量的初始化

  1. var x = 0;
  2. function f(){
  3.   var x = y = 1; // x在函数内部声明,y不是!
  4. }
  5. f();
  6. console.log(x, y); // 0, 1
  7. // x是全局变量。
  8. // y是隐式声明的全局变量。
复制代码


隐式全局变量和外部函数作用域

看起来像是隐式全局作用域的变量也有可能是其外部函数变量的引用。

  1. var x = 0;  // x是全局变量,并且赋值为0。
  2. console.log(typeof z); // undefined,因为z还不存在。
  3. function a() { // 当a被调用时,
  4.   var y = 2;   // y被声明成函数a作用域的变量,然后赋值成2。
  5.   console.log(x, y);   // 0 2
  6.   function b() {       // 当b被调用时,
  7.     x = 3;  // 全局变量x被赋值为3,不生成全局变量。
  8.     y = 4;  // 已存在的外部函数的y变量被赋值为4,不生成新的全局变量。
  9.     z = 5;  // 创建新的全局变量z,并且给z赋值为5。
  10.   }         // (在严格模式下(strict mode)抛出ReferenceError)
  11.   b();     // 调用b时创建了全局变量z。
  12.   console.log(x, y, z);  // 3 4 5
  13. }
  14. a();                   // 调用a时同时调用了b。
  15. console.log(x, z);     // 3 5
  16. console.log(typeof y); // undefined,因为y是a函数的本地(local)变量。
复制代码


§1.1.2 let 局部变量

let 语句声明一个块级作用域的本地变量,并且可选的将其初始化为一个值。

  1. let 变量A [= 值1] [, 变量2 [= 值2]] [, ..., 变量N [= 值N]];
复制代码

  1. var a = 1;
  2. var b = 2;
  3. if (a === 1) {
  4.   var a = 11; // the scope is global
  5.   let b = 22; // the scope is inside the if-block
  6.   console.log(a);  // 11
  7.   console.log(b);  // 22
  8. }
  9. console.log(a); // 11
  10. console.log(b); // 2
复制代码


let允许你声明一个作用域被限制在块级中的变量、语句或者表达式。与var关键字不同的是,它声明的变量只能是全局或者整个函数块的。

  1. function varTest() {
  2.   var x = 1;
  3.   if (true) {
  4.     var x = 2;  // 同样的变量!
  5.     console.log(x);  // 2
  6.   }
  7.   console.log(x);  // 2
  8. }
  9. function letTest() {
  10.   let x = 1;
  11.   if (true) {
  12.     let x = 2;  // 不同的变量
  13.     console.log(x);  // 2
  14.   }
  15.   console.log(x);  // 1
  16. }
复制代码


在程序或者函数的顶层,let并不会像var一样在全局对象上创造一个属性,比如:

  1. var x = 'global';
  2. let y = 'global';
  3. console.log(this.x); // "global"
  4. console.log(this.y); // undefined
复制代码


§1.1.3 const 常量

常量是块级作用域,很像使用 let 语句定义的变量。常量的值不能通过重新赋值来改变,并且不能重新声明。

  1. const 常量1 = 值1 [, 常量2 = 值2 [, ... [, 常量N = 值N]]];
复制代码


此声明创建一个常量,其作用域可以是全局或本地声明的块。 与var变量不同,全局常量不会变为窗口对象的属性。需要一个常数的初始化器;也就是说,您必须在声明的同一语句中指定它的值(这是有道理的,因为以后不能更改)。

const声明创建一个值的只读引用。但这并不意味着它所持有的值是不可变的,只是变量标识符不能重新分配。例如,在引用内容是对象的情况下,这意味着可以改变对象的内容(例如,其参数)。

关于“暂存死区”的所有讨论都适用于let和const。

一个常量不能和它所在作用域内的其他变量或函数拥有相同的名称。

示例:

  1. // 注意: 常量在声明的时候可以使用大小写,但通常情况下全部用大写字母。
  2. // 定义常量MY_FAV并赋值7
  3. const MY_FAV = 7;
  4. // 报错
  5. MY_FAV = 20;
  6. // 输出 7
  7. console.log("my favorite number is: " + MY_FAV);
  8. // 尝试重新声明会报错
  9. const MY_FAV = 20;
  10. //  MY_FAV 保留给上面的常量,这个操作会失败
  11. var MY_FAV = 20;
  12. // 也会报错
  13. let MY_FAV = 20;
  14. // 注意块范围的性质很重要
  15. if (MY_FAV === 7) {
  16.     // 没问题,并且创建了一个块作用域变量 MY_FAV
  17.     // (works equally well with let to declare a block scoped non const variable)
  18.     let MY_FAV = 20;
  19.     // MY_FAV 现在为 20
  20.     console.log('my favorite number is ' + MY_FAV);
  21.     // 这被提升到全局上下文并引发错误
  22.     var MY_FAV = 20;
  23. }
  24. // MY_FAV 依旧为7
  25. console.log("my favorite number is " + MY_FAV);
  26. // 常量要求一个初始值
  27. const FOO; // SyntaxError: missing = in const declaration
  28. // 常量可以定义成对象
  29. const MY_OBJECT = {"key": "value"};
  30. // 重写对象和上面一样会失败
  31. MY_OBJECT = {"OTHER_KEY": "value"};
  32. // 对象属性并不在保护的范围内,下面这个声明会成功执行
  33. MY_OBJECT.key = "otherValue";
  34. // 也可以用来定义数组
  35. const MY_ARRAY = [];
  36. // It's possible to push items into the array
  37. // 可以向数组填充数据
  38. MY_ARRAY.push('A'); // ["A"]
  39. // 但是,将一个新数组赋给变量会引发错误
  40. MY_ARRAY = ['B']
复制代码


§1.2 数据类型

变量解释示例
String字符串(文字序列)。 要表示变量的值是字符串,你必须将它们用引号包裹起来。var myVariable = 'Bob';
Number数字。不用引号包围。var myVariable = 10;
Boolean布尔(逻辑)值。一个 True/False (真 / 假)值。 true/false 是 JS 里的特殊关键字,不需要引号。var myVariable = true;
Array数组,一种允许你存储多个值在一个引用里的结构。var myVariable = [1,'Bob','Steve',10];
Object对象,基本上 JavaScript 里的任何东西都是对象,而且都可以被储存在变量里。上面所有示例都是对象。


§1.3 注释

单行注释(//)

  1. //我被注释了
  2. var 变量 = '我被声明了';//我被注释了
复制代码


多行注释(/**/)

  1. /*我被注释了
  2. 我也被//注释了
  3. /*我亦被注释了//
  4. */
复制代码


§1.4 运算

运算符解释符号
加/连接/正数值求和或者字符串拼接。亦可以作正号。+
减/负使两个操作数相减,结果是它们的差值。亦可以作负号。-
结果是操作数的乘积。*
结果是操作数的商 ,左操作数是被除数,右操作数是除数。/
赋值基于右值给左值赋值。=
如果原本的值是 true 则返回 false ,反之亦然。!
求余返回第一个操作数对第二个操作数的模。%
返回第一个操作数做底数,第二个操作数做指数的乘方。**
递增为其操作数增加1,返回一个数值。++
递减将其操作数减去1,并返回一个数值。--


§1.4.1 加法 (+)

加法运算符的作用是数值求和,或者字符串拼接。

  1. // Number + Number -> 数字相加
  2. 1 + 2 // 3
  3. // Boolean + Number -> 数字相加
  4. true + 1 // 2
  5. // Boolean + Boolean -> 数字相加
  6. false + false // 0
  7. // Number + String -> 字符串连接
  8. 5 + "foo" // "5foo"
  9. // String + Boolean -> 字符串连接
  10. "foo" + false // "foofalse"
  11. // String + String -> 字符串连接
  12. "foo" + "bar" // "foobar"
复制代码


§1.4.2 减法 (-)

减法运算符使两个操作数相减,结果是它们的差值。

  1. 5 - 3 // 2
  2. 3 - 5 // -2
  3. "foo" - 3 // NaN
复制代码


§1.4.3 除法 (/)

除法运算符的结果是操作数的商 ,左操作数是被除数,右操作数是除数。

  1. 1 / 2      // 在 JavaScript 中返回 0.5
  2. 1 / 2      // 在 Java 中返回 0
  3. // (不需要数字是明确的浮点数)
  4. 1.0 / 2.0  // 在 JavaScript 或 Java 中都返回 0.5
  5. 2.0 / 0    // 在 JavaScript 中返回 Infinity
  6. 2.0 / 0.0  // 同样返回 Infinity
  7. 2.0 / -0.0 // 在 JavaScript 中返回 -Infinity
复制代码


§1.4.4 乘法 (*)

乘法运算符的结果是操作数的乘积。

  1. 2 * 2 // 4
  2. -2 * 2 // -4
  3. Infinity * 0 // NaN
  4. Infinity * Infinity // Infinity
  5. "foo" * 2 // NaN
复制代码


§1.4.5 求余 (%)

求余运算符返回第一个操作数对第二个操作数的模,即 var1 对 var2 取模,其中 var1 和 var2 是变量。取模功能就是 var1 除以 var2 的整型余数。

  1. 12 % 5 // 2
  2. -1 % 2 // -1
  3. NaN % 2 // NaN
  4. 1 % 2 // 1
  5. 2 % 3 // 2
  6. -4 % 2 // -0
  7. 5.5 % 2 // 1.5
复制代码


§1.4.6 幂 (**)

幂运算符返回第一个操作数做底数,第二个操作数做指数的乘方。即, var1var2 ,其中 var1 和 var2 是其两个操作数。幂运算符是右结合的。a ** b ** c 等同于 a ** (b ** c)。

  1. 2 ** 3 // 8
  2. 3 ** 2 // 9
  3. 3 ** 2.5 // 15.588457268119896
  4. 10 ** -1 // 0.1
  5. NaN ** 2 // NaN
  6. 2 ** 3 ** 2 // 512
  7. 2 ** (3 ** 2) // 512
  8. (2 ** 3) ** 2 // 64
复制代码


如果要反转求幂表达式结果的符号,你可以采用这样的方式:

  1. -(2 ** 2) // -4
复制代码


强制求幂表达式的基数为负数:

  1. (-2) ** 2 // 4
复制代码


§1.4.7 递增 (++)

递增运算符为其操作数增加1,返回一个数值。

  • 如果后置(postfix)使用,即运算符位于操作数的后面(如 x++),那么将会在递增前返回数值。
  • 如果前置(prefix)使用,即运算符位于操作数的前面(如 ++x),那么将会在递增后返回数值。


  1. // 后置
  2. var x = 3;
  3. y = x++;
  4. // y = 3, x = 4
  5. // 前置
  6. var a = 2;
  7. b = ++a;
  8. // a = 3, b = 3
复制代码


§1.4.8 递减 (--)

递减运算符将其操作数减去1,并返回一个数值。

  • 如果后置使用(如 x--),则在递减前返回数值。
  • 如果前置使用(如 --x),则在递减后返回数值。


  1. // 后置
  2. var x = 3;
  3. y = x--; // y = 3, x = 2
  4. // 前置
  5. var a = 2;
  6. b = --a; // a = 1, b = 1
复制代码


§1.4.9 一元负号 (-)

一元负号运算符位于操作数前面,并转换操作数的符号。

  1. var x = 3;
  2. y = -x; // y = -3, x = 3
复制代码


§1.4.10 一元正号 (+)

一元正号运算符位于其操作数前面,计算其操作数的数值,如果操作数不是一个数值,会尝试将其转换成一个数值。 尽管一元负号也能转换非数值类型,但是一元正号是转换其他对象到数值的最快方法,也是最推荐的做法,因为它不会对数值执行任何多余操作。它可以将字符串转换成整数和浮点数形式,也可以转换非字符串值 true,false 和 null。小数和十六进制格式字符串也可以转换成数值。负数形式字符串也可以转换成数值(对于十六进制不适用)。如果它不能解析一个值,则计算结果为 NaN.

  1. +3     // 3
  2. +"3"   // 3
  3. +true  // 1
  4. +false // 0
  5. +null  // 0
  6. +function(val){ return val;} //NaN
复制代码


§1.4.11 非




§1.5 比较

有两种比较方式:严格比较运算符和转换类型比较运算符。对于严格比较运算符(===)来说,仅当两个操作数的类型相同且值相等为 true,而对于被广泛使用的比较运算符(==)来说,会在进行比较之前,将两个操作数转换成相同的类型。对于关系运算符(比如 <=)来说,会先将操作数转为原始值,使它们类型相同,再进行比较运算。

比较符解释符号示例
大于大于运算符仅当左操作数大于右操作数时返回true>4 > 3; // true
大等大于等于运算符当左操作数大于或等于右操作数时返回true>=3 >= 3; // true
小于小于运算符仅当左操作数小于右操作数时返回true<3 < 4; // true
小等小于等于运算符当左操作数小于或等于右操作数时返回true<=3 <= 4; // true
相等测试两个是否相等,返回一个 true/false (布尔型)值。==1 == 2;
全等测试两个值与类型是否相等,返回一个 true/false (布尔型)值。==="3" === 3;
不等测试两个是否不等,返回一个 true/false (布尔型)值。!="4" != 4;
不全等测试两个值与类型是否不等,返回一个 true/false (布尔型)值。!==5 !== "5";


§1.6 条件句

条件句是能够让你测试一个表达式是否返回 true 然后根据结果运行不同的代码的代码结构。

§1.6.1 if

  1. if ('对象' == '对象') {
  2.     变量A = "变量1";
  3. }
复制代码


§1.6.2 if...else

  1. if (false) {
  2.     变量B = "变量2";
  3. } else {
  4.     变量B = "变量3";
  5. }
复制代码


§1.6.3 if...else if...else

  1. if ('变量n' == 5) {
  2.     变量C = "变量4";
  3. } else if (5 === '5') {
  4.     变量C = "变量5";
  5. } else {
  6.     变量C = "变量6";
  7. }
复制代码


§1.7 switch...case...break...default

判断句评估一个表达式,将表达式的值与case子句匹配,并执行与该情况相关联的语句。

  1. switch (expression) {
  2.   case value1:
  3.     // 当 expression 的结果与 value1 匹配时,执行此处语句
  4.     [break;]
  5.   case value2:
  6.     // 当 expression 的结果与 value2 匹配时,执行此处语句
  7.     [break;]
  8.   ...
  9.   case valueN:
  10.     // 当 expression 的结果与 valueN 匹配时,执行此处语句
  11.     [break;]
  12.   [default:
  13.     // 如果 expression 与上面的 value 值都不匹配时,执行此处语句
  14.     [break;]]
  15. }
复制代码


expression:一个用来与 case 子语句匹配的表达式。

case valueN(可选):用于匹配 expression 的 case 子句。如果 expression 与给定的 valueN 相匹配,则执行该 case 子句中的语句直到该 switch 语句结束或遇到一个 break 。

default(可选):一个 default 子句;如果给定,这条子句会在 expression 的值与任一 case 语句均不匹配时执行。default 可以放到 case 之间。

  1. switch (expr) {
  2.   case '1':
  3.     变量a = 1;
  4.     break;
  5.   case '2':
  6.   case '3':
  7.     变量a = 3;
  8.     break;
  9.   default:
  10.     变量a = 0;
  11. }
复制代码


一个 switch 语句首先会计算其 expression 。然后,它将从第一个 case 子句开始直到寻找到一个其表达式值与所输入的 expression 的值所相等的子句(使用 严格运算符,===)并将控制权转给该子句,执行相关语句。(如果多个 case 与提供的值匹配,则选择匹配的第一个 case,即使这些 case 彼此间并不相等。)如果没有 case 子句相匹配,程序则会寻找那个可选的 default 子句,如果找到了,将控制权交给它,执行相关语句。若没有 default 子句,程序将继续执行直到 switch 结束。按照惯例,default 子句是最后一个子句,不过也不需要这样做。

可选的 break 语句确保程序立即从相关的 case 子句中跳出 switch 并接着执行 switch 之后的语句。若 break 被省略,程序会继续执行 switch 语句中的下一条语句。

如果你忘记添加break,那么代码将会从值所匹配的 case 语句开始运行,然后持续执行下一个 case 语句而不论值是否匹配。

§1.8 循环

循环可以将代码重复运行。

§1.8.1 for

用于创建一个循环,它包含了三个可选的表达式,三个可选的表达式包围在圆括号中并由分号分隔, 后跟一个在循环中执行的语句(通常是一个块语句)。

  1. for ([initialization]; [condition]; [final-expression])
  2.    statement
复制代码


initialization:一个表达式 (包含赋值语句) 或者变量声明。典型地被用于初始化一个计数器。该表达式可以使用var关键字声明新的变量。初始化中的变量不是该循环的局部变量,而是与for循环处在同样的作用域中。该表达式的结果无意义。

condition:一个条件表达式被用于确定每一次循环是否能被执行。如果该表达式的结果为true, statement 将被执行。 这个表达式是可选的。如果被忽略,那么就被认为永远为真。如果计算结果为假,那么执行流程将被跳到for语句结构后面的第一条语句。

final-expression:每次循环的最后都要执行的表达式。执行时机是在下一次condition的计算之前。通常被用于更新或者递增计数器变量。

statement:只要condition的结果为true就会被执行的语句。 要在循环体内执行多条语句,使用一个块语句({ ... })来包含要执行的语句。没有任何语句要执行,使用一个空语句(;)。

以下例子声明了变量i并被初始赋值为0,for语句检查i的值是否小于9,如果小于9,则执行语句块内的语句,并且最后将i的值增加 1。

  1. for (var i = 0; i < 9; i++) {
  2.    变量A = i;
  3.    // more statements
  4. }
复制代码


for语句的所有的表达式都是可选的

例如,初始化块中的表达式没有被指定:

  1. var i = 0;
  2. for (; i < 9; i++) {
  3.     变量A = i;
  4.     // more statements
  5. }
复制代码


像初始化块一样,条件块也是可选的。如果省略此表达式,则必须确保在循环体内跳出,以防创建死循环。

  1. for (var i = 0;; i++) {
  2.     变量A = i;
  3.    if (i > 3) break;
  4.    // more statements
  5. }
复制代码


你当然可以忽略所有的表达式。同样的,确保使用了break语句来跳出循环并且还要修改(增加)一个变量,使得break 语句的条件在某个时候是真的。

  1. var i = 0;
  2. for (;;) {
  3.   if (i > 3) break;
  4.   变量A = i;
  5.   i++;
  6. }
复制代码


for允许无语句,但循环条件后的分号是强制性的。如果没有分号,循环声明之后的行将被视为语句。

  1. var 变量B = 3,变量c = "笑";
  2. for (
  3.     var 变量a = "哈";
  4.       变量B;
  5.     变量c +=  变量a
  6.   );
  7. var 变量D = "最终的变量c为:" + 变量c; //笑哈哈哈
  8. }
复制代码


§1.8.2 for...in

for...in语句以任意顺序遍历一个对象的可枚举属性。对于每个不同的属性,语句都会被执行。

  1. var obj = {a:1, b:2, c:3};
  2.    
  3. for (var prop in obj) {
  4.   console.log("obj." + prop + " = " + obj[prop]);
  5. }
  6. // Output:
  7. // "obj.a = 1"
  8. // "obj.b = 2"
  9. // "obj.c = 3"
复制代码


§1.8.3 for...of

for...of语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句

  1. function* foo(){
  2.   yield 1;
  3.   yield 2;
  4. }
  5. for (let o of foo()) {
  6.   console.log(o);
  7.   // expected output: 1
  8.   break; // closes iterator, triggers return
  9. }
复制代码


§1.8.4 while

while 语句可以在某个条件表达式为真的前提下,循环执行指定的一段代码,直到那个表达式不为真时结束循环。

  1. while (condition) {
  2.   statement
  3. }
复制代码


§1.9 函数

函数声明定义一个具有指定参数的函数。

  1. function 函数名a([参数名1,[,参数名2,[..., 参数名n]]]) {
  2.   //do sth..
  3. }
复制代码


参数是有限的。

你也可以使用 Function 构造函数和一个函数声明来定义函数。

  1. var 函数表达式 = function 函数名B([参数名1,[,参数名2,[..., 参数名n]]]) {
  2.   //do sth..
  3. };
复制代码


函数可以被有条件来声明,这意味着,在一个 if 语句里,函数声明是可以嵌套的。有的浏览器会将这种有条件的声明看成是无条件的声明,无论这里的条件是true还是false,浏览器都会创建函数。因此,它们不应该被使用。

默认情况下,函数是返回 undefined 的。想要返回一个其他的值,函数必须通过一个 return 语句指定返回值。

下面的例子定义了一个匿名函数并把它赋值给变量x。这个函数返回它参数的平方:

  1. var x = function(y) {
  2.    return y * y;
  3. };
复制代码


§1.9.1 使用函数

  1. function 函数1(参数1,参数2,参数3) {
  2.    return 参数1 + 参数3 - 5 + 参数2 * 2;
  3. }
  4. 函数1(10,15,2);//37
复制代码


§1.9.2 函数提升

JavaScript 中的函数声明被提升到了函数定义。你可以在函数声明之前使用该函数:

  1. hoisted(); // "foo"
  2. function hoisted() {
  3.      console.log("foo");
  4. }
  5. /* equal to*/
  6. var hoisted;
  7. hoisted = function() {
  8.   console.log("foo");
  9. }
  10. hoisted();
  11. // "foo"
复制代码


注意 :函数表达式function expressions 不会被提升:

  1. notHoisted(); // TypeError: notHoisted is not a function
  2. var notHoisted = function() {
  3.    console.log("bar");
  4. };
复制代码


§1.9.3 命名函数表达式

如果你想在函数体内部引用当前函数,则需要创建一个命名函数表达式。然后函数名称将会且只会作为函数体(作用域内)的本地变量。

  1. var math = {
  2.   'factorial': function factorial(n) {
  3.     if (n <= 1)
  4.       return 1;
  5.     return n * factorial(n - 1);
  6.   }
  7. };
复制代码


§1.x 内置对象

待更新,可自行参考MDN

§1.x Classes

待更新,可自行参考MDN

§1.x 其它

持续填坑中,尽请期待!

§2 Nukkit 模组加载器

阅读本章内容前你应该熟练掌握上一大章节的内容并对Java有所了解。

可在本插件的GitHub源码上查看所有可调用的方法。

请以ANSI格式保存文件,否则中文字符串将乱码。

§2.1 全局变量

你应该避免对这些内置变量进行重新赋值。

  1. /* 直接暴露 */
  2. var server; // 返回 Java 的 “getServer();”
  3. var plugin; // 返回 Java 的模组加载器插件的 “MainClass”
  4. var manager; // 返回 Java 的 “FunctionManager Class”, 用于创建命令或任务
  5. var logger; // 返回 Java 的控制台日记记录器
  6. var players; // 返回所有在线玩家
  7. /* 非直接暴露() */
  8. var me; // 返回触发者
  9. var level; // 返回世界
  10. var pos; // 返回坐标
复制代码


§2.2 命令

创建命令
使用manager的createCommand()方法,有3个参数

  • 命令
  • 介绍
  • 函数名


  1. manager.createCommand("test1", "测试1", "命令1");
  2. function 命令1(sender, args) { // 这个函数的第一个参数为命令执行者,第二个参数为执行命令附带的参数(数组)
  3.     if(args.length < 1){ // 判断是否存在参数
  4.         sender.sendMessage('亲,带个参数吧~'); // 给命令使用者发消息
  5.         return; //返回
  6.     }
  7.     //如果存参数
  8.     sender.sendMessage("你输入的第一个参数为:" + args[0]); // 给命令使用者发消息
  9.     sender.sendMessage(
  10.         manager.format("你输入的第一个参数为: %s", args[0]) // manager的format()方法用于格式化字符串,即“...{args[0]}”
  11.     );
  12. }
复制代码


§2.3 任务

§2.3.1 定时任务

创建Java定时任务
使用manager的createTask()方法,有2个参数

  • 函数名
  • 等待Tick


  1. manager.createTask("定时任务1", 6 * 20); // 1秒=20tick,所以这里就是等待6秒执行函数“定时任务1”
  2. function 定时任务1(currentTick) { // 这个函数的参数为当前的Tick
  3.     print(currentTick); // 打印输出
  4.     print('I tasknormal!');
  5. }
复制代码


§2.3.2 循环任务

创建Java循环任务
使用manager的createLoopTask()方法,有2个参数

  • 函数名
  • 间隔Tick


  1. manager.createLoopTask("循环任务1", 9 * 20);  // 1秒=20tick,所以这里就是每隔9秒执行函数“循环任务1”一次
  2. function 循环任务1(currentTick) { //  这个函数的参数为当前的Tick
  3.     print(currentTick); // 打印输出
  4.     print('I taskloop');
  5. }
复制代码


§2.4 事件

所有的事件类型请在Nukkit事件大全查阅。

用事件名命名的函数监听事件,参数为此事件

  1. function PlayerJoinEvent(event) { // 监听玩家进服事件
  2.     var player = event.getPlayer(); // 获取触发事件的玩家
  3.     player.sendMessage("欢迎来到我的测试服务器!"); // 给玩家发送消息
  4. }
复制代码


§2.5 配置

创建配置
使用manager的createConfig()方法,有2个参数

  • 文件
  • 类型


  1. var config = manager.createConfig(
  2.     manager.getFile("测试文件夹", "配置.yml"), // manager的getFile()方法用于获取文件,第一个参数是文件夹,第二个参数是文件名
  3. 2); // 2为YAML语言
  4. config.set("键", "值"); // 设置配置
  5. config.save(); // 保存配置
复制代码


§3 练习

暂无

§4 作品

你可以在js文件头部使用注释添加版权等信息

  1. /*
  2. * auther: @wode490390
  3. * 采用GPLv3开源许可证
  4. */
复制代码


§4.1 混淆

你可以使用工具对代码进行加密,使抄袭者阅读不便

如源代码:

  1. function main(player,info) {
  2.     player.sendMessage(info+(info*info-info));
  3. }
  4. main(wode490390,233);
  5. main(093094edow,666);
复制代码


混淆后:

  1. function a(b,c) {
  2.     b.sendMessage(c+(c*c-c));
  3. }
  4. a(wode490390,233);
  5. a(093094edow,666);
复制代码


§4.2 加密

如源代码:

  1. function main(player,info) {
  2.     player.sendMessage(info+(info*info-info));
  3. }
  4. main(wode490390,233);
  5. main(093094edow,666);
复制代码


加密后:

  1. 持续更新中
复制代码


§4.3 压缩

你可以使用一些工具进行压缩,简化代码

  1. 持续更新中
复制代码


§4.4 发布

恭喜你学完了本教程,快去制作属于自己的NK模组吧,如有更新记得回来看看哦。

来看看其他人写的模组吧(按优秀程度排序,欢迎广大版友提供)

  • 暂无
来自群组: NukkitPluginStudio

评分

参与人数 3人气 +6 金粒 +50 收起 理由
cc7w + 3 MCBBS有你更精彩~
pogox + 2 + 30 MCBBS有你更精彩~
xiaozha13 + 1 + 20 MCBBS有你更精彩~

查看全部评分

wode490390 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
7841
钻石
性别
保密
注册时间
2014-6-21
查看详细资料
 楼主| 发表于 2018-8-17 07:06:23 | 显示全部楼层
逗比的幻影 发表于 2018-8-17 06:53
JS文件吗! JS不是Nukkit吧 是原版MOD

nk的js模组,详见此插件:http://www.mcbbs.net/thread-813311-1-1.html
回复

使用道具 举报

。—。 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
12352
钻石
性别
保密
注册时间
2012-12-16
查看详细资料
发表于 2018-8-17 10:36:13 | 显示全部楼层
wode490390 发表于 2018-8-17 07:06
nk的js模组,详见此插件:http://www.mcbbs.net/thread-813311-1-1.html

类似于以前modpe的样子……
回复

使用道具 举报

Ieech 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
34
钻石
性别
保密
注册时间
2018-8-17
查看详细资料
发表于 2018-8-17 10:57:41 | 显示全部楼层
/..................../.............................../
回复

使用道具 举报

xiaozha13 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
1422
钻石
性别
保密
注册时间
2017-4-1
查看详细资料
发表于 2018-8-17 13:08:52 | 显示全部楼层
感觉比NK插件简单多了
回复

使用道具 举报

wode490390 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
7841
钻石
性别
保密
注册时间
2014-6-21
查看详细资料
 楼主| 发表于 2018-8-17 18:35:02 来自手机 | 显示全部楼层
xiaozha13 发表于 2018-8-17 13:08
感觉比NK插件简单多了

这是肯定的
回复

使用道具 举报

堕落落 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
572
钻石
性别
保密
注册时间
2016-8-16
查看详细资料
发表于 2018-8-21 10:23:36 | 显示全部楼层
之前不知道为什么不能说话,早就很想问了,对于小部分的js,例如红石js,自定义生物js可以实现吗
回复

使用道具 举报

wode490390 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
7841
钻石
性别
保密
注册时间
2014-6-21
查看详细资料
 楼主| 发表于 2018-8-21 13:09:52 | 显示全部楼层
堕落落 发表于 2018-8-21 10:23
之前不知道为什么不能说话,早就很想问了,对于小部分的js,例如红石js,自定义生物js可以实现吗 ...

nk不支持红石与生物,需要额外插件实现
回复

使用道具 举报

堕落落 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
572
钻石
性别
保密
注册时间
2016-8-16
查看详细资料
发表于 2018-8-24 18:58:29 | 显示全部楼层
wode490390 发表于 2018-8-21 13:09
nk不支持红石与生物,需要额外插件实现

我并不是说原版的红石,而是用js实现的红石,自定义方块换成原版的方块,能实现吗
回复

使用道具 举报

wode490390 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
7841
钻石
性别
保密
注册时间
2014-6-21
查看详细资料
 楼主| 发表于 2018-8-24 19:22:24 | 显示全部楼层
堕落落 发表于 2018-8-24 18:58
我并不是说原版的红石,而是用js实现的红石,自定义方块换成原版的方块,能实现吗 ...

如果你是红石大神又精通js,可以试一试
回复

使用道具 举报

堕落落 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
572
钻石
性别
保密
注册时间
2016-8-16
查看详细资料
发表于 2018-8-29 15:18:17 | 显示全部楼层
wode490390 发表于 2018-8-24 19:22
如果你是红石大神又精通js,可以试一试

很早之前不是已经有过红石插件js了吗
回复

使用道具 举报

wode490390 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
7841
钻石
性别
保密
注册时间
2014-6-21
查看详细资料
 楼主| 发表于 2018-8-29 16:23:50 | 显示全部楼层
堕落落 发表于 2018-8-29 15:18
很早之前不是已经有过红石插件js了吗

那个是bl的,不是nk的
回复

使用道具 举报

堕落落 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
572
钻石
性别
保密
注册时间
2016-8-16
查看详细资料
发表于 2018-8-29 23:58:08 | 显示全部楼层
wode490390 发表于 2018-8-29 16:23
那个是bl的,不是nk的

你不是转载了一个模组加载器的插件吗
回复

使用道具 举报

wode490390 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
7841
钻石
性别
保密
注册时间
2014-6-21
查看详细资料
 楼主| 发表于 2018-8-30 00:12:30 | 显示全部楼层
堕落落 发表于 2018-8-29 23:58
你不是转载了一个模组加载器的插件吗

这玩意新出的,哪有红石js
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册(register)

本版积分规则

Archiver|小黑屋|Mcbbs.net ( 京ICP备15023768号-1 ) | 京公网安备 11010502037624号 | 手机版

GMT+8, 2019-12-11 22:16 , Processed in 0.063269 second(s), Total 22, Slave 21 queries, Release: Build.2019.12.06.1150, Gzip On, MemCached On.

"Minecraft"以及"我的世界"为Mojang Synergies AB的商标 本站与Mojang以及微软公司没有从属关系

© 2010-2019 我的世界中文论坛 版权所有 本站原创图文内容版权属于原创作者,未经许可不得转载

快速回复 返回顶部 返回列表