【JavaScript 簡明入門教程】為了Screeps服務的純JS入門教程

0 前言

0-1 Screeps: World

請添加圖片描述

  • 眾所不周知,?Screeps: World是一款面向編程愛好者的開源大型多人在線即時戰略(MMORTS)沙盒游戲,其核心機制是通過編寫JavaScript代碼來控制游戲中的單位(稱為“Creep”),以建立和發展自己的帝國。
  • 在游戲中,玩家需要編寫代碼來自動化單位的行為,包括采集資源、建造建筑、擴張領土等。?這些代碼會在游戲服務器上持續運行,即使玩家離線,單位也會按照預設的指令執行任務。
  • 那為了我們愉快的進入游戲玩耍之前,我們今天來速通一下JavaScript的基礎語法
0-2 JavaScript

請添加圖片描述

  • JavaScript(簡稱JS)是一種高級、解釋型、動態的編程語言,主要用于==網頁開發==。它最早由網景(Netscape)公司的布蘭登·艾奇(Brendan Eich)在1995年開發,用于增強網頁的交互性。如今,JavaScript已經發展成為一種功能強大的通用編程語言,廣泛應用于前端、后端、移動端、游戲開發等領域
  • JavaScript的特點:
  1. 解釋性語言:無需編譯,瀏覽器或Node.js可以直接執行。
  2. 支持動態類型:變量的類型可以在運行時動態變化。
  3. 弱類型:允許不同類型的數據進行運算。
  4. 基于對象:JavaScript中的幾乎所有內容(如數組、函數等)都是對象。
  5. 事件驅動和異步:使用事件監聽和回調函數,使網頁能響應用戶操作。通過Promiseasync/await支持異步編程,提高性能。
  6. 跨平臺:適用于Windows、Mac、Linux等各種操作系統,并且支持大多數瀏覽器(Chrome、Firefox、Edge等)。
0-3 食用本文前須知!!!
  • 通常大部分的JS教程都會和HTMLCSS綁定(畢竟是網頁開發捏),但由于本教程的后續目的咱們是為了愉快的玩耍Screeps: World,故本教程將專注于JS 純邏輯編程 為主,涵蓋變量、函數、對象、異步編程等核心內容。
  • 本教程目錄:
    • 編程環境搭建和HelloWorld
    • 變量聲明和數據類型
    • 函數、作用域與閉包
    • 運算符
    • 異常處理機制
    • 異步機制、回調函數與Promise(Screeps用不上)
    • 類、繼承與prototype
    • 多態
    • 數組(Array)

1 編程環境搭建和HelloWorld

1-1 Node.js簡介

請添加圖片描述

  • 通常傳統的JavaScript·只能在瀏覽器環境中運行,無法直接訪問文件系統、操作系統資源或數據庫。為了解決上述局限性,我們引入Node.js~
  • Node.js是一個基于 Chrome V8 引擎JavaScript 運行環境,允許 JS 在服務器端運行。
1-2 Node.js的安裝
  • 官網:Download Node.js請添加圖片描述

  • 如官網所述,windows端的下載打開powershell

# Download and install fnm:
winget install Schniz.fnm# Download and install Node.js:
fnm install 22# 如果輸入node -v 出現報錯請輸入下列代碼
# 記得是在poweshell中輸出
fnm env --use-on-cd | Out-String | Invoke-Expression# Verify the Node.js version:
node -v # Should print "v22.14.0".# Verify npm version:
npm -v # Should print "10.9.2".
  • winget 是 Windows 10/11自帶的 包管理器(類似于 Linux 的 aptbrew)。
  • fnm(Fast Node Manager),是一個 Node.js 版本管理工具。方便管理多個 Node.js 版本并且可以快速進行切換。
  • npm(Node Package Manager)是 Node.js 自帶的包管理工具,用于安裝和管理 JavaScript 庫。
  • 值得一提的是,上述代碼在下載完成中驗證Node.js的版本時候也許會出現下述報錯:請添加圖片描述
fnm env --use-on-cd | Out-String | Invoke-Expression
  • 上述代碼fnm 的環境變量加載到當前的 PowerShell 會話中,使得 Node.js 的相關命令(如 node -v)能夠在當前終端會話中正常使用。

1-3 HelloWorld與你的第一個js程序
  • IDE的話這里大家就隨便自己選咯,我這里用的是VSCode
  • 我們新建一個文件命名為Hello.js
console.log("Hello World!");
  • 然后在終端直接使用Node.js運行js文件
node .\hellojs.js
  • 至此我們的第一個JS程序就完成辣請添加圖片描述

  • 當然可以考慮安裝一些擴展(當然你也可以純記事本進行編程~)請添加圖片描述

1-4 (補充)ESX是啥
  • ESX 通常是一個非正式的表達,泛指 ECMAScript 的各種版本(ES6 及后續版本),即 ES6、ES7、ES8、ES9 等等。
  • ES6(ECMAScript 2015) 是 JavaScript 語言的一次重大更新,引入了 letconst、箭頭函數、類(class)、模塊(import/export)等重要特性。
版本發布時間重要特性
ES6 (ES2015)2015let / const、箭頭函數、類(class)、模板字符串、解構賦值、默認參數、import/export
ES7 (ES2016)2016Array.prototype.includes()、指數運算符 (**)
ES8 (ES2017)2017async/awaitObject.entries()Object.values()
ES9 (ES2018)2018Promise.finally()、正則表達式改進(命名捕獲組等)
ES10 (ES2019)2019Array.prototype.flat(), Object.fromEntries()
ES11 (ES2020)2020BigIntPromise.allSettled()、可選鏈 ?.
ES12 (ES2021)2021String.replaceAll()、邏輯賦值運算符 (`&&=,
1-5 JavaScript 嚴格模式 ("use strict")
  • 嚴格模式("use strict")是 ES5 引入的一種 JavaScript 執行模式,旨在 消除 JavaScript 的不安全或錯誤用法,提高代碼質量和執行效率
  • 開啟嚴格模式后,JavaScript 代碼會 拋出更多錯誤,阻止一些潛在的 Bug,同時提高 JS 引擎的優化效率。
  • 如何開啟嚴格模式?
  1. 在代碼的第一行添加
"use strict";console.log("嚴格模式開啟!");
  1. 嚴格模式也可以局部應用于某個函數
function strictFunction() {"use strict";let x = 10;console.log(x);
}
strictFunction();
  • 嚴格模式總結:
規則解釋
必須顯式聲明變量x = 10; 會報錯
禁止重復變量聲明var a = 10; var a = 20; 會報錯
禁止刪除變量/函數delete x; 會報錯
普通函數的 thisundefinedfunction test() { console.log(this); }
禁止 with 語句with (obj) { console.log(x); } 會報錯
禁止 eval() 影響作用域eval("var x = 10;"); console.log(x);
禁止八進制數var num = 010;

2 變量聲明和數據類型

2-1 變量聲明
  • JavaScript 提供了 varletconst 三種方式來聲明變量
2-1-1 var(已過時,不推薦)
  • 變量可以在聲明前使用(變量提升)。
  • 作用域是函數作用域(function scope)。
  • 可以重復聲明同名變量。
console.log(a); // undefined(變量提升)
var a = 10;
var a = 20; // 允許重復聲明
console.log(a); // 20
2-1-2 let(推薦使用)
  • 作用域是塊作用域(block scope)。
  • 不能在聲明前使用(不會變量提升)。
  • 不能重復聲明同名變量。
console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 10;
let b = 20; // ? SyntaxError: Identifier 'b' has already been declared
2-1-3 const(推薦用于常量)
  • 作用域是塊作用域(block scope)。
  • 必須在聲明時初始化,且值不能更改(不可變)。
  • 不能重復聲明。
const PI = 3.14159;
PI = 3.14; // ? TypeError: Assignment to constant variable
2-2 原始數據類型
  • JavaScript 主要有七種原始數據類型一種對象類型
2-2-1 number(數字類型)
  • 包括整數和浮點數
  • 例如:103.14-5
  • 還有特殊值:Infinity-InfinityNaN
let num1 = 42;
let num2 = 3.14;
let notANumber = NaN;
2-2-2 string(字符串類型)
  • 由字符組成,使用單引號 '、雙引號 " 或反引號 `(模板字符串)。
  • 例如:"hello"'world'`Hello, ${name}`
let str1 = "Hello";
let str2 = 'World';
let name = "Alice";
let str3 = `Hello, ${name}`; // 模板字符串
2-2-3 boolean(布爾類型)
  • 只有兩個值:truefalse
  • 用于邏輯判斷
let isOnline = true;
let hasError = false;
2-2-4 undefined(未定義類型)
  • 變量聲明但未賦值時的默認值
let x;
console.log(x); // undefined
2-2-5 null(空值)
  • 表示“空值”或“無值”
  • 通常用于手動賦值,表示變量為空
let y = null;
2-2-6 symbol(符號類型,ES6 新增)
  • 創建獨一無二的值,通常用于對象屬性鍵
let sym = Symbol("unique");
2-2-7 bigint(大整數類型,ES11/ES2020 新增)
  • 適用于處理比 Number.MAX_SAFE_INTEGER 更大的整數
let bigNum = 9007199254740991n;

2-3 對象類型

JavaScript 只有一種復雜數據類型——對象(Object),包括:

  • 普通對象 { key: value }
  • 數組 [1, 2, 3]
  • 函數 function() {}
  • 日期 new Date()
  • 正則表達式 /abc/
let person = {name: "Alice",age: 25
};let arr = [1, 2, 3];function sayHello() {console.log("Hello!");
}
  • 可以使用 typeof 來檢查變量類型:
console.log(typeof 42);       // "number"
console.log(typeof "hello");  // "string"
console.log(typeof true);     // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null);     // "object"(JavaScript 的歷史遺留問題)
console.log(typeof {});       // "object"
console.log(typeof []);       // "object"
console.log(typeof function() {}); // "function"
console.log(typeof Symbol("id")); // "symbol"
console.log(typeof 9007199254740991n); // "bigint"

2-4 對象類型的創建,訪問,屬性引用
  • 創建對象
    • (下述內容部分超出范圍還沒說,但是相信熟悉其他編程語言的朋友們可以看懂)
    • (如果沒看懂的話可以先往后看后面再回來看這一部分)
const person = {name: "Alice",age: 25,"home city": "New York", greet: function () {console.log("Hello, I'm " + this.name);}
};
2-4-1 訪問對象的屬性(一):使用 . 訪問(常用)
  • . 訪問方式只能用于符合變量命名規則的鍵(如 nameage)。
console.log(person.name); // 輸出: Alice
console.log(person.age);  // 輸出: 25
2-4-2 訪問對象的屬性(二):使用 [] 訪問(適用于動態鍵)
  • 可以訪問特殊字符(如空格、- 等)的屬性(如 "home city")。
  • 可以用變量作為鍵名,適用于動態訪問。
console.log(person["name"]);      // 輸出: Alice
console.log(person["home city"]); // 輸出: New York
  • 動態鍵訪問
const key = "age";
console.log(person[key]);  // 輸出: 25
2-4-4 訪問對象的方法
person.greet(); // 輸出: Hello, I'm Alice
2-4-5 檢查對象是否包含某個屬性
  1. 使用 in 關鍵字
console.log("name" in person);  // true
console.log("gender" in person); // false
  1. 使用 hasOwnProperty() 方法
console.log(person.hasOwnProperty("age"));  // true
console.log(person.hasOwnProperty("gender")); // false
2-4-6 遍歷對象的屬性
for (let key in person) {console.log(key + ": " + person[key]);
}
2-4-7 刪除對象屬性
  • 訪問對象中不存在的屬性時,返回 undefined,不會報錯。
delete person.age;
console.log(person.age); // 輸出: undefined


3 函數、作用域與閉包

  • JavaScript 中,函數(Function) 是代碼的可復用塊,允許封裝邏輯并在需要時調用。同時,作用域(Scope) 決定了變量的可訪問性。
  • JavaScript 提供了三種常見方式來定義函數:
3-1 函數聲明(Function Declaration)
  • 關鍵字 function 開頭
  • 支持函數提升(Hoisting),可以在定義前調用
console.log(square(5)); // 25function square(num) {return num * num;
}console.log(square(5)); // 25
3-2 函數表達式(Function Expression)
  • 沒有函數名(匿名函數)
  • 賦值給變量后使用
  • 不支持函數提升(只能在定義后調用)
const greet = function(name) {return "Hello, " + name;
};
console.log(greet("Bob")); // Hello, Bob
3-3 箭頭函數(Arrow Function,ES6)
  • 語法更簡潔
  • 沒有 this 綁定(this 取決于外部作用域)
  • 適合回調函數 & 簡單邏輯
const add = (a, b) => {return a + b;
};
console.log(add(3, 4)); // 7
  • 單行省略 {}return
const multiply = (a, b) => a * b;
console.log(multiply(2, 3)); // 6

3-4 作用域(Scope)
  • 作用域決定了變量的可訪問范圍。JavaScript 有三種主要作用域
  1. 全局作用域(Global Scope)**: 聲明在函數外部的變量,在整個腳本或瀏覽器窗口中可訪問
  2. 函數作用域(Function Scope):在函數內部聲明的變量,只能在該函數內部訪問
  3. 塊級作用域(Block Scope,ES6):letconst 具有塊級作用域,var 沒有塊級作用域
{let x = 10;const y = 20;var z = 30; // ?? var 例外
}
console.log(z); // ? 30
console.log(x); // ? ReferenceError
console.log(y); // ? ReferenceError

3-5 閉包(Closure)
  • 閉包是指內部函數可以訪問外部函數的變量,即使外部函數已經執行完畢。4
  • 閉包的作用:
    • 數據私有化
    • 模擬 static 變量
function outer() {let count = 0;return function inner() {count++;console.log("Count:", count);};
}const counter = outer();
counter(); // Count: 1
counter(); // Count: 2
  • 關于閉包的調用方式及其注意點:
調用方式是否形成閉包?變量是否累積?原因
outer();? 否? 否inner 從未被執行
outer().inner();? 否? 否count 在每次 outer() 調用后重置
const counter = outer(); counter(); counter();? 是? 是counter 持有 count 的引用,形成閉包

3-6 this 關鍵字
  • this 是 JavaScript 中的特殊關鍵字,它的值取決于函數的調用方式
    1?? 全局作用域
  • 非嚴格模式下,this 指向 window(瀏覽器)或 global(Node.js)。
  • 嚴格模式下,thisundefined
"use strict";
console.log(this);  // 輸出:undefined

2?? 作為對象方法調用

  • 此時this 指向對象本身
const obj = {name: "Alice",sayHi: function() {console.log(this.name);}
};obj.sayHi();  // 輸出:"Alice"

3??作為構造函數調用

  • 在構造函數中,this 指向新創建的對象
function Person(name) {this.name = name;
}const p = new Person("Bob");
console.log(p.name);  // 輸出:"Bob"

4??call / apply / bind 顯式綁定

  • JavaScript 允許手動設置 this,可以使用:
    • call() 傳遞參數列表
    • apply() 傳遞參數數組
    • bind() 返回一個新的綁定函數
const user = { name: "Charlie" };function sayHello() {console.log("Hello, " + this.name);
}sayHello.call(user);   // 輸出:"Hello, Charlie"
sayHello.apply(user);  // 輸出:"Hello, Charlie"const boundFunc = sayHello.bind(user);
boundFunc();  // 輸出:"Hello, Charlie"

5?? 箭頭函數中的 this

  • 箭頭函數不會創建自己的 this,而是繼承外部作用域的 this
const obj = {name: "Alice",sayHi: function() {const inner = () => {console.log(this.name);};inner();}
};obj.sayHi();  // 輸出:"Alice"

4 運算符

  • 本節內容基礎就給出表格大家自行參閱!
4-1 比較運算符
運算符描述示例結果
==寬松相等(值相等,類型可轉換)'5' == 5true
===嚴格相等(值相等,類型也必須相同)'5' === 5false
!=寬松不等(值不相等,類型可轉換)'5' != 5false
!==嚴格不等(值或類型不同)'5' !== 5true
>大于10 > 5true
<小于10 < 5false
>=大于等于10 >= 10true
<=小于等于10 <= 5false
4-2 算數運算符
運算符描述示例結果
+加法5 + 38
-減法5 - 32
*乘法5 * 315
/除法5 / 22.5
%取模(取余數)5 % 21
**指數(冪運算)2 ** 38
  • 然后是自增自減老規矩~
形式說明示例結果
x++后置自增(先返回值,再加 1)let a = 5; let b = a++;b = 5, a = 6
++x前置自增(先加 1,再返回值)let a = 5; let b = ++a;b = 6, a = 6
x--后置自減(先返回值,再減 1)let a = 5; let b = a--;b = 5, a = 4
--x前置自減(先減 1,再返回值)let a = 5; let b = --a;b = 4, a = 4
4-3 賦值運算符
運算符等價于示例
+=x = x + yx += 2;
-=x = x - yx -= 2;
*=x = x * yx *= 2;
/=x = x / yx /= 2;
**=x = x ** yx **= 2;
%=x = x % yx %= 2;

5 分支語句(條件語句) 和 循環語句

  • 本節同樣基礎,我們飛速略過
5-1 if-else 語句
  • 無需多言
if (/*condition1*/)  
{  }  
else if (/*condition2*/)  
{  }  
else  
{  }
5-2 switch 語句
  • 需要注意的是,js的switch 語句可以用于 任何類型stringnumberboolean,甚至 objectfunction)。
  • js的switch 語句支持嵌套(不建議你這么干)
  • 其他部分和其他語言相同:
    • case 語句后必須是具體的值,不能是范圍或條件表達式。
    • break 語句用于阻止穿透(fall-through),否則會繼續執行下一個 case 代碼塊。
    • default 是可選的,但建議寫上,以防所有 case 都不匹配。
let color = "紅色";
switch (color) {case "紅色":console.log("你選擇了紅色");break;case "藍色":console.log("你選擇了藍色");break;case "綠色":console.log("你選擇了綠色");break;default:console.log("未知顏色");
}
5-3 for 循環
for (let i = 1; i <= 5; i++) {console.log(i);
}
  • 注意區分:for...infor...of
語句適用對象作用
for...in對象遍歷對象的屬性名
for...of數組、字符串遍歷數組的
  • for...in:
let person = { name: "張三", age: 25, city: "北京" };
for (let key in person) {console.log(key + ": " + person[key]);
}
  • for...of
let numbers = [10, 20, 30];
for (let num of numbers) {console.log(num);
}
5-4 while 循環
let count = 1;
while (count <= 3) {console.log(count);count++;
}
5-5 do-while循環
let num = 1;
do {console.log(num);num++;
} while (num <= 3);
5-6 breakcontinue
  • 同理:
    • break 終止循環
    • continue跳過當前循環的剩余代碼,直接進入下一次循環,不會終止整個循環。

6 異常處理機制

  • 在 JavaScript 開發中,程序運行時可能會遇到錯誤(比如變量未定義、JSON 解析失敗、網絡請求錯誤等)。為了防止這些錯誤導致程序崩潰,我們可以使用 異常處理機制 來捕獲和處理錯誤。
6-1 異常處理機制 try-catch-finally
try {// 可能會出錯的代碼
} catch (error) {// 處理錯誤console.log("捕獲錯誤:", error.message);
} finally{// 無論是否發生錯誤都會執行,適用于資源釋放、日志記錄等場景。
}
6-2 throw 關鍵字(手動拋出異常)
 throw new Error("你的錯誤信息");

7 異步機制、回調函數與Promise

  • 值得一提的是,Screeps 的代碼是 Tick 驅動的,而不是時間驅動的,所以要用 Game.time 來管理邏輯,而不是 setTimeoutPromise
  • 因此本節對Screeps編程毫無作用,不感興趣的朋友們可以直接跳過~
7-1 異步機制
  • JavaScript 是 單線程 語言,為了防止長時間執行的任務(如網絡請求、文件讀寫)阻塞主線程,采用 異步編程 方式,使代碼可以在等待操作完成的同時執行其他任務。
  • 常見的異步操作:
    • setTimeout / setInterval(定時器)
    • DOM 事件監聽 (addEventListener)
    • AJAX / Fetch 請求(HTTP 請求)
    • Promiseasync/await
7-2 setTimeout / setInterval(定時器)
  • setTimeoutsetInterval 是 JavaScript 的內置函數。它屬于 Web API,由 瀏覽器或 Node.js 提供,并不直接屬于 JavaScript 語言核心。
方法用途特點
setTimeout(fn, delay)延遲執行 fn 一次僅執行一次,需要手動遞歸調用
setInterval(fn, delay)間隔執行 fn會一直執行,直到調用 clearInterval()
  • 下面我們來看二者具體的區別:
7-2-1 setTimeout
  • setTimeout 是 JavaScript 的內置函數,用于延遲執行代碼
setTimeout(callback, delay, param1, param2, ...);
  • callback(必填):延遲執行的 函數(匿名函數或函數引用)。
  • delay(必填):延遲時間(單位:毫秒 ms1000ms = 1秒)。
  • param1, param2, ...(可選):傳遞給 callback 的參數。
  • 注意可以使用clearTimeout(timer); // 取消定時器
let timer = setTimeout(() => {console.log("不會執行");
}, 5000);clearTimeout(timer);  // 取消定時器
7-2-2 ``setInterval`
  • setInterval 是 JavaScript 內置的定時器函數,用于按指定時間間隔重復執行某個函數,直到調用 clearInterval() 停止。
setInterval(callback, delay, param1, param2, ...);
  • callback 要執行的函數(可以是匿名函數或函數引用)
  • delay 時間間隔(毫秒),1000ms = 1秒
  • param1, param2, … 傳遞給 callback 的參數(可選)
setInterval(() => {console.log("每 2 秒執行一次");
}, 2000);
  • 使用 clearInterval(intervalID) 停止 setInterval
let count = 0;
let intervalID = setInterval(() => {count++;console.log("執行次數:" + count);if (count === 5) {clearInterval(intervalID);  // 停止定時器console.log("定時器已停止");}
}, 1000);
7-3 回調函數
  • 回調函數 是一種最基本的異步處理方式,即將一個函數作為參數傳遞,待操作完成后調用該函數。
function fetchData(callback) {setTimeout(() => {console.log("數據獲取成功");callback("數據內容");}, 2000);
}fetchData((data) => {console.log("回調函數接收數據:", data);
});

缺點:

  • 回調地獄(Callback Hell):多個回調嵌套使代碼變得難以維護。
  • 錯誤處理不方便:錯誤需要通過回調手動傳遞,容易遺漏。
7-4 Promise
  • Promise 是 ES6 引入的一種異步編程解決方案,它可以更優雅地處理異步操作,避免回調地獄。
  • *Promise 三種狀態:
    • pending(進行中)
    • fulfilled(已成功)
    • rejected(已失敗)
function fetchData() {return new Promise((resolve, reject) => {setTimeout(() => {let success = true; // 模擬成功或失敗if (success) {resolve("數據獲取成功");} else {reject("數據獲取失敗");}}, 2000);});
}fetchData().then((data) => console.log("成功:", data))   // 處理成功.catch((error) => console.log("失敗:", error)) // 處理失敗.finally(() => console.log("請求完成"));       // 無論成功失敗都會執行

優勢:

  • 避免回調地獄,使代碼更易讀。
  • 提供 .then().catch().finally() 結構,方便管理異步操作。
7-5 async/await(基于 Promise)
  • async/awaitES8 引入的一種更直觀的異步編程方式,它是 Promise 的語法糖,使異步代碼更接近同步寫法。
async function fetchData() {try {let data = await new Promise((resolve) => setTimeout(() => resolve("數據獲取成功"), 2000));console.log(data);} catch (error) {console.log("錯誤:", error);} finally {console.log("請求完成");}
}fetchData();

特點:

  • await 關鍵字會等待 Promise 處理完成后再執行后續代碼。
  • try/catch 可用于錯誤處理,比 .catch() 更直觀。

8 類、繼承與prototype

  • 在 JavaScript 中,類(Class)原型(Prototype) 是實現面向對象編程(OOP)的核心。ES6 之前,JavaScript 使用 原型繼承(Prototype Inheritance),而在 ES6 引入了 class 語法,使面向對象編程更直觀。
8-1 class(類)
  • ES6 引入 class 關鍵字,使 JavaScript 的面向對象代碼更加清晰,但本質上它仍然是 基于原型的繼承
class Person {constructor(name, age) {this.name = name;this.age = age;}// 定義方法(自動添加到原型上)sayHello() {console.log(`Hi, I'm ${this.name} and I'm ${this.age} years old.`);}
}// 創建對象
const person1 = new Person("Alice", 25);
person1.sayHello();  // 輸出: Hi, I'm Alice and I'm 25 years old.
  • constructor():構造函數,在創建對象時自動執行。
  • sayHello():實例方法,所有 Person 對象共享。
8-2 靜態方法 (Static Methods)
  • 在 JavaScript 中,靜態方法是定義在類本身而不是類的實例上的方法。靜態方法可以通過類名直接訪問,而不能通過類的實例來調用。
  • 使用 static 關鍵字定義靜態方法。
class MyClass {// 靜態方法static staticMethod() {console.log("This is a static method");}// 實例方法instanceMethod() {console.log("This is an instance method");}
}// 調用靜態方法
MyClass.staticMethod();  // 輸出: This is a static method// 創建類的實例
const myInstance = new MyClass();// 調用實例方法
myInstance.instanceMethod();  // 輸出: This is an instance method// 無法通過實例調用靜態方法
// myInstance.staticMethod();  // TypeError: myInstance.staticMethod is not a function
8-3 繼承(Inheritance)
  • 在 ES6 中,可以使用 extends 關鍵字實現 類繼承,并使用 super() 調用父類的構造函數。
class Student extends Person {constructor(name, age, grade) {super(name, age);  // 調用父類的構造函數this.grade = grade;}study() {console.log(`${this.name} is studying in grade ${this.grade}.`);}
}const student1 = new Student("Bob", 20, "10th");
student1.sayHello();  // 繼承父類的方法
student1.study();     // 輸出: Bob is studying in grade 10th.
  • extends 讓子類繼承父類。
  • super() 允許調用 父類的構造函數必須在 constructor第一行執行。
  • 子類可以擴展自己的方法。

  • 靜態方法也可以被繼承,子類可以繼承父類的靜態方法,或者重寫靜態方法。
class Animal {static type() {console.log("I am an animal");}
}class Dog extends Animal {static type() {console.log("I am a dog");}
}// 調用父類靜態方法
Animal.type();  // 輸出: I am an animal// 調用子類重寫的靜態方法
Dog.type();  // 輸出: I am a dog
8-4 prototype(原型)
  • JavaScript 是基于 原型繼承 的語言,每個對象都有一個 __proto__ 屬性,指向其 原型(prototype)
  • JavaScript 本質上仍然是基于原型的繼承class 只是語法糖。
  • 類的方法實際上是添加到 prototype 上的。
function Animal(name) {this.name = name;
}// 添加方法到原型
Animal.prototype.makeSound = function () {console.log(`${this.name} makes a sound.`);
};const dog = new Animal("Dog");
dog.makeSound();  // 輸出: Dog makes a sound.
console.log(Person.prototype.sayHello === person1.sayHello); // true
  • prototype 讓所有實例共享方法,減少內存占用。
  • 直接操作 prototype 可實現手動繼承。

9 多態

  • 多態(Polymorphism)指的是相同的方法在不同對象上具有不同的行為。在 JavaScript 中,多態主要通過 **方法重寫(Method Overriding)****鴨子類型(Duck Typing)** 實現。
  • JavaScript 是支持多態的,但它不像 Java、C++ 那樣有嚴格的類型系統,而是依賴于其動態特性和原型繼承來實現多態。
9-1 方法重寫(Method Overriding)
  • 子類可以重寫父類的方法,實現不同的功能。
class Animal {makeSound() {console.log("Some generic animal sound");}
}class Dog extends Animal {makeSound() {console.log("Woof! Woof!");  // 重寫父類的方法}
}class Cat extends Animal {makeSound() {console.log("Meow~");  // 重寫父類的方法}
}// 統一調用
const animals = [new Dog(), new Cat()];//不關心 `animal` 的具體類型,只調用 `makeSound()`。
animals.forEach(animal => animal.makeSound());  
// 輸出:
// Woof! Woof!
// Meow~
9-2 鴨子類型(Duck Typing)
  • “如果它會游泳、嘎嘎叫,那么它就是一只鴨子。” —— 鴨子類型 JavaScript 是動態語言,只要對象實現了相同的方法,就可以被當作同一種類型使用,而不關心它的類繼承關系
class Bird {speak() {console.log("Chirp chirp");}
}class Robot {speak() {console.log("Beep boop");}
}// 統一處理不同對象
const entities = [new Bird(), new Robot()];
entities.forEach(entity => entity.speak());// 輸出:
// Chirp chirp
// Beep boop
  • BirdRobot 沒有繼承同一個父類,但都實現了 speak() 方法。
  • entities.forEach(entity => entity.speak()); 實現了多態,因為 JS 只在運行時檢查 speak() 是否存在,而不檢查對象的類型。
9-3 函數多態(參數多態)
  • JavaScript 的函數可以接收不同類型的參數,表現出函數多態(Function Polymorphism)。
function printMessage(msg) {if (typeof msg === "string") {console.log(`Text: ${msg}`);} else if (typeof msg === "number") {console.log(`Number: ${msg}`);} else {console.log("Unknown type");}
}printMessage("Hello"); // Text: Hello
printMessage(123);     // Number: 123
printMessage(true);    // Unknown type

10 數組(Array)

  • 在JavaScript中,數組是存儲一組數據的對象。數組的元素可以是任何類型,包括其他對象和函數等。
10-1 數組的基本創建和訪問
  • 有兩種常見的方式來創建數組:
// 使用數組字面量創建數組
let numbers = [1, 2, 3, 4];  // 數字數組
let names = ['Alice', 'Bob', 'Charlie'];  // 字符串數組// 使用Array構造函數
let emptyArray = new Array();  // 創建一個空數組
let anotherArray = new Array(10);  // 創建一個包含10個空位的數組
let filledArray = new Array(1, 2, 3);  // 創建并初始化數組
10-2 元素訪問
  • 數組的索引是從 0 開始的。我們可以通過索引來訪問數組的元素。
let arr = [10, 20, 30, 40];
console.log(arr[0]);  // 輸出:10
console.log(arr[2]);  // 輸出:30
  • indexOf():查找元素的索引位置。
let arr = [10, 20, 30, 40];
console.log(arr.indexOf(30)); // 輸出:2
10-3 數組內建方法
  • push(): 向數組末尾添加一個或多個元素,返回新數組的長度。
let arr = [1, 2, 3];
arr.push(4); // arr變為 [1, 2, 3, 4]
console.log(arr); // 輸出:[1, 2, 3, 4]
  • pop(): 刪除數組末尾的元素,返回刪除的元素。
let arr = [1, 2, 3, 4];
let poppedElement = arr.pop(); // poppedElement = 4
console.log(arr); // 輸出:[1, 2, 3]
  • shift(): 刪除數組開頭的元素,返回刪除的元素。
let arr = [1, 2, 3, 4];
let shiftedElement = arr.shift(); // shiftedElement = 1
console.log(arr); // 輸出:[2, 3, 4]
  • unshift(): 向數組的開頭添加一個或多個元素。
let arr = [1, 2, 3];
arr.unshift(0); // arr變為 [0, 1, 2, 3]
console.log(arr); // 輸出:[0, 1, 2, 3]
  • splice(): 在任意位置添加或刪除元素。
let arr = [1, 2, 3, 4];
arr.splice(2, 1, 5); // 從索引2刪除1個元素,插入5
console.log(arr); // 輸出:[1, 2, 5, 4]
  • map():對數組中的每個元素執行一個函數并返回一個新數組。
let arr = [1, 2, 3];
let squared = arr.map(x => x * x); // [1, 4, 9]
console.log(squared);
  • filter():根據條件過濾數組元素,返回一個新數組。
let arr = [1, 2, 3, 4];
let evenNumbers = arr.filter(x => x % 2 === 0); // [2, 4]
console.log(evenNumbers);
  • reduce():將數組元素通過某個函數累積成一個單一的值。
let arr = [1, 2, 3, 4];
let sum = arr.reduce((acc, current) => acc + current, 0); // 10
console.log(sum);
10-4 數組遍歷
  • for 循環:傳統的遍歷方式。
let arr = [10, 20, 30];
for (let i = 0; i < arr.length; i++) {console.log(arr[i]);
}
  • forEach():對每個元素執行一個函數。
let arr = [10, 20, 30];
arr.forEach((element, index) => {console.log(`Index: ${index}, Value: ${element}`);
});
  • map():創建一個新數組,數組的每個元素是通過提供的函數對原數組每個元素進行處理的結果。
let arr = [1, 2, 3];
let doubled = arr.map(x => x * 2); // [2, 4, 6]
console.log(doubled);
10-5 注意點
  • 數組大小:在JavaScript中,數組實際上是對象,且鍵名是數字(數組的索引)。因此,處理大型數組時,性能可能會成為問題。尤其是使用shift()unshift()操作時,數組的所有元素會被重新索引,可能導致性能下降。

11 總結

  • 本教程我們從Screeps: World必須的JavaScript,將JSCSSHTML的教程分離,專注于講解JS的原生基礎語法。

  • 完成上述基礎知識學習,你就可以正式開始學習玩耍Screeps咯,事不宜遲那就從教程開始吧:Screeps官方教程請添加圖片描述

  • 如有錯誤,歡迎指出!!!!!

  • 感謝大家的支持!!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/73572.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/73572.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/73572.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

第12章:優化并發_《C++性能優化指南》notes

優化并發 一、并發基礎與優化核心知識點二、關鍵代碼示例與測試三、關鍵優化策略總結四、性能測試方法論多選題設計題答案與詳解多選題答案&#xff1a; 設計題答案示例 一、并發基礎與優化核心知識點 線程 vs 異步任務 核心區別&#xff1a;std::thread直接管理線程&#xf…

[C++面試] RAII資源獲取即初始化(重點)

一、入門 1、什么是 RAII&#xff1f; RAII&#xff08;Resource Acquisition Is Initialization&#xff0c;資源獲取即初始化&#xff09;是 C 的核心編程范式&#xff0c;核心思想是 ?將資源的生命周期與對象的生命周期綁定&#xff1a; ?資源獲取&#xff1a;在對象構造…

Unity粒子系統

目錄 一、界面參數介紹1.主模塊2.Emission 模塊3.Shape 模塊4.Velocity over Lifetime 模塊5.Noise 模塊6.Limit Velocity Over Lifetime 模塊7.Inherit Velocity 模塊8.Force Over Lifetime 模塊9.Color Over Lifetime 模塊10.Color By Speed 模塊11.Size over Lifetime 模塊1…

Docker-清理容器空間prune

docker system prune -a 是一個非常有用的命令&#xff0c;用于清理 Docker 系統中未使用的資源&#xff0c;包括停止的容器、未使用的網絡、卷以及未被任何容器引用的鏡像&#xff08;懸空鏡像和所有未使用的鏡像&#xff09;。以下是關于該命令的詳細說明&#xff1a; 命令格…

LabVIEW遠程控制通訊接口

abVIEW提供了多種遠程控制與通訊接口&#xff0c;適用于不同場景下的設備交互、數據傳輸和系統集成。這些接口涵蓋從基礎的網絡協議&#xff08;如TCP/IP、UDP&#xff09;到專用技術&#xff08;如DataSocket、遠程面板&#xff09;&#xff0c;以及工業標準協議&#xff08;如…

LeetCode hot 100—尋找重復數

題目 給定一個包含 n 1 個整數的數組 nums &#xff0c;其數字都在 [1, n] 范圍內&#xff08;包括 1 和 n&#xff09;&#xff0c;可知至少存在一個重復的整數。 假設 nums 只有 一個重復的整數 &#xff0c;返回 這個重復的數 。 你設計的解決方案必須 不修改 數組 nums…

linux - centos7 部署 redis6.0.5

事先說明 本篇文章只解決在部署redis中出現的問題&#xff0c;并沒有部署redis的全過程&#xff0c;詳細部署過程可以參考Linux安裝部署Redis(超級詳細) - 長沙大鵬 - 博客園 執行 make 命令時報錯 原因&#xff1a;是因為gcc版本太低 升級gcc版本時 出現沒有可用軟件包 devt…

31天Python入門——第15天:日志記錄

你好&#xff0c;我是安然無虞。 文章目錄 日志記錄python的日志記錄模塊創建日志處理程序并配置輸出格式將日志內容輸出到控制臺將日志寫入到文件 logging更簡單的一種使用方式 日志記錄 日志記錄是一種重要的應用程序開發和維護技術, 它用于記錄應用程序運行時的關鍵信息和…

AI Agent開發大全第八課-Stable Diffusion 3的本地安裝全步驟

前言 就像我們前面幾課所述,本系列是一門體系化的教學,它不像網上很多個別存在的單篇博客走“吃快餐”模式,而是從扎實的基礎來帶領大家一步步邁向AI開發高手。所以我們的AI課程設置是相當全面的,除了有牢固的基礎知識外還有外面互聯網上也搜不到的生產級實戰。 前面講過…

用selenium+ChromeDriver豆瓣電影 肖申克的救贖 短評爬取(pycharm 爬蟲)

一、豆瓣電影 肖申克的救贖 短評urlhttps://movie.douban.com/subject/1292052/comments 二、基本知識點講解 1. Selenium 的基本使用 Selenium 是一個用于自動化瀏覽器操作的庫&#xff0c;常用于網頁測試和爬蟲。代碼中使用了以下 Selenium 的核心功能&#xff1a; webdriv…

開源在線客服系統源碼-前端源碼加載邏輯

客服源碼是使用Golang(又稱Go)開發的&#xff0c;Go是Google公司開發的一種靜態強類型、編譯型、并發型&#xff0c;并具有垃圾回收功能的編程語言。Go 天生支持并發。好處太多就不多說了。 全源碼客服系統用戶&#xff0c;想要針對自己的業務&#xff0c;進行二次開發&#xf…

Oracle數據庫服務器地址變更與監聽配置修改完整指南

一、前言 在企業IT運維中&#xff0c;Oracle數據庫服務器地址變更是常見的運維操作。本文將詳細介紹如何安全、高效地完成Oracle數據庫服務器地址變更及相關的監聽配置修改工作&#xff0c;確保數據庫服務在遷移后能夠正常運行。 二、準備工作 1. 環境檢查 確認新舊服務器I…

g對象在flask中主要是用來實現什么

在Flask中&#xff0c;g對象&#xff08;全稱flask.g&#xff09;是一個線程局部&#xff08;thread-local&#xff09;的臨時存儲對象&#xff0c;主要用于在單個請求的上下文&#xff08;request context&#xff09;中共享數據。它的核心作用是為同一請求的不同處理階段&…

工具介紹《WireShark》

Wireshark 過濾命令中符號含義詳解 一、比較運算符 Wireshark 支持兩種比較運算符語法&#xff1a;英文縮寫&#xff08;如 eq&#xff09;和 C語言風格符號&#xff08;如 &#xff09;&#xff0c;兩者功能等價。 符號&#xff08;英文縮寫&#xff09;C語言風格符號含義示…

JavaScrip-模版字符串的詳解

1.模版字符串的詳解 1.1 模版字符串的使用方法 在ES6之前&#xff0c;如果我們想要將字符串和一些動態的變量&#xff08;標識符&#xff09;拼接到一起&#xff0c;是非常丑陋的&#xff08;ugly) ES6允許我們使用模版字符串來嵌入變量或者表達式來進行拼接 首先&#xff0c;…

STM32C011 進入停止模式和待機模式

對于STM32C011J4M3微控制器&#xff0c;你可以使用HAL庫來實現進入停止模式&#xff08;Stop Mode&#xff09;和待機模式&#xff08;Standby Mode&#xff09;。下面是進入停止模式和待機模式的示例代碼&#xff1a; 進入停止模式代碼示例&#xff1a; #include "stm3…

海康設備http監聽接收報警事件數據

http監聽接收報警事件數據 海康獲取設備報警事件數據兩種方式&#xff1a; 1、sdk 布防監聽報警事件數據&#xff08;前面文章有示例&#xff09; 2、http監聽接收報警事件數據 http監聽接收報警事件數據&#xff0c;服務端可以使用netty通過端口來監聽獲取事件數據。 WEB 端…

FastAPI 全面指南:功能解析與應用場景實踐

FastAPI 全面指南&#xff1a;功能解析與應用場景實踐 FastAPI 是一個現代、快速&#xff08;高性能&#xff09;的 Python Web 框架&#xff0c;用于構建 API。它基于標準 Python 類型提示&#xff0c;使用 Starlette 和 Pydantic 構建&#xff0c;提供了極高的性能并簡化了開…

【STM32】編寫程序控制開發板的RGB LED燈

目錄 1、原理圖2、文件結構3、使用寄存器模式點亮3.1、什么是寄存器3.2、寄存器開發的本質3.3、寄存器開發步驟3.4、主要源碼3.4.1、main.c3.4.2、drv_gpio.h3.4.3、drv_gpio.c3.4.4、使用BSRR和BRR影子寄存器優化drv_gpio.c3.4.5、效果演示 4、使用標準庫模式點亮4.1、使用標準…

MyBatis-Plus 的加載及初始化

在 Spring Boot 啟動過程中&#xff0c;MyBatis-Plus 的加載和初始化涉及多個階段的工作。這些工作包括 MyBatis-Plus 自身的配置解析、Mapper 接口的掃描與注冊、SQL 語句的動態注入以及底層 MyBatis 的初始化等。以下是對整個過程的詳細分析&#xff1a; 1. Spring Boot 啟動…