进一步了解Js

本文作为系统学习js的笔记。主要参考了这篇文档中的内容。

什么是javascript?#

js是

  • 一门脚本语言:js 可以作为用来编写 自动执行某些任务控制其他对象 的脚本的 语言
  • 一门 面向对象的语言
  • 一门 跨平台的语言:在浏览器中,JavaScript 可以改变网页(DOM)的外观与样式。同样地,在服务器上,Node.js 中的 JavaScript 可以对浏览器上编写的代码发出的客户端请求做出响应。

但js和java没有必然的联系。最初好像是创始者蹭java的热度?

此外,js也有规范:ECMAScript规范。

开始正式的总结:#

推荐使用 严格模式 。也即在代码开头加一句"use strict";

语法和数据类型:#

js是

  • 大小写敏感的;
  • 使用unicode字符集的:可以支持法文等等,你甚至可以写const 按钮 = document.getElementById('certain-button');,不过保留字都是英文的,这样反而不方便。

注释:#

支持

  • 单行注释// 这是一段单行注释
  • 多行注释
    1
    2
    3
    4
    5
    6
    7
    8
    /* 
    这是多行注释
    这是多行注
    这是多行
    这是多
    这是

    */
    并且不能 嵌套注释

声明与变量:#

支持

  • var:声明一个变量,可选初始化一个值;
  • let:声明一个块作用域的局部变量,可选初始化一个值;
  • const:声明一个块作用域的只读常量。

同时也可以像 python 那样直接赋值,例如 x = 42,但这(如果在函数外声明的话)是一个全局变量,容易造成混乱(在严格模式下会产生错误)。

支持 解构赋值

变量值:#

varlet声明的变量,如果没有赋初始值,则其值为undefined

如果访问一个未声明的变量会导致抛出 ReferenceError 异常.

可以使用input === undefined来判断某个变量是否已经赋值。特别的,undefined在布尔类型环境中会被当做false;在数值类型环境中会被当作NaN

而与之对应的null变量在数值类型环境中会被当作 0 来对待,而布尔类型环境中会被当作 false

变量的作用域:#

  • 函数之外声明的变量叫做 全局变量,可以被任何其他代码访问(但需要一定方法);
  • 函数内部声明的变量叫做 局部变量,只能在当前函数的内部访问。

事实上,全局变量是 全局对象 的属性。在网页中,默认的全局对象是window

变量提升:#

你可以先使用变量,稍后再声明变量;同时注意,每个函数都有独立的作用域,即使函数内部使用了相同名称的变量,还是会创建一个新的变量。例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 例子 1
*/
console.log(x === undefined); // true
var x = 3;

/**
* 例子 2
*/
// will return a value of undefined
var myvar = "my value";

(function () {
console.log(myvar); // undefined
var myvar = "local value";
})();

对于函数(在js中也是一种变量)而言,只有函数声明会被提升,而函数表达式不会。例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* 函数声明 */

foo(); // "bar"

function foo() {
console.log("bar");
}

/* 函数表达式 */

baz(); // 类型错误:baz 不是一个函数

var baz = function () {
console.log("bar2");
};

常量:#

可以使用const创建一个只读的常量。必须赋初值。作用域和let变量相同。

然而,对象数组 被赋值为常量却不受保护。

数据类型:#

七种基本数据类型:

  • boolean
  • null
  • undefined
  • Number:整数或者浮点数,js中没有专门的 int 或者 float
  • BigInt:任意精度的整数,可以安全地存储和操作大整数。
  • String
  • Symbol:其实例唯一且不可改变的数据类型;

对象

数据类型的转换:#

js是一门动态类型语言,因此声明变量的时候可以不必指定数据类型,在代码执行的时候会根据需要进行自动转换。

在包含的数字和字符串的表达式中使用加法运算符(+),JavaScript 会把数字转换成字符串。在涉及其他运算符时,JavaScript 语言不会把数字变为字符串。前者会被解释为strcat

使用

  • parseInt()
  • parseFloat()

来将字符串转换数字,但这个转换比较抽象。

或者也可以使用 一元加法运算符

1
2
3
"1.1" + "1.1" = "1.11.1"
(+"1.1") + (+"1.1") = 2.2
// 注意:加入括号为清楚起见,不是必需的。

字面量:#

在 JavaScript 中,你可以使用各种字面量。这些字面量是脚本中按字面意思给出的固定的值,而不是变量。

常见的有:

  • 数组字面量
  • 布尔字面量
  • 数字字面量
  • 对象字面量
  • RegExp 字面量
  • 字符串字面量

数组:#

数组字面值是一个封闭在方括号对 ([]) 中的包含有零个或多个表达式的列表,其中每个表达式代表数组的一个元素。

例如

1
2
3
4
5
6
7
var coffees = ["French Roast", "Colombian", "Kona"];

var a = [3];

console.log(a.length); // 1

console.log(a[0]); // 3

这里的数组字面值也是一种 对象初始化器;此外,你不必列举数组字面值中的所有元素,可以 连写两个逗号 来产生一个没有指定的元素,初始值为undefined;同时,(只有)元素列表的结尾的逗号将会被忽略。

建议将缺失元素直接写成undefined,提高代码清晰度。

数组字面值具有类似变量那样的作用域。

布尔:#

布尔对象是对布尔类型的包装。布尔类型包括true/false

数字:#

多种基数的 整数字面量 和以10为基数的 浮点数字面量
其形式完全类似于 C语言。

对象:#

封闭在花括号对中的一个对象的零个或多个 键值对 的列表。

合法属性名可以使用.来获取;非法属性名则要使用 方括号表示法 ,其实也就是使用字符串作为下标。

一些比较新的特性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var obj = {
// 设定对象的原型为 `theProtoObj`
__proto__: theProtoObj,

// 属性 `handler` 的值来自外部同名变量 `handler`
handler,

// 对象方法 `toString`,调用 `super.toString()` 来获取父类的 `toString` 结果
toString() {
return "d " + super.toString();
},

// 动态计算属性名 `prop_42`,其值为 `42`
["prop_" + (() => 42)()]: 42,
};

RegExp:#

regular-expression,也即常说的 正则表达式 ,是字符被 正斜杠 围起来的表达式,类如var re=/ab+c/;

字符串字面量:#

使用''/""括起来的字面量。

ES2015中还提供了一种 模板字面量 ,可以帮你构造字符串,类似于 字符串插值

除此之外,你可以在通过模板字符串前添加一个 tag 来自定义模板字符串的解析过程,这可以用来防止注入攻击,或者用来建立基于字符串的高级数据抽象。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Basic literal string creation
`In JavaScript '\n' is a line-feed.` // Multiline strings
`In JavaScript this is
not legal.`;

// String interpolation
var name = "Bob",
time = "today";
`Hello ${name}, how are you ${time}?`;

// Construct an HTTP request prefix is used to interpret the replacements and construction
POST`http://foo.org/bar?a=${a}&b=${b}
Content-Type: application/json
X-Credentials: ${credentials}
{ "foo": ${foo},
"bar": ${bar}}(myOnReadyStateChangeHandler)`;

字符串:#

流程控制与错误处理:#

最基本的语句是用于组合语句的 语句块 。该块由一对大括号{}界定;

块语句不会特别产生一个作用域,如下代码

1
2
3
4
5
var x = 1;
{
var x = 2;
}
alert(x);

输出结果是 2,因为括号内声明的变量和之前的变量在同一个作用域内。并且还因为js允许重复声明变量,后声明的变量会覆盖之前声明的。

if:#

形式和C语言相同。

这些值:

  • false
  • undefined
  • null
  • 0
  • NaN
  • “”

作为判断条件的时候视为false。其他为真。

不要混淆布尔值和Boolean对象。

switch:#

和C语言完全相同。

异常:#

循环与迭代:#

支持和C语言形式上完全相同的for,while,do,break,continue;以及新的label,for...in and for...of

label#

label语法相当于goto的语法糖。方便进行多层循环的控制。例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var num = 0;
outPoint: for (var i = 0; i < 10; i++) {
for (var j = 0; j < 10; j++) {
if (i == 5 && j == 5) {
break outPoint; // 在 i = 5,j = 5 时,跳出所有循环,
// 返回到整个 outPoint 下方,继续执行
}
num++;
}
}

alert(num); // 输出 55


var num = 0;
outPoint: for (var i = 0; i < 10; i++) {
for (var j = 0; j < 10; j++) {
if (i == 5 && j == 5) {
continue outPoint;
}
num++;
}
}
alert(num); // 95

注意这里的break and continue的用法,其可以对某循环直接操作。

for...in:#