P1 开发者工具的使用 与 JavaScript 基础教程
开发者工具的使用
F12 或者 菜单 -> 更多工具 -> 开发者工具 调出
切换中文
更改语言后重新打开开发者工具生效

或者

界面简介
-
元素
HTML 原文
HTML节点的属性
-
控制台
在任意Tab按ESC可以在下方调出
-
源代码
浏览网站中的所有资源
调试代码
-
网络
抓包工具
-
应用
查看本地储存的内容 Cookie Session LocalStorage
JavaScript 基础教程
一些 JavaScript 学习资源
MDN 文档: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript
廖雪峰: https://www.liaoxuefeng.com/wiki/1022910821149312
菜鸟教程: https://www.runoob.com/js/js-tutorial.html
uTools 插件
基本特性
- 单线程
- 弱类型 / 动态类型
- 大小写敏感
',"通用- 不强制使用分号 (建议统一)
- 语法很灵活
运行时:
v8, NodeJS
基础语法
注释
//单行注释
/*
多行注释
*/
变量与常量
赋值操作符 var let const
//定义变量/常量
var a = 1;
var b;
let c = 1;
let d;
const e = 4;
//a,b,c,d,e 1 undefined 1 undefined 4
console.log("a,b,c,d,e",a,b,c,d,e);
//Uncaught SyntaxError: Missing initializer in const declaration
const f;
//赋新值
a = 2;
c = 3;
//Uncaught TypeError: Assignment to constant variable.
e = 1;
//重复定义
//undefined
var a = 6;
let c = 6;
//Uncaught SyntaxError: Identifier 'a' has already been declared
let a = 6;
//Uncaught SyntaxError: Identifier 'a' has already been declared
const a = 6;
//常量覆盖
const e = 6;
//e 6
console.log("e",e);
//在子域中覆盖(ES6引入)
var ts = 1;
let he = 2;
{
var ts = "aaa";
let he = "yyy";
//ts,he aaa yyy
console.log("ts,he",ts,he);
}
//ts,he aaa 2
console.log("ts,he",ts,he);
-
var 定义一个
变量 -
let 定义一个仅在作用域内生效的
变量 -
const 定义一个
常量,一旦定义无法修改,但是可以覆盖定义 -
使用相同的操作符可以覆盖定义同名的变量,但是不建议这么使用
-
使用
let覆盖定义时不影响父作用域的同名变量 -
强烈推荐优先使用
let定义变量,如果值不需要改变,建议使用const定义成常量 -
函数提升
//函数提升
foo(); // "bar"
function foo() {
console.log("bar");
}
//这种写法的函数不会被提升
bar(); // 类型错误:bar 不是一个函数
var bar = function() {
console.log("bar2");
};
作用域
{ } 定义代码作用域 (ES6的内容)
使用 let 定义的变量,在子域可以访问父域的变量,但是父域不能访问子域的变量
函数中定义的内容外部无法访问
子域中定义的函数,父域无法访问
//顶级作用域(最外层的作用域)
let x = 114;
{
//子作用域
let b = 514;
//x,b 114 514
console.log("x,b", x, b);
}
//函数内部其实也是一种作用域
function xbz() {
let c = 233;
//x,c 114 233
console.log("x,c", x, c);
//Uncaught ReferenceError: b is not defined
console.log("b", b);
}
xbz();
//匿名函数同理
(() => {
let d = 3.14;
//x,d 114 3.14
console.log("x,d", x, d);
//Uncaught ReferenceError: b is not defined
console.log("b", b);
})();
//另一种写法
(function() {
let d = 3.14;
//x,d 114 3.14
console.log("x,d", x, d);
//Uncaught ReferenceError: b is not defined
console.log("b", b);
})();
//x 114
console.log("x", x);
//Uncaught ReferenceError: b is not defined
console.log("b", b);
//Uncaught ReferenceError: c is not defined
console.log("c", c);
//Uncaught ReferenceError: d is not defined
console.log("d", d);
一模一样的代码,只是使用 var 而不是 let ,可访问性略有区别
//顶级作用域(最外层的作用域)
var x = 114;
{
//子作用域
var b = 514;
//x,b 114 514
console.log("x,b", x, b);
}
//函数内部其实也是一种作用域
function xbz() {
var c = 233;
//x,c 114 233
console.log("x,c", x, c);
//b 514
console.log("b", b);
}
xbz();
//匿名函数同理
(() => {
var d = 3.14;
//x,d 114 3.14
console.log("x,d", x, d);
//b 514
console.log("b", b);
})();
//x, 114
console.log("x", x);
//b, 514
console.log("b", b);
//Uncaught ReferenceError: c is not defined
console.log("c", c);
//Uncaught ReferenceError: d is not defined
console.log("d", d);
数据类型
-
基础类型
-
数值
整数
浮点数(小数)
NaN(跟任何值比较都是false) -
字符串
" "
' '
` `(模板字符串,可以用${ }直接引用程序中的变量)let a = 1; //'a=1' `a=${a}` -
布尔
truefalse
-
-
对象 object
-
Array 数组
[ xxx, xxx ]new Array(xxx, xxx)属性:
length元素个数
方法:
-
at获取指定索引的元素,找不到返回underfined,等效于Array[index] -
contact拼接另一个可迭代元素,不影响原数组 -
indexOf查找元素位置,索引从0开始,找不到返回-1 -
includes是否包含元素,返回布尔 -
join使用分隔符将列表元素合并成字符串 -
push在末尾添加元素,返回数组长度 -
pop移除末尾元素,返回被移除的元素 -
unshift在数组首位添加元素,返回数组长度 -
shift移除首位元素,返回被移除的元素 -
slice切片,不影响原数组,返回切片后的新数组 -
some传入lambda表达式,如果列表中含有符合表达式的元素,返回true,反之返回false -
filter传入lambda表达式,返回一个包含符合表达式的元素的新列表 -
find传入lambda表达式,返回第一个符合表达式的元素,没有匹配则返回undefined -
sort传入lambda表达式,返回排序后的数组 -
forEach传入lambda表达式,将列表的每一个元素代入执行
-
字典
{"key": value}示例
let dict = {}; //添加键值对 dict["a"] = 1; dict.b = 2; //{a: 1, b: 2} console.log(dict); //一个字典中键名不会重复 dict.b = 3; //{a: 1, b: 3} console.log(dict); //读取键值对, 不存在的键名返回 underfined //1 console.log(dict.a); //3 console.log(dict["b"]); //undefined console.log(dict["c"]); -
Map 字典
new Map(); Map.set(key,value);属性
size键值对数量
方法
-
set添加键值对 -
get通过键名获取键值, 不存在时返回underfined -
clear清空字典 -
has是否含有指定的键名 -
delete删除指定键值对 -
keys返回键名的可迭代对象 -
forEach传入lambda表达式,将字典的每一个键名和键值一起代入执行
-
Set 集合
new Set()集合中元素是唯一的,可以用来去重,内部元素无序,无法通过索引访问
属性
size键值对数量
方法
-
add添加元素 -
delete删除元素 -
clear清空集合 -
has是否有指定元素 -
entries返回集合的可迭代对象 -
keys返回集合的可迭代对象 -
forEach传入lambda表达式,将集合中的每一个元素代入执行
-
-
函数 function
获取变量类型
typeof(xx)
数据类型转换
Boolean(any) //任意类型转布尔
String() //所有类型都可以用这个转成字符串
Number() //任意类型转数值类型,转换失败返回NaN
parseFloat(any) //转换失败返回NaN
parseInt(any) //转换失败返回NaN
object.toString() //基础类型没有这个方法
变量比较的坑 == 与 === ( = 是赋值操作符)
-
==比较操作符,自动隐式类型转换 -
===绝对等于,不允许自动类型转换 -
NaN跟任意值比较结果都是false -
推荐优先使用
===判断是否相等 -
一些被认为是
false的值falseunderfinednull0NaN""
执行流
-
if 条件判断
if( /* 表达式 */ ) { //表达式运算结果转换为布尔为 true 时执行该块 } else if( /* 表达式2 */ ) //也可以使用 else if 连续判断多个表达式 { //可以存在任意和 else if 子句,也可以省略 //表达式2运算结果转换为布尔为 true 时执行该块 } else { //else 子句可以省略 //表达式1和表达式2的运算结果转换为布尔都为 false 时执行该块 } //示例 let a = 500; if(a > 514){ console.log(1); } else if(a < 114){ console.log(2); } else{ console.log("啊啊啊"); } //"啊啊啊" -
switch 分支
switch ( /* 表达式 */ ) { case /* 值1 */: //表达式计算结果等于值1时执行从case到第一个break之间的语句 [break;]//不写break的话会case语句 case /* 值2 */: //表达式计算结果等于值2时执行从case到第一个break之间的语句 [break;] //可以存在任意个case default: //只能写在最后, 可以省略 //当表达式的值不满足任意一个case, 或者没有遇到break跳出时执行这里的语句 [break;]//可以写break,但是没有必要 } //示例 for(let x=0; x<5; x++) { switch (x){ case 1: console.log('1'); case 2: case 4: console.log('2 or 4'); break; default: console.log('default'); } } /* default 1 2 or 4 2 or 4 default 2 or 4 */ -
for 循环
-
for
最通用的计数循环
for(/* 初值设定,只执行一次 */ ; /* 表达式,满足条件则执行循环 */ ; /* 每次循环后执行 */){ //循环执行这里的语句 } //例子 for (let i = 0; i < 5; i++) { console.log(i); } //0 1 2 3 4 const list = [1,2,3,4,5]; for (let i=0; i < list.length; i++){ console.log(list[i]); } //1 2 3 4 5 -
for...in
自动枚举对象的
可枚举属性,适用于枚举字典,一般不适用于数组和集合不能在循环体内修改迭代对象
//错误示范 const list = [9,8,7,6,5]; for(let x in list){ console.log(x); } //0 1 2 3 4 //获取的实际上是元素的下标 const set = new Set([1,2,3,4,5]); for(let x in set){ console.log(x); } //无输出 //为什么会得到这样的结果?

//对字典使用则会得到预期的结果 const dict = {'a':1,'b':2,'c':3}; for(let x in dict){ console.log(x); } //a b c
for...in 循环还可以用来迭代
对象的属性
-
for...of 循环
自动枚举可迭代对象的每一个元素 ,适用于任何可迭代对象,
字典不可直接迭代不能在循环体内修改迭代对象
const list = [9,8,7,6,5]; for(let x of list){ console.log(x); } //9 8 7 6 5 const set = new Set([1,2,3,4,5]); for(let x of set){ console.log(x); } //1 2 3 4 5 //错误示例 const dict = {'a':1,'b':2,'c':3}; for(let x of dict){ console.log(x); } //TypeError: dict is not iterable -
forEach 循环
严格意义上来说是属于部分可迭代对象的原型方法 (
Prototype),而不是通用操作符需要传入一个函数,执行过程就是把可迭代对象的每个元素代入函数中执行,因为每次循环都相当于调用函数,因此效率远不如上面的几种 for 循环
const list = ['a', 'b', 'c']; list.forEach(x => console.log(x)); //a b c //相当于 list.forEach(function(x) { console.log(x); });执行速度 for > for...in / for...of >>> forEach
-
-
while 循环
-
while
类似
for循环,满足循环条件就会一直执行循环体while(/* 循环条件为 true 则进入循环 */) { /* 循环执行体 */ } //例子 let x = 3; while(x--){ console.log(x); } //2 1 0 //要注意避免出现死循环 -
do...while
在执行循环体后才会检查循环条件,也就是说至少会执行一次循环体
do { /* 循环执行体 */ } while(/* 循环条件为 true 则进入循环 */) //例子 let x = 3; do { console.log(x); } while(x--); //3 2 1 0
-
-
循环操作
-
continue
跳过执行当前循环体,进行下一轮循环
//跳过执行部分循环 let x = 0; while(x++ < 10) { if(x % 3 == 0){ continue; } console.log(x); } //1 2 4 5 7 8 10 //使用 label 自由控制外部循环 var i = 0; var j = 10; checkiandj: while (i < 4) { console.log('i',i); i += 1; checkj: while (j > 4) { console.log('j',j); j -= 1; if ((j % 2) == 0) { continue checkj; } console.log(j + ' 是奇数。'); } console.log('i = ' + i); console.log('j = ' + j); } -
break
结束当前循环体
//结束循环 const a = [1,2,3,4,5]; for (i = 0; i < a.length; i++) { if (a[i] == 3) { break; } console.log(a[i]); } //1 2 //也可以指定 label 终止外部循环 let x = 0; let z = 0 labelCancelLoops: while (true) { console.log("外部循环: " + x); x += 1; z = 1; while (true) { console.log("内部循环: " + z); z += 1; if (z === 3 && x === 3) { break labelCancelLoops; } else if (z === 3) { break; } } }
-
-
try-catch 错误捕获
在 try 块中的代码如果执行遇到错误,会被 catch 块捕获,而不会影响外部代码继续执行
try { //使用 throw 可以手动引发异常 throw '114514异常'; } catch (error) { console.error(error); } //控制台输出了异常消息 //还可以使用 finally 块,不论是否遇到错误,跳出 try...catch 块前都会执行 finally 块的代码 try { //使用 throw 可以手动引发异常 throw '114514异常'; } finally { console.log('finally') } //finally 和 catch 块都是可选的,也可以一起用,但是不能单独使用 try 块 try { //使用 throw 可以手动引发异常 throw '114514异常'; } catch (error) { console.error(error); } finally { console.log('finally') }
运算操作符
-
算数运算
摆烂了,看MDN吧: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Expressions_and_Operators
+加++自增-减--自减*乘/除**指数%取余数
-
位运算
&按位与|按位或^按位异或
-
逻辑运算
&&逻辑与||逻辑或
-
简化赋值运算
x += y=>x = x + yx -= y=>x = x - yx *= y=>x = x * yx /= y=>x = x / yx %= y=>x = x % yx **= y=>x = x ** yx <<= y=>x = x << yx >>= y=>x = x >> yx &= y=>x = x & yx |= y=>x = x | yx ^= y=>x = x ^ y
-
解构赋值
//可迭代元素的解构,相当于把不同下标的元素赋值给定义的变量 const list = ['1','2','3']; let [t1, t2, t3, t4] = list; console.log(t1,t2,t3,t4); //1 2 3 undefined //如果元素不够分配,未分配到的元素不会被赋值 //使用 ... 可以让某个变量接受剩余元素 const list = ['1','2','3','4','5']; let [t1, t2, ...t3] = list; console.log(t1,t2,t3); //1 2 (3) ['3', '4', '5'] //注意,t3变量是一个数组 //也可以对字典使用解构,但是需要使用 {} 而不是 [] const dict = {aa:1,bb:2,cc:3}; let {bb,aa,cc,dd} = dict; console.log(aa,bb,cc,dd); //1 2 3 undefined //字典的解构赋值是通过 key 而不是变量索引来获取的,因此变量的顺序无关紧要 //如果变量和key名字不一致也可以指定别名 const dict = {aa:1,bb:2,cc:3}; let {aa:s1,bb:s2,cc:s3} = dict; console.log(s1,s2,s3); //1 2 3 -
三目运算
表达式 ? 值1 : 值2当表达式成立,三目运算的结果为值1,当表达式不成立,三目运算的结果为值2
let x = false ? 1 : 2; console.log(x); //2 let x = true ? 1 : 2; console.log(x); //1
浏览器对象 Window
window 是浏览器对象,访问属性或者方法的时候可以省略 window
常用属性
documentHTML文档对象,页面上的元素都可以通过这个对象获取console控制台对象,用于打印日志location地址对象,读取网页链接或者控制跳转localStorage访问本地储存数据screen获取显示器分辨率scrollX,scrollY水平/垂直滚动条位置
常用方法
alert弹出提示框,会阻塞 JS 运行confirm弹出确认提示框,会阻塞 JS 运行blur将焦点移出当前窗口close关闭窗口eval执行字符串形式的 JS 语句find查找指定字符串,并聚焦到字符串的位置focus激活当前窗口open打开新窗口 (标签页)openDialog打开新的对话框窗口print显示打印对话框prompt弹出输入框,会阻塞 JS 运行scroll控制滚动条滚动到指定位置stop停止加载
文档对象 Document
Document 接口是 HTML 页面的另一种形式,或者叫 DOM 树,通过 window.document 可以获取当前窗口的 DOM 树,通过 Document 对象可以很方便的添加或者修改 DOM 元素
Document 对象也继承了 Node 对象的属性和方法
常用属性
body返回<body>节点head返回<head>节点cookie读取或者设置 cookietitle获取或者设置网页标题URL返回地址栏链接
常用方法
createElement指定标签名,创建一个新的元素getElementsByClassName指定类名查找元素getElementById指定ID查找元素querySelector通过CSS选择器查找第一个匹配元素querySelectorAll通过CSS选择器查找所有匹配元素evaluate执行XPath表达式hasFocus返回当前文档是否拥有焦点
文档元素对象 Element
Element 对象相当于HTML中的Tag,比如 <div></div>
Element 对象也继承了 Node 对象的属性和方法
常用属性
attributes标签属性集合classList标签 class 属性列表 (按空格分隔)className标签 class 属性的值id标签的 id 属性innerHTMLDOM 元素内部的 HTML 文本innerTextDOM 元素内部的文本tagName标签自身的名称,例如divaspan等
常用方法
addEventListener添加事件监听器,需要指定事件名和回调函数,触发特定事件后自动调用回调函数dispatchEvent手动触发指定的事件getAttribute获取标签的指定属性
文档节点对象 Node
网页中的所有 Node 一起构成了 DOM 树,对节点的修改会反应到网页中
常用属性
childNodes返回该节点的所有子节点firstChild返回第一个子节点,没有返回nulllastChild返回最后一个子节点,没有返回nullnodeName返回节点对应的名称,比如#documentnodeType返回节点类型对应的值,具体定义参考 MDNparentNode返回父节点parentElement返回父元素textContent返回节点内所有子节点的文本内容
常用方法
appendChild将指定节点作为子节点添加到当前节点的末尾cloneNode克隆指定节点hasChildNodes判断当前节点是否有子节点insertBefore在当前节点新增子节点,插入在指定节点之前
Document Element 与 Node

Document即 DOM 树,包含了网页中的所有 DOM 对象,既包含Element也包含NodeElement标签元素,类似与<a href="xx">xxx</a>,它继承Node的属性和方法,同时具有自己特有的属性和方法Node节点,是 DOM 树的最基础单位,比如<a href="xx">xxx</a>这一个Element,就包含一个ANode (即<a href="xx"></a>)和一个TextNode(即xxx)
一个 Element 可以包含任意个 Element 元素 和 Node 元素
本文链接:https://blog.chrxw.com/archives/2022/08/08/1678.html
转载请保留本文链接,谢谢
3 条评论
后面怎么不继续更新了?
另一个原因是chrome据说要弃用油猴插件依赖的API了,不过貌似弃用计划推迟了
没有这个精力了,维护的开源项目太多了