@artman328
2022-08-02T08:00:09.000000Z
字数 5409
阅读 411
JavaScript
js
cookbook
//仅包含一个分隔空格
"It is power of the dream".split(" ")
//['It', 'is', 'power', 'of', 'the', 'dream']
//包含多个不同数量的间隔空白字符
"It is power of the dream".split(" ")
//['It', '', 'is', 'power', 'of', 'the', '', '', '', 'dream'] 包含空串!
//解决方案
"It is power of the dream".replace(/\s+/g," ").split(" ")
//['It', 'is', 'power', 'of', 'the', 'dream']
//or:
"It is power of the dream".split(/\s+/g)
//['It', 'is', 'power', 'of', 'the', 'dream']
在正则表达式中,\s 代表一切空白字符,包括空格、换行、TAB等。
class Employee {
constructor(employee_id, firstName, lastName) {
this.employee_id = employee_id
this.firstName = firstName
this.lastName = lastName
}
get fullName() {
return this.firstName + " " + this.lastName
}
set fullName(fullName) {
fullName = fullName.split(/\s+/g)
this.firstName = fullName[0]
this.lastName = fullName[1]
}
}
/*
这是一个管理员工的类,它将被用来针对整个员工群体进行管理,
比如添加员工到集合中、从集合中删除员工等。这些管理行为
可以应用程序逻辑进行控制。
*/
class EmployeeCollection {
constructor(employees = []) {
this.employees = employees
}
add(employee){
// 检查 employee 对象数据的合法性、操作者的权限等
// 如果满足要求才:
this.employees.push(employee)
}
remove(employee_id) {
// 检查操作者的权限,如果满足才:
const index = this.employees.findIndex((emp)=>emp.employee_id==employee_id)
if(index >= 0){ // found
this.employees.splice(index,1)
}
}
[Symbol.iterator]() {
let index = 0
return {
next: () => {
if (index < this.employees.length) {
return {
value: this.employees[index++],
done: false
}
}
return {
done: true
}
}
}
}
}
let employeeCollection = new EmployeeCollection([
new Employee(1, "Billy", "Gilman"),
new Employee(2, "Tracy", "Taylor"),
new Employee(3, "Emily", "Brown")
])
//iterate the collection
for (let emp of employeeCollection) {
console.log(emp.fullName)
}
/* output:
Billy Gilman
Tracy Taylor
Emily Brown
*/
employeeCollection.remove(2)
for (let emp of employeeCollection) {
console.log(emp.fullName)
}
/* output:
Billy Gilman
Emily Brown
*/
要求:按从左到右,从上到下的顺序遍历所有网格中的单元格。
以下示意图说明了单元格的索引号(0~47)和其所在行、列索引之间的互换关系。
class Grid {
constructor(rows = 1, columns = 1) {
this.rows = rows
this.columns = columns
this.cells = []
for (let r = 0; r < rows; r++) { // 构建二维数组
this.cells[r] = []
for (let c = 0; c < columns; c++) {
this.cells[r][c] = columns * r + c
}
}
}
[Symbol.iterator] = function () {
let idx = 0
return {
next: () => {
if (idx < this.rows * this.columns) {
const r = Math.floor(idx / this.columns)
const c = idx % this.columns
const res = {
value: this.cells[r][c],
done: false
}
idx++;
return res;
}
else {
return { done: true }
}
}
}
}
}
let grid = new Grid(6, 8)
// console.log(grid)
for (let cell of grid) {
console.log(cell)
}
/* output:
0
1
...
47
*/
--------------------------------
| div.grand-parent |
| ------------------------ |
| | div.parent | |
| | ------------- | |
| | | div.child | | |
| | ------------- | |
| ------------------------ |
--------------------------------
在以上的DOM结构中,如果一个事件发生在 div.child
元素上,如何在它的前辈元素中捕获并处理此事件?如何确定处理顺序?
事件捕获处理顺序如下:
document
| |
---------------------| |-----------
| div.grand-parent | | |
| -----------------| |------- |
| | div.parent | | | |
| | -------------| |---- | |
| | | div.child \ / | | |
| | --------------------- | |
| ---------------------------- |
------------------------------------
document
/ \
---------------------| |-----------
| div.grand-parent | | |
| -----------------| |------- |
| | div.parent | | | |
| | -------------| |---- | |
| | | div.child | | | | |
| | --------------------- | |
| ---------------------------- |
------------------------------------
W3C标准的事件顺序是(当div.child发生事件时):
document ----------> div.child -----------> document
事件捕获 事件冒泡
document
| | / \
---------------------| |---| |--------
| div.grand-parent | | | | |
| -----------------| |---| |---- |
| | div.parent | | | | | |
| | -------------| |---| |- | |
| | | div.child \ / | | | | |
| | ------------------------- | |
| -------------------------------- |
----------------------------------------
用 addEventListener(event_type,handle_func,useCapture)
函数来确定事件响应顺序。其中的第三个参数 useCapture
是一个 bool 型参数,用于说明事件的响应函数应该在哪一个阶段执行。
以下例子演示了事件处理顺序。
<!DOCTYPE html>
<html lang="en" data-name="document">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Custom Attributes</title>
<style>
div {
padding: 20px;
border: 1px dashed #ccc;
margin-top: 20px;
width: 80%;
}
div.grand-parent{
width: 500px;
background-color: rgb(190, 190, 234);
}
div.parent {
background-color: rgb(239, 186, 186);
}
div.child {
background-color: rgb(218, 246, 236);
}
</style>
</head>
<body>
<div class="grand-parent" data-name="grand-parent">
div.grand-parent
<div class="parent" data-name="parent">
div.parent
<div class="child" data-name="child">
div.child
</div>
</div>
</div>
<script>
log = (useCapture,e)=>console.log(
"事件由:",
e.target.dataset.name,
" 触发,在",
useCapture?"捕获":"冒泡",
"阶段由:",
e.currentTarget.dataset?e.currentTarget.dataset.name:"document",
" 响应。"
)
const $ = (sel) => document.querySelector(sel)
document.addEventListener("click",(e)=>{
log(true,e)
},true)
document.addEventListener("click",(e)=>{
log(false,e)
},false)
$(".grand-parent").addEventListener("click",(e)=>{
log(true,e)
},true)
$(".grand-parent").addEventListener("click",(e)=>{
log(false,e)
},false)
$(".parent").addEventListener("click",(e)=>{
log(true,e)
},true)
$(".parent").addEventListener("click",(e)=>{
log(false,e)
},false)
$(".child").addEventListener('click',(e)=>{
log(true,e)
},true)
$(".child").addEventListener('click',(e)=>{
log(false,e)
})
</script>
</body>
</html>
如果在 div.child 上点击鼠标,会得到以下输出。
事件由: child 触发,在 捕获 阶段由: document 响应。
事件由: child 触发,在 捕获 阶段由: grand-parent 响应。
事件由: child 触发,在 捕获 阶段由: parent 响应。
事件由: child 触发,在 捕获 阶段由: child 响应。
事件由: child 触发,在 冒泡 阶段由: child 响应。
事件由: child 触发,在 冒泡 阶段由: parent 响应。
事件由: child 触发,在 冒泡 阶段由: grand-parent 响应。
事件由: child 触发,在 冒泡 阶段由: document 响应。