轉自個人博客
因為本人經常使用QML,而由于QML與JS之間的關系,本人經常使用到JS相關語法,所以在此系統性對JS基礎知識進行總結、記錄。
1. 入門
JavaScript(簡稱 JS)是一種廣泛應用于Web開發的腳本語言,它是構建現代Web應用的核心技術之一。
1.1 JS與Web三大件
JavaScript是全球流行的Web編程語言,是Web開發者必學的三大技術之一:
- HTML:定義網頁的內容,如文本、圖片、鏈接等。
- CSS:規定網頁的布局和樣式,使網頁具備美觀的外觀。
- JavaScript:負責網頁的行為與交互,為網頁添加動態效果和響應用戶操作的能力。
JS的作用就是通過對HTML元素的控制,使網頁具備交互功能,比如點擊按鈕時執行某些操作,或者通過網絡請求動態加載數據。
1.2 JS與QML
QML(Qt Modeling Language)是一種聲明式語言,主要用于Qt Quick中進行界面設計。QML與JavaScript緊密集成,JavaScript負責處理QML中的邏輯部分。通過在QML中使用JavaScript,可以實現復雜的事件處理、數據綁定等功能。
QML中的JavaScript語法基本遵循ECMAScript標準,因此QML開發者常常需要掌握JavaScript的基礎知識。QML支持在組件內嵌入JavaScript代碼,處理各種界面交互和計算任務。
2. 基礎語法
2.1 JS在Web中的使用
JS可以改變HTML內容,比如使用**getElementById()
**方法找到指定HTML元素并對其進行修改,也能通過這個方法找到HTML樣式(CSS)并對其進行修改。
// 找到 id==demo 的HTML元素, 并將元素內容 (innerHTML) 更改為 “Hello JavaScript”
document.getElementById("demo").innerHTML = "Hello JavaScript";
JavaScript在Web中主要通過**<script>
**標簽引入,需要使用<script> </script>
對代碼塊首尾進行標識。JS可以插入在<head>
或<body>
中,并運行在瀏覽器中。JS可以在HTML中直接編寫,或者通過外部JS文件進行引入。例如:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Simple JS Example</title>
</head>
<body><h1>Welcome to JavaScript!</h1><script>// 插入JSconsole.log('Hello, World!');</script></body>
</html>
2.2 代碼格式
JS程序是一系列計算機“指令”語句組成
基本每一個語句的結構與其他編程語言如C/C++類似,這里不再贅述。
JS使用在HTML中是需要使用分號;
分割語句的;
但是因為QML可以不使用分號區分語句,而使用換行進行區分,所以在QML中使用JS函數等都可以不用分號,注意好換行即可。
2.3 注釋
與C/C++類似,JavaScript支持如下兩種類型的注釋:
-
單行注釋:使用
//
,適用于注釋一行代碼。// 這是一個單行注釋 let a = 5;
-
多行注釋:使用
/* */
,適用于注釋多行代碼。/* 這是一個多行注釋 */ let b = 10;
2.4 輸出輸入
JavaScript通過 alert()
、prompt()
、console.log()
等方法與用戶交互。
其中使用**console.log()
**向控制臺輸出消息是JS用在QML中最多的。
-
alert():彈出警告框。
alert('Hello, World!');
-
prompt():彈出輸入框,獲取用戶輸入。
let name = prompt('What is your name?');
-
console.log():打印信息到瀏覽器控制臺,用于調試。
在瀏覽器中需要使用F12打開Console控制臺才能看到輸出,在QML中可以直接使用Qt通道輸出。
可以用其輸出各種變量,如同C中的
print()
方法。輸出多個數據使用逗號
,
隔開。console.log('Debug message'); let a = 1; let b = 2; console.log(" a: ", a, " b: ", b);
3. 變量
在JavaScript中,變量不需要指定數據類型,但需要關鍵字進行聲明變量,計算機能自動識別數據類型,關鍵字有**let
、const
** 和 var
。
let
:(2015年新引入的關鍵字,更符合使用邏輯)定義一個可變的局部變量。const
:直接定義一個常量(不是修飾作用),值不能修改。var
:(舊式變量聲明,現在應避免使用)定義具有函數作用域,盡量避免使用。
let x = 10; // 可變變量
const y = 20; // 常量
var z = 30; // 舊式變量聲明
let x += z;
注意事項:
-
支持使用一個關鍵字聲明多個變量
let person = "John Doe", carName = "Volvo", price = 200;
-
為定義的值將被賦予
undefined
-
對于
var
,在同一作用域中二次聲明不會重置值。對let
和const
不適用,不支持二次聲明。var carName = "Volvo"; var carName; // 依然等于 "Volvo"
let
和var
的根本區別:
在JS中,有一個稱為**“變量提升”**的機制,只要在代碼中使用var
聲明了變量,無論位置,解釋器都會將這個變量的聲明其提升到最初調用的位置,如下。這種情況讓變量的作用域變得不再符合邏輯,一些情況下也容易出現難以排查的錯誤。
console.log(a); // 輸出undefined,說明被正常聲明了,只是沒有賦值
var a = 1;
而使用let
和const
就不會,編譯器對變量會使用局部作用域,符合使用邏輯。
console.log(a); // 報錯,未聲明變量
let a = 1;
4. 數據類型簡述
JavaScript的數據類型包括原始類型和引用類型。
使用**typeof
**操作符查看變量的類型,可以后接()
,再加入變量,同C,也可直接接變量如下。
typeof "John" // 返回 string
typeof 3.14 // 返回 number
typeof false // 返回 boolean
typeof [1,2,3,4] // 返回 object
typeof {name:'John', age:34} // 返回 object
4.1 原始類型(基本數據類型)
支持使用對于方法名進行顯式指定聲明類型或類型轉換,注意首字母大寫
- Number:數值類型,包括整數和浮動點數。
- String:字符串類型。
- Boolean:布爾值,
true
或false
。 - Undefined:未定義,表示變量聲明但沒有賦值。
- Null:空值,表示無值。
- Symbol:ES6新增的唯一標識符,表示獨一無二的值。
- BigInt:表示大整數。
let a = BigInt(1);
console.log(typeof a, a); // bigint 1n
4.2 引用類型(復雜數據類型)
-
Object:對象,用來存儲鍵值對。聲明時使用**大括號
{}
**指定類型。 -
Array:數組,是一種特殊類型的對象。聲明時使用**中括號
[]
**指定類型。注意,使用
typeof
獲取類型時,也會輸出object
。 -
Function:函數,是可以執行的代碼塊。
-
RegExp:正則表達式。
-
Date:日期。
5. 深入數據類型
5.1 Number方法
方法 | 描述 |
---|---|
toString() | 以字符串形式返回一個數字 |
toExponential(n) | 返回一個字符串,其中數字四舍五入并使用指數表示法寫入。參數n指定小數點后面的字符數。 |
toFixed(n) | 返回一個字符串,其中包含寫入指定數量n的小數 |
toPrecision(n) | 返回一個字符串,其中的數字用 指定長度n |
valueOf() | 以數字形式返回一個數字 |
Number也有一些方法,但要注意的是這些方法不能對變量使用:
方法 | 描述 |
---|---|
Number.isInteger(number) | 判斷參數number是否是整數 |
Number.isSafeInteger(number) | 判斷參數number是否是安全整數(安全整數是可以精確表示為雙精度數字的整數) |
Number.parseFloat(str) | 解析字符串并返回一個浮點數。允許字符串有空格,但僅返回第一個數字。 |
Number.parseInt(str) | 解析字符串并返回一個整數。允許字符串有空格,但僅返回第一個數字。 |
Number.parseInt("years 10"); // 10
5.2 String方法
方法 | 描述 |
---|---|
length | 返回字符串長度 |
at(index) | 返回指定索引位置的字符的新方法,等同[] |
charAt(index) | 返回指定索引位置的字符 |
charCodeAt(index) | 返回指定索引字符的 Unicode 編碼 |
concat(str1, str2, …) | 連接兩個或多個字符串 |
includes(substring) | 檢查字符串是否包含子字符串,返回 true 或 false |
indexOf(substring) | 返回子字符串第一次出現的索引,找不到返回 -1 |
lastIndexOf(substring) | 返回子字符串最后一次出現的索引 |
slice(start, end) | 截取字符串的一部分,返回新字符串 |
substring(start, end) | 提取兩個索引之間的子字符串 |
substr(start, length) | 從起始索引提取指定長度的子字符串**(已廢棄)** |
toUpperCase() | 轉換為大寫字母 |
toLowerCase() | 轉換為小寫字母 |
trim() | 去除字符串兩端的空格 |
trimStart() /trimEnd() | 僅去除字符串開頭/結尾的空格 |
padStart(len, char) /padEnd(len,char) | 從頭/尾使用字符char填充字符串,直到給定的長度len |
replace(search, replaceWith) | 用新字符串替換匹配的部分 |
replaceAll(search, replaceWith) | 替換所有匹配的部分(ES2021+) |
split(separator) | 按指定分隔符拆分字符串為數組 |
repeat(n) | 返回重復 n 次的新字符串 |
let str = " Hello World! ";
console.log(str.trim()); // "Hello World!"
console.log(str.toUpperCase()); // " HELLO WORLD! "
console.log(str.slice(1, 5)); // "Hell"let words = "apple,banana,orange".split(','); // ["apple", "banana", "orange"]
5.3 Object方法
方法 | 描述 |
---|---|
Object.keys(obj) | 返回對象的所有鍵(屬性名)組成的數組 |
Object.values(obj) | 返回對象的所有值組成的數組 |
Object.entries(obj) | 返回對象的鍵值對數組 |
Object.assign(target, source) | 復制對象的屬性到目標對象 |
Object.freeze(obj) | 凍結對象,防止修改屬性 |
Object.seal(obj) | 允許修改現有屬性,但不能添加或刪除 |
Object.hasOwnProperty(prop) | 檢查對象是否包含指定的屬性 |
Object.getOwnPropertyNames(obj) | 返回對象所有可枚舉和不可枚舉屬性的名稱 |
Object.getPrototypeOf(obj) | 獲取對象的原型 |
Object.setPrototypeOf(obj, proto) | 設置對象的原型 |
Object.create(proto, propertiesObject) | 創建具有指定原型的新對象 |
JSON.stringify(obj) | JSON的方法,將對象轉換為 JSON 字符串 |
JSON.parse(jsonString) | JSON的方法,解析 JSON 字符串為對象 |
let person = { name: "Alice", age: 25, city: "New York" };console.log(Object.keys(person)); // ["name", "age", "city"]
console.log(Object.values(person)); // ["Alice", 25, "New York"]
console.log(Object.entries(person)); // [["name", "Alice"], ["age", 25], ["city", "New York"]]let newPerson = Object.assign({}, person, { age: 30 });
console.log(newPerson); // { name: "Alice", age: 30, city: "New York" }let jsonString = JSON.stringify(person);
console.log(jsonString); // '{"name":"Alice","age":25,"city":"New York"}'let parsedObject = JSON.parse(jsonString);
console.log(parsedObject); // { name: "Alice", age: 25, city: "New York" }
5.4 Array方法
方法 | 描述 |
---|---|
at(index) | 獲取編號為index的元素的新方法,與[] 相同作用 |
length | 獲取數組中元素個數 |
toString() | 將數組轉換為逗號分隔數組各值的字符串 |
join(separator) | 轉換為指定分隔符的字符串,通過參數separator來替換默認的逗號 |
push(item1, item2, ...) | 在數組末尾添加一個或多個元素 |
pop() | 刪除數組的最后一個元素并返回該元素 |
unshift(item1, item2, ...) | 在數組開頭添加一個或多個元素 |
shift() | 刪除數組的第一個元素并返回該元素 |
concat(arr2, arr3, ...) | 合并兩個或多個數組,返回新數組 |
copyWithin(index1, index2, index3) | 將索引index1的元素復制到索引index2到index3。也可以不寫index3,即只復制給index2。(該方法只是覆蓋現有元素,不會增加新元素) |
flat() | 平展數組,將多維度數組平展到一維。 |
flatMap() | 首先映射數組的所有元素 然后通過展平數組來創建新數組。 |
indexOf(item) | 返回元素第一次出現的索引,找不到返回 -1 |
lastIndexOf(item) | 返回元素最后一次出現的索引 |
includes(item) | 檢查數組是否包含某個元素,返回 true 或 false |
find(callback) | 返回符合條件的第一個元素,參數是一個回調函數 |
findLast(callback) | 從數組末尾開始執行find() |
findIndex(callback) | 返回符合條件的第一個元素的索引 |
filter(callback) | 返回符合條件的所有元素組成的新數組 |
map(callback) | 遍歷數組并對每個元素執行回調,返回新數組 |
forEach(callback) | 遍歷數組并對每個元素執行回調,無返回值 |
reduce(callback, initialValue) | 通過回調函數累積數組元素,返回單個值 |
reverse() | 反轉數組順序 |
sort(compareFunction) | 按指定規則對數組排序(默認按字符編碼順序) |
slice(start, end) | 截取數組的一部分,返回新數組,不修改原數組 |
splice(start, deleteCount, item1, item2, …) | 從指定索引位置刪除或插入元素,修改原數組 |
const fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.join(" * "); // Banana * Orange * Apple * Mangolet arr = [1, 2, 3];
arr.push(4); // [1, 2, 3, 4]
arr.pop(); // [1, 2, 3]
arr.unshift(0); // [0, 1, 2, 3]
arr.shift(); // [1, 2, 3]let newArr = arr.concat([4, 5]); // [1, 2, 3, 4, 5]const myArr = [[1,2],[3,4],[5,6]];
const newArr = myArr.flat(); // [1, 2, 3, 4, 5, 6]
const myArr2 = [1, 2, 3, 4];
const newArr2 = myArr.flatMap(x => [x, x * 10]);
// [1, 10, 2, 20, 3, 30, 4, 40]arr.reverse(); // [3, 2, 1]
arr.sort(); // 默認按字符編碼順序排序const numbers = [4, 9, 16, 25, 29];
let first = numbers.find(myFunction); // 25
function myFunction(value, index, array) {return value > 18;
}
6. 運算符
JavaScript支持常見的運算符,包括算術運算符、比較運算符、邏輯運算符等。
基本與C/C++一樣,要注意比較運算符的嚴格等于/嚴格不等于
-
算術運算符
也支持縮寫:
x += 2
加法:
+
;減法:-
;乘法:*
;除法:/
;取余:%
;自增:++
;自減:--
。 -
比較運算符
- 等于:
==
。只會比較值是否一致 - 不等于:
!=
- 嚴格等于:
===
。會比較數據類型是否一致。 - 嚴格不等于:
!==
* - 大于:
>
- 小于:
<
- 大于等于:
>=
- 小于等于:
<=
let a = 11; let b = "11"; console.log(a == b); // 輸出 true console.log(a === b); // 輸出 false
- 等于:
-
邏輯運算符
與:
&&
;或:||
;非:!
。 -
位運算符
與:
&
;或:|
;取反:~
;左移:<<
;右移:>>
;無符號右移:>>>
。
7. 流程控制
JavaScript提供了多種控制結構來實現條件判斷和循環。
7.1 條件語句
-
if
:條件判斷。if (x > 10) {console.log('x is greater than 10'); } else {console.log('x is less than or equal to 10'); }
-
switch
:多條件判斷。switch (day) {case 1:console.log('Monday');break;case 2:console.log('Tuesday');break;default:console.log('Unknown day'); }
7.2 循環
-
for
:常規循環。for (let i = 0; i < 5; i++) {console.log(i); }
-
while
:條件為true
時繼續循環。let i = 0; while (i < 5) {console.log(i);i++; }
-
do...while
:至少執行一次循環。let i = 0; do {console.log(i);i++; } while (i < 5);
8. 函數
格式類似Python格式,JavaScript通過function
關鍵字來定義函數。
8.1 函數定義
function add(a, b) {return a + b;
}
let result = add(5, 10); // 15
8.2 匿名函數和箭頭函數
JavaScript支持匿名函數和箭頭函數,它們可以作為值傳遞給其他函數或事件處理器。
// 匿名函數
let multiply = function(a, b) {return a * b;
};// 箭頭函數
let divide = (a, b) => a / b;
9. 類
JavaScript是面向對象的編程語言,支持類(class)和對象(object)。格式也比較類似Python。
class Person {constructor(name, age) {this.name = name;this.age = age;}greet() {console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);}
}let person1 = new Person('John', 30);
person1.greet(); // "Hello, my name is John and I am 30 years old."
10. 異常處理
10.1 try...catch
JavaScript 提供 try...catch
語句來處理可能出現的錯誤:
try
代碼塊:放置可能會拋出異常的代碼。catch
代碼塊:當try
代碼塊中發生異常時,catch
代碼塊會被執行,并獲取錯誤信息。
try {// 可能會發生錯誤的代碼
} catch (error) {// 處理錯誤的代碼console.log(error.message);
}
10.2 try...catch...finally
finally
代碼塊:無論是否發生異常,都會執行。finally
常用于關閉資源(如數據庫連接)或清理操作。
try {// 可能會發生錯誤的代碼
} catch (error) {// 處理錯誤的代碼
} finally {// 無論是否發生錯誤,都會執行
}
10.3 throw
關鍵字
- JavaScript 允許使用
throw
關鍵字主動拋出異常,可以拋出 任意類型(字符串、對象、Error 實例等)。 - 拋出異常后,代碼執行會立即停止,并跳轉到
catch
代碼塊。
throw "錯誤信息"; // 拋出字符串
throw 100; // 拋出數字
throw new Error("自定義錯誤"); // 拋出 Error 實例
function divide(a, b) {if (b === 0) {throw new Error("除數不能為 0");}return a / b;
}try {console.log(divide(10, 2)); // 正常執行console.log(divide(5, 0)); // 拋出異常
} catch (error) {console.log("捕獲錯誤:" + error.message); //輸出:捕獲錯誤:除數不能為 0
}
10.4 Error
對象
JavaScript 提供 Error
構造函數來創建錯誤對象:
new Error(message); // 創建一個通用錯誤對象
new TypeError(message); // 類型錯誤
new ReferenceError(message); // 引用錯誤
new SyntaxError(message); // 語法錯誤
try {throw new TypeError("變量類型錯誤!");
} catch (error) {console.log(error.name); // TypeErrorconsole.log(error.message); // 變量類型錯誤!
}
10.5 常見錯誤類型
錯誤類型 | 說明 | 示例 |
---|---|---|
Error | 通用錯誤 | throw new Error("普通錯誤"); |
ReferenceError | 引用了不存在的變量 | console.log(x); // x is not defined |
TypeError | 變量或參數不是期望的類型 | null.toString(); |
SyntaxError | 語法錯誤 | eval("console.log(123"); |
RangeError | 數值超出范圍 | new Array(-1); |