Javascript
本文基于《现代Javascript教程》记录,速通较凌乱,有错误希望指出。
基础的内置知识
helloworld:
...
<script>
alert("Hello, world!");
</script>
...
也可以使用script标签中的src属性来引入外界的js代码,不赘叙。
代码结构
每句结尾加分号,换行符被理解为隐式的分号,所以不加也可以。
注释用/**/或者//。
现代模式
"use strict";放在脚本的最顶部表明启用严格模式,一旦启用不能退出。
"class"和"module"会自动启用use strict。
变量
使用let关键词生成一个变量(完了我怎么记得我之前用的都是var啊),显而易见的弱类型语言。
不重复声明一个变量。
命名规则:
- 变量名称必须仅包含字母、数字、符号
$和_。 - 首字符必须非数字。
保留字列表规定了所有不能被作为变量名称的词。
声明一个常数不会去改变之,使用const关键字。
数据类型
动态类型语言(如js)也就是不限制被声明后变量的数据类型,可以随意改变之。
number类型
整数浮点数不论,我们看Infinity与NaN。
Infinity表示无穷大,可以使用除以0来得到。
NaN表示计算错误,可以出现在不正确或执行未定义的数字操作,比如"man!what can i say"/0。它是粘性的,也就是说对NaN的任何操作都使得结果为NaN。
BigInt类型
"number" 类型无法安全地表示大于 (253-1)(即 9007199254740991)或小于 -(253-1) 的整数。
更准确的说,"number" 类型可以存储更大的整数(最多 1.7976931348623157 * 10308),但超出安全整数范围 ±(253-1) 会出现精度问题,因为并非所有数字都适合固定的 64 位存储。因此,可能存储的是“近似值。
console.log(9007199254740991 + 1); // 9007199254740992
console.log(9007199254740991 + 2); // 9007199254740992
在结尾添加"n"表明这是一个BigInt类型的数字。
String类型
三种方式表示字符串,即'str'、"str"、`str`。
反引号是 功能扩展 引号。它们允许我们通过将变量和表达式包装在 ${…} 中。
也就是:
let name = "Dremig";
console.log(`Hello,${name}`); // 变量包装
console.log(`${1+1}`) // 表达式包装
Boolean类型(逻辑类型)
true or false,也可以作为运算的结果,如let iscorrect = 4 > 1; // iscorrect = true
null类型
简单表示某个变量/常量"未知"。
undefined类型
表示某个变量/常量"未被赋值",作为未被赋值初始化的值的默认初始值。
Object类型与Symbol类型
typeof运算符
typeof undefined // "undefined"
typeof 0 // "number"
typeof 10n // "bigint"
typeof true // "boolean"
typeof "foo" // "string"
typeof Symbol("id") // "symbol"
typeof Math // "object" (1)
typeof null // "object" (2)
typeof alert // "function" (3)
以字符串的形式返回数据类型。
可以上手试试typeof null其实应该是null对吧?这是js官方自己承认的错误。
typeof(x)也有同样的效果,但是typeof(x)作为一个操作符。
交互:alert与prompt与confirm
我记得这三位都是输出弹窗来着。
alert
刚刚maybe已经见识过了。

prompt
接收两个参数,即title与default指定input框的默认值。

prompt将返回用户在input框内输入的文本,如果用户取消了输入,则返回null。
confirm
接收问题参数,确定返回true,取消返回false。

类型转换
字符型转换
alert自动将所有类型转换为String进行显示。
可以显式地使用String(...)来体现这一过程。
数字型转换
算术运算符则自动将类型转换为number。
可以显式地使用Number(...)来体现这一过程。
| value | change into |
|---|---|
| undefined | NaN |
| boolean | true:1 false:0 |
| null | 0 |
| string | 去掉首尾空白字符(空格、换行符 \n、制表符 \t 等)后的纯数字字符串中含有的数字。如果剩余字符串为空,则转换结果为 0。否则,将会从剩余字符串中“读取”数字。当类型转换出现 error 时返回 NaN。 |
console.log(Number(" 123 ")); // 123
console.log(Number("123z")); // NaN
布尔型转换
逻辑运算符自发转换,Boolean(...)经典也干了。
- 直观上为“空”的值(如
0、空字符串、null、undefined和NaN)将变为false。 - 其余就是
true。
基础运算符,数学运算
运算元就是运算符针对的对象。
数学运算符
除了加减乘除就是多了两个%取余与**求幂运算。
+可以用于拼接字符串。
如果一个运算元是字符串那么另一个也会被转换为字符串。
console.log(1 + "2"); // "12"
console.log("1" + 2); // "12"
console.log(2 + 2 + "1") // "41"
console.log("1" + 2 + 2) // "122"
只有我们牢加号可以这样用,其余都只对数字起作用,如果不是数字就强制类型转换为数字。
+还可以用于将非Number类型转换为Number类型,这就与Number(...)类似。
优先级
一元运算符优先级高于二元运算符。
其余我认为小学的时候就可能会了。
赋值
即=,我们已经认识到,它的优先级真的很低。
let a = 1;
let b = 2;
let c = 3 - (a = b + 1);
console.log(a); // 3
console.log(c); // 0
链式赋值懒得提了。
原地修改
就是类似n = n + 1这种代码,现在有+=这种类似的缩写来实现了。
自增++与自减--。
自增/减的前置返回一个新的操作值,后置则返回原来值。
// a.js
let a = 1;
let b = a++;
console.log(b); // 1
// b.js
let a = 1;
let b = ++a;
console.log(b); // 2
位操作
不提了,C学的够多了。
逗号运算符
我造,原来这也是运算符?
let a = (1 + 2, 3 + 4);
console.log(a); // 7
返回最后一个,由于是所有运算符中优先级最低的,记得使用括号。
值的比较
最成梗的一章。
比较结果是true or false,也就是布尔类型,这是显然的。
数字的比较想必不必多提,字符串的比较是按位比较,按照unicode顺序。
console.log("b" > "a"); // false
console.log("al" > "aa"); // true
console.log("aaa" > "aa"); // true
对于不同类型的比较,首先被转换为数字比较。
alert("2" > 1) // true
alert("01" == 1) // true
===严格相等不仅检查值,还检查类型是否一致。
console.log(null == undefined); // true
console.log(null === undefined); // false
相等性检查与比较检查的逻辑是区分开来的。
console.log(null == 0) // false
console.log(null > 0) // false
console.log(null >= 0) // true
console.log(undefined == 0) // false
console.log(undefined > 0) // false
console.log(undefined >= 0) // false
条件分支
if和c一模一样,不想看了。
?...:...组合实际是用于多个条件的连续判断,某个?后的内容不通过就依靠:继续传递。
函数
一般函数
函数声明:
function sayHi(){
alert("Hello~");
}
函数表达式:
let sayHi = function(){
alert("Hello~");
}
需要重申的是,函数是一个值,如果alert它,会弹出其代码。
复制操作:
function sayHi(){
alert("Hello~");
}
let func = sayHi;
func(); // Hello~
甚至还可以把函数作为参数传递给另一个函数。
function ask(question, yes, no) {
if (confirm(question)) yes()
else no();
}
function showOk() {
alert("You agreed.");
}
function showCancel() {
alert("You canceled the execution.");
}
let age = 16; // 拿 16 作为例子
if (age < 18) {
welcome(); // \ (运行)
// |
function welcome() { // |
alert("Hello!"); // | 函数声明在声明它的代码块内任意位置都可用
} // |
// |
welcome(); // / (运行)
} else {
function welcome() {
alert("Greetings!");
}
}
// 在这里,我们在花括号外部调用函数,我们看不到它们内部的函数声明。
welcome(); // Error: welcome is not defined
箭头函数
对于函数比较简短的书写。
// let func = function(arg1, arg2, ..., argN) { return expression; }
// change into this form
let func = (arg1, arg2, ..., argN) => expression
如果我们只有一个参数,就可以省略其括号,例如:
let double = n => n * 2;
alert(double(3)); // 6
这对于简单的操作挺简单的,复杂的操作...其实差不是太多。
它还有括号形式:
let func = (arg1, arg2, ..., argN) => {body}
body体内可以编写多条语句。
Javascript特性
啥都没有啊。
循环不会可以进厂了,switch简直一模一样啊。
ok结束。
忍者代码
笑死我了,这也太搞了。
概括:你代码写的是个牛魔,根本没有可替代性,因为公司都不想要你。
对象
老生常谈了。
也是简单的属性和方法。
let user = { // 一个对象
name: "John", // 键 "name",值 "John"
age: 30 // 键 "age",值 30
};
这些添加的键值就是对象的属性。
很经典的用.调用属性,不论。
可以使用delete user.name移除属性。
属性的键值如果是有空格的就需要引号。
但是我们思考一个情况,我们怎么调用它呢?比如"the first letter of the name"这种,这样的可以使用user["the first letter of the name"]来调用。
还有一个比较有灵活性的用法:
let user = {
name: "John",
age: 30
};
let key = prompt("What do you want to know about the user?", "name");
// 访问变量
alert( user[key] ); // John(如果输入 "name")
一个叫做"计算属性"的方法,其实就是从哪个变量获取属性名。
let fruit = prompt("Which fruit to buy?", "apple");
let bag = {
[fruit]: 5, // 属性名是从 fruit 变量中得到的
};
alert( bag.apple ); // 5(如果输入 "apple")
属性名简写是这样一个操作:
function makeUser(name, age) {
return {
name: name, // 只写一个name,也可以
age: age, // 同理,只写一个age也可以
// ……其他的属性
};
}
let user = makeUser("John", 30);
alert(user.name); // John
就是说,如果属性名和变量名一样,就可以省略。
没有某个属性即将其定义为undefined。