惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Security @ Cisco Blogs
罗磊的独立博客
宝玉的分享
宝玉的分享
Last Week in AI
Last Week in AI
T
The Blog of Author Tim Ferriss
美团技术团队
T
Tailwind CSS Blog
博客园 - 三生石上(FineUI控件)
博客园 - Franky
G
Google Developers Blog
Jina AI
Jina AI
Stack Overflow Blog
Stack Overflow Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
V
Visual Studio Blog
腾讯CDC
S
SegmentFault 最新的问题
Recent Announcements
Recent Announcements
博客园 - 叶小钗
Microsoft Security Blog
Microsoft Security Blog
雷峰网
雷峰网
L
LangChain Blog
Vercel News
Vercel News
Forbes - Security
Forbes - Security
PCI Perspectives
PCI Perspectives
N
News | PayPal Newsroom
S
Security Affairs
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - 司徒正美
J
Java Code Geeks
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Hacker News: Ask HN
Hacker News: Ask HN
Schneier on Security
Schneier on Security
A
About on SuperTechFans
Attack and Defense Labs
Attack and Defense Labs
Google Online Security Blog
Google Online Security Blog
aimingoo的专栏
aimingoo的专栏
MongoDB | Blog
MongoDB | Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
酷 壳 – CoolShell
酷 壳 – CoolShell
Cloudbric
Cloudbric
B
Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
P
Proofpoint News Feed
D
DataBreaches.Net
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
B
Blog RSS Feed
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
N
News and Events Feed by Topic

披萨盒的赛博日志

谈谈工作了半年的感受 使用策略模式重构复杂业务分支 像 systemd 一样管理 MacOS 后台常驻任务 以ORM看封装的边界 Git Merge VS Git Rebase: 如何优雅地合并分支? 修改Linux内核模块以支持WG OpenLDAP折腾日记 非特权模式容器 ssh 登录问题 在 Linux 开发环境中使用网络代理 白嫖 Aseprite 像素绘图软件 MongoDB 增删改查 Python数据分析工具包-Numpy 解决 CLion 中文乱码问题 搭建 RLCraft 服务器 SpringBoot读取配置文件 Centos 配置 LNMP 环境 部署项目时遇到的坑 浅谈 xhr 请求跨域问题 Eclipse配置Web开发环境 Vue2 基本知识 Ribbon 简单使用 Nacos 简单使用 Spring Cloud Alibaba 环境搭建 什么是RSS?什么是Feed?它们有什么关系? Docker基本使用 TensorFlow启用GPU加速 如何进行内网穿透 Hello World! Git基本使用 Butterfly常用标签外挂
JavaScript 学习笔记
披萨盒 · 2022-09-02 · via 披萨盒的赛博日志

引入

JavaScript 是一种轻量级、跨平台和解释编译的编程语言,也称为网页脚本语言。它以开发网页而闻名,但是许多非浏览器环境也可以使用它。JavaScript 可用于客户端开发以及服务器端开发。它既是命令式又是声明式语言。作为前端三件套之中唯一有编程逻辑的语言,JavaScript 常常用于页面交互、实现一些复杂的动画以及数据传输等。


浏览器工作原理

浏览器分为两个部分:渲染引擎和 JS 引擎

  • 渲染引擎:用来解析HTML和CSS,俗称内核,比如 chrome 的blink,老版本的 webkit
  • JS 引擎:也成为 JS 解释器。用来读取网页中的 JavaScript 代码,对其进行后台处理,比如 chrome 浏览器的 v8

注意:浏览器本身不会执行 JS 代码,而是通过内置 JavaScript 引擎(解释器)来执行JS代码,JS 引擎执行代码时会逐行解释每一行源码(转化为机器语言),然后由计算机去执行


JS 组成

ECMAScript

ECMAScript 是由 ECMA 国际(原欧洲计算机制造商协会)进行标准化的一门编程语言,它规定了 JS 的编程语法和基础核心知识,是所有浏览器厂商共同遵守的一套 JS 语法工业标准

DOM

DOM(Document Object Model,文档对象模型)是 W3C 组织推荐的处理可扩展标记语言(HTML或XML)的标准编程接口。通过此接口我们可以很容易的对页面上的元素的属性进行操作

BOM

BOM(Browser Object Model,浏览器对象模型)是一种独立于内容的,与浏览器窗口进行互动的对象结构。通过 BOM 可以操作浏览器窗口,比如弹出框、浏览器跳转、获取窗口大小、滚动条、分辨率等


JS 数据类型及运算符

JS 是一种弱类型的语言,也就是说某一个变量被定义类型之后,该变量可以根据环境变化自动进行转换,不需要强制转换

字符串

  1. 使用单引号或双引号包裹

  2. \ 为转义字符,通过 \ ,可以打印 Unicode Ascll 字符等

  3. 多行字符串编写

1
2
3
4
5
var msg = `
hello
world
你好
世界`
  1. 模板字符串
1
2
3
4
5
6
7
let name = 'Pillage'
let age = 19

let msg = `你好啊, ${name}`
console.log(msg)

> 你好啊, Pillage
  1. 字符串长度
1
str.length
  1. 可变性:不可变
  2. 大小写转化(对中文没有影响)
1
2
.toUpperCase();
.toLowerCase();
  1. 寻找索引
1
.indexOf('t')
  1. 截取字符串
1
2
.substring(1)    
.substring(1, 3)

数组

注意:for in 是遍历下标, for of 才是遍历数组具体的值

Array 可以包含任意的数据类型

1
let array = [1, 2, 3, "Hello"]
  1. 长度
1
array.length

注意:此属性可读可写,即可以通过赋值修改数组的大小

  1. 寻找索引
1
array.indexOf(1)
  1. 截取数组,返回一个新数组
1
array.slice()

类似于 String 中的 substring

  1. 操作元素(在尾部)
1
2
array.push()
array.pop()
  1. 操作元素(在头部)
1
2
array.unshift   
array.shift
  1. 排序
1
array.sort()
  1. 元素反转
1
array.reverse()
  1. 数组拼接
1
array.concat([1, 2, 3])

注意:concat() 并不会修改原数组,只会返回一个连接后的新数组

  1. 连接数组

打印拼接数组,使用特定的字符串连接

1
array.join('')
  1. 多维数组

类似于 Python。例如二维数组就是一个普通一维数组中的每一个元素又是一个一维数组


对象

定义:

1
2
3
4
5
6
7
8
9
10
11
12
var 对象名 = {
属性名:属性值,
属性名:属性值,
...
属性名:属性值
}

var person = {
name: "pillage",
age: 18,
score: 100
}

JS 中,大括号可以表示一个对象,用键值对描述属性,多个属性之间用逗号隔开,最后一个不需要逗号

JS 中,所有的键都是字符串,值可以是任意类型

  1. 对象赋值
1
person.age = 19
  1. 动态增删属性
1
2
3
4
5

delete person.name


person.sex = "男"
  1. 判断某个属性值是否在这个对象中 xxx in xxx

注意:因为继承机制的存在,所以父类有的属性,子类也会被判定为有 如:

1
2
3
4
5
'toString' in person
> true

'age' in person
> true
  1. 判断某个属性是否在这个对象本身中 hasOwnProperty
1
2
3
4
5
person.hasOwnProperty('toString')
> false

person.hasOwnProperty('age')
> true

注意:Map 和 Set 是 ES6 新特性


Map

定义:

1
var map = new Map([['tom', 100], ['jerry', 99]])

用二维数组的形式可以直接 new 出来

元素操作:

1
2
3
var name = map.get('tom') 
map.set('admin', 1000)
map.delete('tom')

Set

无序不重复集合,Set 会自动进行去重操作

定义:

1
var set = new set([1, 2, 3])

操作元素:

1
2
3
set.add(4)    
set.delete(1)
set.has(1)

遍历

forEach 循环

1
2
3
4
let array = [5, 6, 7]
array.forEach(function(value) {
console.log(value)
})

iterator 迭代器

遍历数组:

1
2
3
4
5
6
7
8
9
10
let array = [5, 6, 7]

for (let i in array) {
console.log(i)
}
console.log("==========")

for (let i of array) {
console.log(i)
}

遍历 Map 和 Set:

1
2
3
4
5
6
7
8
let map = new Map([['Tom', 100], ['Jerry', 99]])
for (let i of map) {
console.log(i)
}
let set = new Set([3, 4, 5])
for (let i of set) {
console.log(i)
}

变量转换

通过 typeof 变量名 可以输出变量的类型

  1. String 转数字:
1
2
parseInt();
parseFloat();
  1. 强制类型转换
1
2
3
Boolean(value);
Number(value);
String(value);

注意:用这三个函数之一转换值,将创建一个新值,存放由原始值直接转换成的值。这可能会造成意想不到的后果。


逻辑运算符

与 && 或 || 非!

比较运算符:

1
2
3
=      
==
===

注意:

NaN 与任何数值都不相等,包括自己

1
NaN === NaN      

只能通过 isNaN(NaN) 这个方法来判断一个数是否为 NaN


JS 常用输入输出方法

方法名 方法的作用 参数解释
alert(msg) 浏览器弹出带有信息的警示框 msg:要显示的信息
console.log(meg) 浏览器控制台打印信息 msg:要打印的信息
console.dir(v) 控制台打印元素对象,从而查看里面的属性和方法 v:变量名
prompt(msg) 浏览器弹出带有一段消息的输入框,获取输入 msg:显示消息,返回值:用户输入内容
confirm(msg) 浏览器弹出带有一段消息的确认框 msg:显示消息,返回值:bool类型用户是否确认

DOM 基础

基本操作

关于 dom 的基操,主要内容有 创建、增、删、改、查、属性操作、事件操作

  1. 创建
1
2
3
document.write
innerHTML
createElement
1
2
appendChild
insertBefore
1
removeChild
1
2
3
4
5
主要修改 dom 的元素属性,dom 元素的内容、属性,表单的值等
1、修改元素属性:src、href、title 等
2、修改普通元素内容:innerHTML、innerText
3、修改表单元素:value、type、disable 等
4、修改元素样式:style、className
1
2
3
4
主要获取查询 dom 的元素
1、DOM 提供的 API 方法:getElementById,getElementByTagName 古老用法 不推荐
2、H5提供的新方法:querySelector,querySelectorAll
3、利用节点操作获取元素:父(parentNode)、子(children)、兄(previousElementSibling、nextElementSibling)
  1. 属性操作
1
2
3
4
主要针对于自定义属性
1、setAttribute
2、getAttribute
3、removeAttribute
  1. 事件操作

给元素注册事件,采取 事件源.事件类型 = 事件处理程序

鼠标事件 触发条件
onclick 鼠标点击左键触发
onmouseover 鼠标经过触发
onmouseout 鼠标离开触发
onfocus 获得鼠标焦点触发
onblur 失去鼠标焦点触发
onmousemove 鼠标移动触发
momouseup 鼠标弹起触发
onmousedown 鼠标按下触发

DOM 获取元素

1
2
3
4
5
6
7
8
9
10
11
12
document.getElementById();
document.getElementByTagName();
element.getElementByTagName();


document.body;
document.documentElement;


document.getElementByClassName();
document.querySelector();
document.querySelectorAll();

事件

事件三要素:事件源、事件类型、事件处理程序

执行事件的步骤:

  1. 获取事件源
  2. 注册事件(绑定事件)
  3. 添加事件处理程序(采取函数赋值形式)
1
2
3
4
5
6
7
<button id="btn">按钮</button>
<script>
var btn = document.querySelector("#btn");
btn.onclick = function() {
console.log("click事件");
}
</script>

this 可以指向事件函数的调用者

操作元素

改变元素的内容

1
2
对象.innerText = ;
对象.innerHTML = ;

这两个属性也能读取对象内的内容

区别:

  • innerText 不能识别 HTML 标签,innerHTML 能识别
  • innerText 在读取内容的时候,会自动去除空格和换行,而 innerHTML 会保留

操作元素属性

1
对象.属性名 = ;

也就是可以直接修改

修改表单属性时需要用到表单特有的属性(比如要修改输入框的内容用 inner HTML 就不好使了):

1
type value checked selected disabled

样式属性的操作

通过 JS 可以修改元素的大小、颜色、位置等属性。

1
2
1. element.style          
2. element.className
  1. element.style

    • 属性采用的是驼峰命名法,与CSS不同,如 fontSize backgroundColor
    • JS 修改 style 样式时,产生的是行内样式,权重比 CSS 更高

    如果要修改的样式比较少,或者功能比较简单的时候,可以这样用

  2. element.className

    • 修改元素的类名
    • 可以提前把要修改的内容写入 CSS 中,需要改变时应用该 CSS
    • 会直接更改类名,也就是覆盖掉以前的类名
    • 如果要保留以前的类名,可以在要修改的类名前加上”以前的类名 “(别忘了空格)。(其实原理就是一个元素可以又多个类名)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<style>
div{
width: 10px;
height: 10px;
background-color: purple;
}
.change{
width: 200px;
height: 400px;
background-color: pink;
margin: auto 0;
}
</style>
<script>
window.onload = function() {
var div = document.querySelector("div");
div.onclick = function() {
div.className = "change";
}
}
</script>

鼠标事件

  1. 焦点事件

鼠标点击焦点事件 onfocus

失去鼠标焦点事件 onblur

(鼠标焦点是指鼠标点一下,失去焦点是指鼠标点一下其他地方)

1
2
3
4
5
6
7
8
var input = document.querySelector("input");

input.onfocus = function() {
console.log("得到了焦点");
}
input.onblur = function() {
console.log("失去了焦点");
}

  1. 移入移出事件

鼠标移入事件 onmouseover

鼠标移出事件 onmouseout

1
2
3
4
5
6
7
8
9
window.onload = function() {
var box = document.querySelector(".box");
box.onmouseover = function() {
this.style.backgroundColor = "red";
}
box.onmouseout = function() {
this.style.backgroundColor = "aqua";
}
}

总结

202112252124168

小思想-排他思想

当用 for 循环对多个元素绑定同一事件时,如果想要某一个元素实现某个样式,则可以:

  1. 清除所有元素的样式
  2. 给当前的元素设置样式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>

<script>
var btns = document.querySelectorAll("button");
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function() {

for (var j = 0; j < btns.length; j++) btns[j].style.backgroundColor = "";
this.style.backgroundColor = "pink";
}
}
</script>

操作自定义属性

元素自定义属性通常以 data- 开头,如:<p data-time=”20”></p>

  1. 获取元素的属性
1
2
3
4
5
element.属性
- 获取元素的内置属性

element.getAttribute('属性')
- 获取自定义属性和内置属性
  1. 设置元素属性
1
2
element.属性 = "值"
element.setAttribute('属性', '值')
  1. 移除元素属性
1
element.removeAttribute('属性')
  1. H5 新增获取自定义属性
1
2
3
4
5
6
7
8
如果有一个元素为:<a data-index="1"></a>

1. 兼容性获取:element.getArribute('data-index');

2. H5 新增:element.dataset.index 或者 element.dataset['index']
- 只能获取 data- 开头的
- 开头的 data- 省略,如果后面有多个 - 连接的单词,则获取的时候采取驼峰命名法
- ie11 才开始支持

节点操作

简述

一般的,节点至少拥有 nodeType(节点类型)、nodeName(节点名称)和 nodeValue(节点值)这三个基本属性

  • 元素节点 nodeType 为 1
  • 属性节点 nodeType 为 2
  • 文本节点 nodeType 为 3(文本节点包含文字,空格,换行等)

节点操作的主要对象是元素节点

获取父子节点

  1. 父级节点
1
node.parentNode
  • parentNode 返回元素节点的最近的一个父节点(亲爸爸)
  • 如果没有找到返回 null
  1. 子节点
1
parentNode.childNodes
  • 返回值包含了元素的所有子节点,包括元素节点和文本节点
  • 如果只想获取元素节点,则应 专门处理
1
2
3
4
5
6
var ul = document.querySelector('ul');
for (var i = 0; i < ul.childNodes.length; i++) {
if (ul.childNodes[i].nodeType === 1) {
console.log(ul.childNodes[i]);
}
}
  1. 子元素节点
1
parentNode.children
  • children 是一个只读属性,只返回子元素节点,其余节点不返回
  • 非标准的,但是得到了很多浏览器的支持
  1. 第一个/最后一个 子节点
1
2
3
4
5

parentNode.firstChild


parentNode.lastChild
  • 节点包含元素节点和文本节点
  1. 第一个/最后一个 子元素节点
1
2
3
4

parentNode.firstElementChild

parentNode.lastElementChild
  • 这两个方法有兼容性问题,ie9 以上才支持

  • 所以可以这样写

1
2
3
4

parentNode.children[0]

parentNode.children[parentNode.children.length - 1]

获取兄弟关系

  1. 兄弟节点
1
2
3
4

node.nextSibling

node.previousSibling
  1. 兄弟元素节点
1
2
3
4

node.nextElementSibling

node.previousElementSibling
  • 兼容性问题,ie9 以上才支持

创建节点

1
document.createElement('tagName')
  • document.createElement() 方法创建由 tagName 指定的 HTML 元素。也称为动态创建元素节点
  • 只是创建并没有添加

添加节点

  1. 在后面追加
1
node.appendChild(child)
  • 将一个节点添加到指定父节点的子节点列表的末尾,类似于 css 中的 after 伪元素
  • 也称为追加元素
  1. 插入节点
1
node.insertBefore(child, 指定元素)
  • 将一个节点插入到父节点的指定子节点的前面

删除节点

1
node.removeChild(childNode)

复制节点

1
node.cloneNode()
  • 克隆相当于新建,克隆后需要添加操作
  • 如果括号参数为空或者 false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点
  • 如果括号里面为 true,则是深拷贝,既复制节点本身,也复制里面的子节点

三种动态创建元素的区别

  • document.write()

    • 是直接将内容写入页面的内容流,但是会导致页面全部重绘
  • element.innerHTML

    • 是将内容写入某个 DOM 节点,不会导致页面全部重绘
    • 创建多个元素效率更高(不要采取拼接字符串,采取数组形式拼接),结构稍微复杂
  • document.createElement()

    • 创建多个元素效率会稍微低一些,但是结构更清晰

DOM 高级

注册事件(绑定事件)

概述

  • 给元素添加事件,称为注册事件或者绑定事件
  • 注册事件有两种方式:传统方式和方法监听注册方式
  1. 传统注册方式
    • 利用 on 开头的事件,如 onclick
    • <button onclick = “alert(‘hi’)”></button>
    • btn.onclick = function() { }
    • 特点:注册事件的唯一性
    • 同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数
  2. 方法监听注册方式
    • w3c 标准推荐方式
    • addEventListener() 是一个方法
    • ie9 之前的 ie 不支持此方法,可使用 attachEvent() 代替
    • 特点:同一个元素同一个事件可以注册多个监听器
    • 按注册顺序依次执行

addEventListener 事件监听方式

1
eventTarget.addEventListener(type, listener, [useCapture])

此方法会将指定的监听器注册到 eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数

同一个元素,同一个事件可以添加多个侦听器

该方法接收三个参数:

  • type:事件类型字符串(别忘了加引号),比如 click, mouseover, 等,注意不用带 on
  • listener:事件处理函数,事件发生时,会调用该监听函数
  • useCapture:可选参数,是一个布尔值
    • 当为 true 时,事件处于捕获阶段
    • 当为 false 或者 省略 时,事件处于冒泡阶段
1
2
3
btn2.addEventListener('click', function() {
alert("使用addEventListener添加点击事件")
})

attachEvent 事件监听方式(了解)

此方法只有 ie9 及以前的浏览器才支持,chrome 等浏览器不支持

1
eventTarget.attachEvent(eventNameWithOn, callback)

参数:

  • eventTarget:目标对象
  • eventNameWithOn:事件类型字符串,比如 onclick, onmouseover,等,要带 on
  • callback:事件处理函数

删除事件(解绑事件)

  1. 传统方式删除事件

.onclick = null;

1
2
3
4
5

div.onclick = function() {
alert("111");
div.onclick = null;
}
  1. 删除方法监听注册的事件

eventTarget.removeEventListener(type, listener, [useCapture])

1
2
3
4
5
6
7

div.addEventListener("click", fn)

function fn() {
alert("222")
div.removeEventTarget("click", fn);
}
  1. 删除 attachEvent 事件

eventTarget.detachEvent(eventNameWithOn, callback)

1
2
3
4
5
6
7

div.attachEvent("onclick", fn);

function fn() {
alert("333")
div.detachEvent("onclick", fn);
}

DOM 事件流

事件发生时会在元素节点之间按照特定的顺序进行传播,这个传播过程叫做 DOM 事件流

  • JS 代码只能执行捕获或者冒泡中的一个阶段
  • onclick 和 attachEvent 只能得到冒泡阶段
  • addEventListener 的第三个参数如果为 true 表示在捕获阶段调用事件处理程序,如果为 false 或 不写则表示在冒泡阶段调用事件处理程序
  • 有些事件是没有冒泡的,如:onblur、onfocus、onmouseenter、onmouseleave