Wang's blog Wang's blog
首页
  • 前端文章

    • HTML教程
    • CSS
    • JavaScript
  • 前端框架

    • Vue
    • React
    • VuePress
    • Electron
  • 后端技术

    • Npm
    • Node
    • TypeScript
  • 编程规范

    • 规范
  • 我的笔记
  • Git
  • GitHub
  • VSCode
  • Mac工具
  • 数据库
  • Google
  • 服务器
  • Python爬虫
  • 前端教程
更多
收藏
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Wang Mings

跟随大神,成为大神!
首页
  • 前端文章

    • HTML教程
    • CSS
    • JavaScript
  • 前端框架

    • Vue
    • React
    • VuePress
    • Electron
  • 后端技术

    • Npm
    • Node
    • TypeScript
  • 编程规范

    • 规范
  • 我的笔记
  • Git
  • GitHub
  • VSCode
  • Mac工具
  • 数据库
  • Google
  • 服务器
  • Python爬虫
  • 前端教程
更多
收藏
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • git命令使用
  • nodejs如何同时支持import和require
  • nodejs使用说明
  • Electron跨平台开发笔记
  • JavaScript笔记
    • HTML标签
      • 标签里添加空格
    • JS文档参考
    • JS操作网页DOM节点
      • JS动态/添加/移除/节点的Class
      • JS动态创建节点
    • JS运行平台
    • JS游览器本地存储
    • JS还原被重写的对象
    • JS函数或变量定义
      • JS函数中的变量定义
    • JS的new关键字构建对象和类class
      • JS初始化对象new关键字
      • JS对象的 prototype/constructor/proto 说明
      • prototype原型对象
      • constructor指针对象
      • proto指针对象
      • prototype/class创建类对比
    • JS类定义
      • 创建类
      • 类继承
      • 子类继承父类属性方法
    • JS文件操作
      • FileReader对象方法
      • FileReader对象事件
      • FileReader使用示例
      • JS文本数据相互转换加解码
    • JS对象操作
      • JS对象合并
    • JS数据类型判断
    • JS数组操作
      • JS统计数组中元素重复次数
      • JS获取数组第几到第几元素
      • JS数组元素删除添加
      • JS数组分割
    • JS字符串操作
      • JS字符串大小写转换
      • JS去除字符串首尾空格
      • JS字符串查找匹配
    • JS异步回调
      • 使用异步回调说明
      • 使用Promise对象回调结果
      • 使用Async/Await配合Promise实现回调
      • 类里面使用async/await/Promise参考
    • URL编码
      • URL编码和解码
    • HTTP请求
      • HTTP性能
      • HTTP1.1
      • HTTP2
      • 异步请求
      • 设置请求超时
      • 同步请求
      • http请求封装
    • JS性能优化
      • 避免if嵌套造成执行效率低下问题
  • 常用的ES5和ES6中对象的导出和导入的差异之处
  • theme-vdoing-blog博客静态编译问题
  • 笔记
wangmings
2022-07-19
目录

JavaScript笔记

# JavaScript笔记

# HTML标签

# 标签里添加空格

<!-- HTML -->
<!-- &ensp;半个空白符 -->
<!-- &emsp;一个空白符 -->
<h1>hello&emsp;worid</h1>
1
2
3
4

# JS文档参考

JS文档参考 (opens new window)

# JS操作网页DOM节点

# JS动态/添加/移除/节点的Class

// 给节点添加className
document.querySelector('#div').classList.add('className')

// 移除节点添加className
document.querySelector('#div').classList.remove('className')

1
2
3
4
5
6

# JS动态创建节点

优点: 动态创建节点不会影响相邻的节点已经注册的事件


// 封装好的动态创建子节点函数
function createNode(nodeName, callback=null, parentNode=null){
    let createNode = document.createElement(nodeName);
    // 设置节点属性
    const set = (attribute, value) => {
        let att = document.createAttribute(attribute)
        att.value = value;
        createNode.setAttributeNode(att)
    }
    if(callback != null) callback(createNode,set)
    if(parentNode != null) parentNode.appendChild(createNode);
}



// ------------------------------------------------------



// 使用示例
// 说明: 创建一个a节点不渲染生成进行点击事件
createNode('a',function(set,att){
    a.href = '#hello'
    set.click()
})




// 说明: 给body节点下添加一个div节点
// 获取父节点对象
let parentNode = node('body','g')[0]
// 创建一个div节点: 使用回调函数设置属性
createNode('div',function(set,att){
    // set对象只能设置一些节点默认的属性、不能设置自定义属性
    // 使用set给这个创建的div设置一个data属性是不生效的
    // 因为div默认没有这个属性,只能通过att进行设置
    
    set.className = 'myClicks'
    set.id = 'ms'
    set.innerHTML = '<a>hello</a>'

    // att对象可以设置默认属性和自定义属性
    // att('class','mac')
    att('data','hello')

},parentNode)



// 创建后的样子
<body>
  <div id='ms' class='myClicks' data='hello'>
    <a>hello</a>
  </div>
</body>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

# JS运行平台

判断运行在什么平台的浏览器上

// 判断浏览器函数
function isMobile() {
    if (window.navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)) {
        return true; // 移动端
    } else {
        return false; // PC端
    }
}
1
2
3
4
5
6
7
8

# JS游览器本地存储

// 封装好的本地存储: 查看,存储,判断,删除,等等
// 本地数据存储操作等等
function storage(type, key=null, value=null){
    // 判断一个值是否存在
    const isKey = (key)=>{return localStorage.hasOwnProperty(key)}
    
    // 获取存储所有的值
    if (type == 'all') return localStorage.valueOf()
    // 清除存储中所有的值
    if (type == 'cll') {localStorage.clear(); return true }
    // 判断没有输入key停止向下执行
    if (key == null) {console.error('没有输入: Key'); return}

    // 判断一个值是否存在
    if (type == 'is') return isKey(key)  
    // 移除一个值
    if (type == 'del') {localStorage.removeItem(key); if (isKey(key) == false) return true}  
    // 设置一个值
    if (type == 'set' && value != null) {localStorage.setItem(key,JSON.stringify(value));return isKey(key)}
    // 获取一个值
    if (type == 'get' && key != null) return JSON.parse(localStorage.getItem(key))
        

}


// 使用示例:

// 查看本地存储所有数据
storage('all')

// 存储数据
storage('set','data','hello')

// 获取数据
storage('get','data')

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

# JS还原被重写的对象

例如调试一个第三方网站时:console对象下的方法被重写了、无法使用console.log进行输出、就需要还原成原来的方法、创建一个iframe标签并把里面的环境引入到当前对象下、实现还原

// 演示例如:
(function(){
    var iframe = document.createElement('iframe')
    document.body.appendChild(iframe)
    window.console = iframe.contentWindow.console
}())
1
2
3
4
5
6

# JS函数或变量定义

# JS函数中的变量定义

// 声明多个变量的方法

// 声明多个变量或者初始化变量使用以下方法,简单实用
let i = 0,
    index = 0, 
    array = [];

// es6通过数组形式声明或者初始化变量方法
let [i,index,array] = [0,0,[]]
    

1
2
3
4
5
6
7
8
9
10
11

# JS的new关键字构建对象和类class

# JS初始化对象new关键字

  1. 创建一个新对象;

  2. 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象;

  3. 执行构造函数中的代码(为这个新对象添加属性;

  4. 返回新对象。

在《JavaScript模式》这本书中、当我们new一个构造器,主要有三步:

  • 创建一个空对象,将它的引用赋给this,继承函数的原型。
  • 通过 this 将属性和方法添加至这个对象
  • 最后返回 thi指向的新对象,也就是实例(如果没有手动返回其他的对象)

# JS对象的 prototype/constructor/proto 说明

prototype原型对象、constructor指针对象、__proto__指针对象 注意: constructor对象、proto对象、都是操作prototype对象下的属性、方法的指针

# prototype原型对象

prototype原型对象构成了js的原型链、通过prototype对象来修改、设置对象下的属性和方法、注意使用: 使用prototype对象,必须是在new初始化之前设置、修改属性、方法

// 演示示例:

// 注意: [[Prototype]] == prototype
function Rect() {
    this.name = '小明'
    this.age = 18
    this.speak = () => console.log(`我叫${this.name},今年${this.age}岁`)
}

// Rect对象继承数组Array对象下的属性、方法、继承后可以使用Array对象下的属性、方法
Rect.prototype = Array.prototype

// 给Rect对象自定义一个方法
Rect.prototype.privacy = function(){ console.log(`${this.name}喜欢看美女`)}


const rect = new Rect()
console.log(rect)

// 输出结果:
// Rect对象没有继承Array对象下的属性、方法时:

Rect {name: '小明', age: 18, speak: ƒ}
age: 18
name: "小明"
speak: ƒ ()
[[Prototype]]: Object
constructor: ƒ Rect()
[[Prototype]]: Object


// 输出结果:
// Rect对象继承Array对象下的属性、方法时:
// 明显多了许多属性、方法

Rect {name: '小明', age: 18, speak: ƒ}
age: 18
name: "小明"
speak: () => console.log(`我叫${this.name},今年${this.age}岁`)
[[Prototype]]: Array(0)
privacy: ƒ ()
at: ƒ at()
concat: ƒ concat()
constructor: ƒ Array()
copyWithin: ƒ copyWithin()
entries: ƒ entries()
every: ƒ every()
fill: ƒ fill()
filter: ƒ filter()
.....
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

# constructor指针对象

constructor指针指向原来的构造函数、可以通过它解决new初始化、调用对象后无法继承prototype对象的属性、方法

// 演示示例:
// 通过constructor指针继承new初始化后prototype对象的属性、方法

function Rect() {
    this.name = '小明'
    this.age = 18
    this.speak = () => console.log(`我叫${this.name},今年${this.age}岁`)
}

// 给Rect对象自定义一个方法
Rect.prototype.privacy = function(){ console.log(`${this.name}喜欢看美女`)}

const rect = new Rect()
console.log(rect)

// ------------------------------------------------>>
function Rect2(){}
// 通过prototype继承 Rect对象下的prototype下的属性,方法
Rect2.prototype = rect.constructor.prototype

const rect2 = new Rect2()
console.log(rect2)

// 输出结果:
Rect {}
[[Prototype]]: Object
privacy: ƒ ()
constructor: ƒ Rect()
[[Prototype]]: Object

// 输出结果:
Rect2 {}
[[Prototype]]: Object
privacy: ƒ ()
constructor: ƒ Rect()
[[Prototype]]: Object
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# proto指针对象

// new初始化后使用__proto__对象来继承prototype对象继承原型下、属性、方法
function Rect() {
    this.name = '小明'
    this.age = 18
    this.speak = () => console.log(`我叫${this.name},今年${this.age}岁`)
}

// Rect对象继承数组Array对象下的属性、方法、继承后可以使用Array对象下的属性、方法
// Rect.prototype = Array.prototype


const rect = new Rect()
// new初始化后无法使用prototype对象继承原型下、属性、方法
// 可以通过__proto__对象来继承prototype原型下、属性、方法
rect.__proto__ = Array.prototype
console.log(rect)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# prototype/class创建类对比

// 示例说明
// 从下面两个示例可以看出他们输出基本是一模一样
// 注意: class创建类优势更大

// 使用prototype原型创建类
function Rect() {
    this.name = '小明'
    this.age = 18
    this.speak = () => console.log(`我叫${this.name},今年${this.age}岁`)
}

Rect.prototype.privacy = () => console.log(`${this.name}喜欢看美女`)

// ----------------------------------------------------------->>

// 使用class对象创建类
class Rect2{
    constructor(){
        this.name = '小明'
        this.age = 18
        this.speak = () => console.log(`我叫${this.name},今年${this.age}岁`) 
    }

    privacy(){
        console.log(`${this.name}喜欢看美女`)
    }
}


const rect = new Rect()
console.log(rect)

const rect2 = new Rect2()
console.log(rect2)

// Rect输出结果:
Rect {name: '小明', age: 18, speak: ƒ}
age: 18
name: "小明"
speak: ƒ ()
[[Prototype]]: Object
privacy: ƒ ()
constructor: ƒ Rect()
[[Prototype]]: Object

// Rect2输出结果:
Rect2 {name: '小明', age: 18, speak: ƒ}
age: 18
name: "小明"
speak: ƒ ()
[[Prototype]]: Object
constructor: class Rect2
privacy: ƒ privacy()
[[Prototype]]: Object

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

# JS类定义

JS类定义或者使用 参考文档:JavaScript类(Class)完全指南 (opens new window)

# 创建类

// 定义类
class user {
    // static # 定义静态私有方法:只能在类里面通过对象调用,外部无法通过对象调用
    static #data = 0;

    // new 初始化
    constructor(name) {
        this.name = name;
    }

    // static定义静态方法: 可以通过内部的类调用或者外部的类对象调用
    // 例如:user.name、不能通过内部this和对象调用
    static name(){
        let name = "xiang ming";
        console.log(name)
    }

    // 定义私有方法: 外部无法调用、内部使用this调用
    #age(a){
        return a + 1
    }

    // 定义方法: 外部后内部都能调用
    main(){
        let age = this.#age(18)
        let name = this.name
        console.log(name,age)
    }
}


// new 时初始化类
let obj = new user('da ming')

// 调用对象方法 
obj.main()

// 调用静态方法
user.name()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

# 类继承

JavaScript 中的类使用extends关键字支持单继承、在class Child extends Parent { }表达式中,Child类从Parent继承构造函数,字段和方法。

// 创建一个新的子类ContentWriter来继承父类User
// ContentWriter继承了User的构造函数,方法getName()和字段name。同样,ContentWriter类声明了一个新的字段posts。
// 注意,父类的私有成员不会被子类继承

class User {
  name;

  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

class ContentWriter extends User {
  posts = [];
}

const writer = new ContentWriter('John Smith');

writer.name;      // => 'John Smith'
writer.getName(); // => 'John Smith'
writer.posts;     // => []

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 子类继承父类属性方法

如果希望在子类中调用父构造函数,则需要使用子构造函数中可用的super()特殊函数。

// 让ContentWriter构造函数调用User的父构造函数,以及初始化posts字段
// 子类ContentWriter中的super(name)执行父类User的构造函数。

class User {
  name;

  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

class ContentWriter extends User {
  posts = [];

  constructor(name, posts) {
    super(name);
    this.posts = posts;
  }
}

const writer = new ContentWriter('前端小智', ['Why I like JS']);
writer.name; // => '前端小智'
writer.posts // => ['Why I like JS']


// 注意,在使用this关键字之前,必须在子构造函数中执行super()。调用super()确保父构造函数初始化实例。
class Child extends Parent {
  constructor(value1, value2) {
    //无法工作
    this.prop2 = value2;
    super(value1);
  }
}


// 如果希望在子方法中访问父方法,可以使用特殊的快捷方式super。
// 子类ContentWriter的getName()直接从父类User访问方法super.getName(),这个特性称为方法重写。
// 注意,也可以在静态方法中使用super来访问父类的静态方法。

class User {
  name;

  constructor(name) {
    this.name = name;
  }

  getName() {
    return this.name;
  }
}

class ContentWriter extends User {
  posts = [];

  constructor(name, posts) {
    super(name);
    this.posts = posts;
  }

  getName() {
    const name = super.getName();
    if (name === '') {
      return '无名氏';
    }
    return name;
  }
}

const writer = new ContentWriter('前端小智', ['Why I like JS']);
writer.getName(); // => '无名氏'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

# JS文件操作

使用FileReader对象读取本地文件: FileReader对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用File或Blob对象指定要读取的文件或数据。注意: FileReader对象读取的文件数据类型为Blob对象的数据类型

# FileReader对象方法

// 作用:中止读取操作。
FileReader.abort()
// 作用:读取的文件数据转换为ArrayBuffer数据对象。
FileReader.readAsArrayBuffer()
// 作用:读取文件的原始二进制数据
FileReader.readAsBinaryString()
// 作用:读取文件的数据为URL格式的字符串以表示所读取文件的内容。此方法较为常用。
FileReader.readAsDataURL()
// 作用:读取文件文本内容
FileReader.readAsText()
1
2
3
4
5
6
7
8
9
10

# FileReader对象事件

// 作用: 该事件在读取操作被中断时触发。
FileReader.onabort = () => {}
// 作用:  该事件在读取操作发生错误时触发。
FileReader.onerror = () => {}
// 作用:  该事件在读取操作完成时触发。该事件较为常用。
FileReader.onload = () => {}
// 作用: 该事件在读取操作开始时触发。
FileReader.onloadstart = () => {}
// 作用: 该事件在读取操作结束时(要么成功,要么失败)触发。
FileReader.onloadend = () => {}
// 作用:该事件在读取Blob时触发
FileReader.onprogress = () => {}

1
2
3
4
5
6
7
8
9
10
11
12
13

# FileReader使用示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>本地文件读取</title>
</head>
<body>
<input id='readFile' type="file" />
<script type="text/javascript">

    // 获取选中的本地文件
    document.querySelector('#readFile').addEventListener('change', (e) => {
        // 获取文件信息
        const file = e.target.files[0]; 

        if (file) {

            // 初始化一个FileReader 对象
            const reader = new FileReader();

            // 读取文件数据为的ArrayBuffer数据对象
            reader.readAsArrayBuffer(file);

            // 文件读取成功时触发
            reader.onloadend = function() {
                // 这个事件在读取结束后,无论成功或者失败都会触发
                if (reader.error) {
                    console.log(reader.error);
                } else {
                    console.log(reader.result);
                    /*
                    输出结果:
                        ArrayBuffer(663)
                        byteLength: 663
                        [[Prototype]]: ArrayBuffer
                        [[Int8Array]]: Int8Array(663)
                        [[Uint8Array]]: Uint8Array(663)
                        [[ArrayBufferByteLength]]: 663
                        [[ArrayBufferData]]: 1
                    */
                }
            }
        }
    })
</script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

# JS文本数据相互转换加解码

1. FileReader对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用File或Blob对象指定要读取的文件或数据。 2. Blob对象表示一个不可变、原始数据的类文件对象、它的数据可以按文本或二进制的格式进行读取,也可以转换成ReadableStream来用于数据操作。Blob表示的不一定是JavaScript原生格式的数据、File接口基于Blob,继承了blob的功能并将其扩展使其支持用户系统上的文件。 3. ArrayBuffer对象代表储存二进制数据的一段内存,它不能直接读写,只能通过视图(TypedArray视图和DataView视图)来读写、视图的作用是以指定格式解读二进制数据。 4. Uint8Array对象是ArrayBuffer的一个数据类型(8位不带符号整数)。 5. TextEncoder接受代码点流作为输入、并提供UTF-8字节流作为输出。 6. TextDecoder接口表示一个文本解码器、一个解码器只支持一种特定文本编码,例如utf-8、iso-8859-2、koi8、cp1261,gbk等等。解码器将字节流作为输入,并提供代码点流作为输出。

// 演示示例:

// 示例1. TextEncoder -> ArrayBuffer
let encoder = new TextEncoder();
// 字符 转 Uint8Array
let uint8Array = encoder.encode("你好啊");
// Uint8Array 转 ArrayBuffer
let arrayBuffer = uint8Array.buffer



// 示例2. Blob -> ArrayBuffer
let str = 'hello,你好吗?'
let blob = new Blob([str],{type:'text/plain;charset=utf-8'});
let utf8decoder = new TextDecoder()
blob.arrayBuffer().then(buffer=>{
  // ArrayBuffer
  console.log(buffer)
  let text = utf8decoder.decode(buffer)
  // String
  console.log(text)
})




// 示例3. FileReader => ArrayBuffer
let str = 'hello,你好吗?'
let blob = new Blob([str],{type:'text/plain;charset=utf-8'});
let utf8decoder = new TextDecoder()
let fr = new FileReader()
fr.readAsArrayBuffer(blob)
fr.onload = function(res) {
  // ArrayBuffer
  let buffer = fr.result
  console.log(buffer)
  let text = utf8decoder.decode(buffer)
  // String
  console.log(text)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

# JS对象操作

# JS对象合并

利用了: Object.assign方法

// 演示例如:
let obj = {name:'xiangming'}
let obj2 = {num:12}
Object.assign(obj,obj2)
console.log(obj)

// 输出结果
{ name: 'xiangming', num: 12 }
1
2
3
4
5
6
7
8

# JS数据类型判断

使用Object.prototype.toString.call方法来进行数据类型判断比、typeof、instanceof、constructor方法更加好 详细说明请参考: js判断数据类型 (opens new window)

// 演示示例:
var bool = true
var num = 1
var str = 'abc'
var und = undefined
var nul = null
var arr = [1,2,3]
var obj = {name:'haoxl',age:18}
var fun = function(){console.log('I am a function')}

// 定义数据类型判断函数
function type(data){
    return Object.prototype.toString.call(data).replace('[object ','').replace(']','').toLowerCase()
}


// 输出
console.log(type(bool));
console.log(type(num));
console.log(type(str));
console.log(type(und));
console.log(type(nul));
console.log(type(arr));
console.log(type(obj));
console.log(type(fun));

// 输出结果:
boolean
number
string
undefined
null
array
object
function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# JS数组操作

# JS统计数组中元素重复次数

// 演示示例:
var arr = ["李","李","设","弟","弟","生","生","李"]; 

let obj = arr.reduce(function(prev,next){ 
    prev[next] = (prev[next] + 1) || 1; 
    return prev; 
},{}); 

console.log(obj);

// 输出结果
{李: 3, 设: 1, 弟: 2, 生: 2}
1
2
3
4
5
6
7
8
9
10
11
12

# JS获取数组第几到第几元素

// 演示示例: 获取数组前三个元素
var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"];
var citrus = fruits.slice(0,3);
console.log("数组前三个元素:"+citrus);
// 输出结果
数组前三个元素:Banana,Orange,Lemon

1
2
3
4
5
6
7

# JS数组元素删除添加

// 演示示例

// 给数组尾部添加数
let arr = []
arr.push(2)

let arr = [1,2,3,4,5]

// 通过索引删除数组元素
let delete_index = 0
arr = arr.splice(delete_index, 1)
// 结果
[2,3,4,5]



// 通过指定元素删除数组元素
var arr = [1,2,3,4,5],
    element = 2
// 删除数组中为2的数组元素 
arr = arr.filter(item => item != element)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# JS数组分割

利用array.slice()方法来平均分割一个数组,并将分割后的数组组合成一个新的数组

// 定义演示数组
var arr = [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5]; 

// 定义数组分割函数
function splitArray(arr, size) { 
    let i = 0,
        index = 0, 
        array = [],
        split = Math.ceil(arr.length / size, 10);  // Math.ceil()向上取整的方法
    
    while (i < split) {
        array[i] = arr.slice(index, size + index);
        index += size;
        i++;
    }

    return array
}

// 将数组平均分割成4份
let arrs = splitArray(arr,4)
console.log(arrs)

// 输出结果:
[
  [ 1, 1, 1, 1 ],
  [ 1, 2, 2, 2 ],
  [ 2, 2, 3, 3 ],
  [ 3, 3, 3, 4 ],
  [ 4, 4, 4, 4 ],
  [ 5, 5, 5, 5 ]
]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# JS字符串操作

# JS字符串大小写转换

字符串方法 说明
toLocaleLowerCase() 把字符串转换成小写
toLocaleUpperCase() 将字符串转换成大写
toLowerCase() 将字符串转换成小写
toUpperCase() 将字符串转换成大写
// 演示示例:
var s = "JavaScript";
console.log(s.toUpperCase());  //返回字符串“JAVASCRIPT”
1
2
3

# JS去除字符串首尾空格

let str = '  hello worid  '
str.replace(/(^\s*)|(\s*$)/g, "")

// 输出结果
hello worid
1
2
3
4
5

# JS字符串查找匹配


// 示例
let str ='abcdefab';

// 静态匹配的字符
let arr = str.match(/a/g)

// 动态查找匹配的字符
str.match(RegExp(su,'g'))
console.log(arr)

// 输出结果
[ 'a', 'a' ]


// 匹配成功返回true
let su = 'ab'
let bool = RegExp(su,'g').test(str)
console.log(bool);

// 可以写成
bool = /d/g.test(str)
console.log(bool);

// 输出结果
true

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# JS异步回调

# 使用异步回调说明

// 演示示例:

/**
下面示例说明:我需要获取setTimeout一秒后执行的结果、
console.log输出的是: 0,那是因为setTimeout是在console.log后异步执行的、我们没有办法在同步之上获取结果
**/

let num = 0
setTimeout(function(){
    num++
},1000)

console.log(num)
// 输出: 0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 使用Promise对象回调结果

Promise 被引入了用于解决著名的回调地狱问题,但是它们自身引入了复杂性以及语法复杂性。

// Promise对象使用示例:
let num = 0

const getData = function(){
    return new Promise((resolve, reject) => {
      // 模拟异步执行: 请替换你需要处理的异步
      setTimeout(function(){
          num++
          if(num > 0){
              // 获取正确结果回调
              resolve(num)

          }else{
              // 获取错误结果回调
              reject(num)
              return
          }
      },1000)


    })
}



// 调用方法
getData().then(res=>{
    console.log('后异步',res)
    {等待返回的结果后:在这里写需要处理的任务}

}).catch(err=>{
    {等待返回的错误结果后:在这里写需要处理的任务}
    console.log('后异步',err)

}) 

console.log('先同步',num)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

# 使用Async/Await配合Promise实现回调

为什么引入 async/await 它们减少了promises的样板、且减少了promise链的不破坏链条的限制

// 示例:封装async/await/Promise和方便调用
async function getAsyncAwait(callback) {
    const request = () => {
        return new Promise((resolve,reject) => {
            // 模拟异步执行: 请替换你需要处理的异步
            setTimeout(function(){
                num++
                if(num > 0){
                    resolve(num)

                }else{
                    reject(num)
                    return
                }
            },1000)
            
        })

    }

    // await等待异步获取返回的结果后回调
    let resolve = await request()
    callback(resolve)

}


// 调用方法
getAsyncAwait((res,err)=>{
    console.log(res)
    {等待返回的结果后:在这里写需要处理的任务}
})

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 类里面使用async/await/Promise参考

http请求封装

# URL编码

# URL编码和解码

// 只对URL的参数进行编码或者解码
encodeURI(URL) // 编码
decodeURI(URL) // 解码

// 只对URL整个连接进行编码或者解码
encodeURIComponent(URL) // 编码
decodeURIComponent(URL) // 解码

// 演示示例:
encodeURI('http://iecoxe.top:5000/v1/kuwo/search?key=你好')
// 输出结果: 'http://iecoxe.top:5000/v1/kuwo/search?key=%E4%BD%A0%E5%A5%BD'

encodeURIComponent('http://iecoxe.top:5000/v1/kuwo/search?key=你好')
// 输出结果: 'http%3A%2F%2Fiecoxe.top%3A5000%2Fv1%2Fkuwo%2Fsearch%3Fkey%3D%E4%BD%A0%E5%A5%BD'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# HTTP请求

参考: 文档:XMLHttpRequest (opens new window) 文档:同步和异步请求 (opens new window)

var xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.open(method, url, async);
xhr.open(method, url, async, user);
xhr.open(method, url, async, user, password);

// 参数
method:   要使用的 HTTP 方法,比如 GET、POST、PUT、DELETE、等。对于非 HTTP(S) URL 被忽略。
url:      一个 DOMString 表示要向其发送请求的 URL。
async:    可选的布尔参数,表示是否异步执行操作,默认为 true。如果值为 false,send() 方法直到收到答复前不会返回。如果 true,已完成事务的通知可供事件监听器使用。如果 multipart 属性为 true 则这个必须为 true,否则将引发异常。
user:     可选的用户名用于认证用途;默认为 null。
password: 可选的密码用于认证用途,默认为 null。

1
2
3
4
5
6
7
8
9
10
11
12
13

# HTTP性能

HTTP参考文档: (opens new window)

# HTTP1.1

HTTP1.1协议请求只能串行发送:HTTP1.1协议规定请求只能串行发送,也就是说一百个请求必须依次逐个发送,前面的一个请求完成才能开始下个请求 虽然不会花费tcp三次握手时间:但是本身是串行请求 HTTP1.1如果要同时发起多个请求,就得建立多个 TCP 连接,因为一个 TCP 连接同时只能处理一个 HTTP1.1的请求。

# HTTP2

在HTTP2 上,多个请求可以共用一个 TCP 连接,这称为多路复用。同一个请求和响应用一个流来表示,并有唯一的流 ID 来标识。 多个请求和响应在 TCP 连接中可以乱序发送,到达目的地后再通过流 ID 重新组建。

# 异步请求

演示一个简单的异步请求

// 第 2 行中指定第三个参数为 true,表示该请求应该以异步模式执行。
// 第 3 行创建一个事件处理函数对象,并将其分配给请求的 onload 属性。此处理程序查看请求的 readyState,以查看事务是否在第 4 行完成,如果是,并且 HTTP 状态为 200,则转储接收到的内容。如果发生错误,则显示错误消息。
// 第 15 行实际上启动了请求。只要请求的状态发生变化,就会调用回调程序。

var xhr = new XMLHttpRequest();
xhr.open("GET", "/bar/foo.txt", true);
xhr.onload = function (e) {
  if (xhr.readyState === 4) {
    if (xhr.status === 200) {
      console.log(xhr.responseText);
    } else {
      console.error(xhr.statusText);
    }
  }
};
xhr.onerror = function (e) {
  console.error(xhr.statusText);
};
xhr.send(null);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 设置请求超时

示例: 设置请求超时

// 你可以使用一个超时设置,来避免你的代码为了等候读取请求的返回数据长时间执行。超时毫秒数可以通过为 XMLHttpRequest 对象的 timeout 属性赋值来指定
 var xhr = new XMLHttpRequest();
xhr.ontimeout = function () {
    console.error("The request for " + url + " timed out.");
};
xhr.onload = function() {
    if (xhr.readyState === 4) {
        if (xhr.status === 200) {
            console.log(xhr.responseText);
        } else {
            console.error(xhr.statusText);
        }
    }
};
xhr.open("GET", url, true);
xhr.timeout = 2000;
xhr.send(null);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 同步请求

例子:http 同步请求

var request = new XMLHttpRequest();
request.open('GET', 'http://www.mozilla.org/', false);
request.send(null);
if (request.status === 200) {
  console.log(request.responseText);
}
1
2
3
4
5
6

# http请求封装

// http请求
class httpRequest{


    // new 初始化时执行
    constructor(timeout = 4000){
        this.headerData = null
        this.requestHeader = []
        this.timeout = timeout
    }



    // 定义私有方法: 格式化请求头
    #setHeader(xhr,header){
        
        // xhr无法设置的请求头
        let disableHeader = `
            Accept-Charset Accept-Encoding Access-Control-Request-Headers 
            Access-Control-Request-Method Connection Content-Length 
            Cookie Cookie2 Date DNT Expect Host Keep-Alive Origin User-Agent 
            Proxy- Sec- Referer TE Trailer Transfer-Encoding Upgrade Via     
        `;

        let data = []
        if(this.headerData != header){
            this.headerData = header;
            header = header.split('\n')
            header.forEach(list =>{
                list = list.replace(/(^\s*)|(\s*$)/g, "")
                if(list.length > 0){
                    list = list.split(':')
                    if(list.length > 1){
                        let bool = RegExp(list[0]).test(disableHeader),
                            bool2 = RegExp(list[0].split('-')[0]).test(disableHeader)
                        if(bool||bool2){
                            console.log('无法设置请求头: ',list[0])
                        }else{
                            xhr.setRequestHeader(list[0],list[1])
                            data.push(list)
                        }
                    }
                }
            })

            this.requestHeader = data;

        
        }else{

            this.requestHeader.forEach(list=>{
                xhr.setRequestHeader(list[0],list[1])
            })
        }
    }





    // http发送数据
    send(url,header=`null`,data){
        let xhr = new XMLHttpRequest();
        xhr.open("POST",url,true);
        if(header != null) this.#setHeader(xhr,header)
        xhr.send(data);
    }



    // http同步请求:效率低:容易操作
    getSync(url, header=`null`, statusCode=200) {
        let res = false;
        let xhr = new XMLHttpRequest();
        xhr.open('GET', url, false);
        if(header != null) this.#setHeader(xhr,header)

        xhr.send();
        if (xhr.status === statusCode) {
            res = JSON.parse(xhr.responseText)
        } else {
            console.error(xhr.statusText);
        }

        return res;
    }




    // http异步等待实现:同步:效率中:不好操作 
    async getAsyncAwait(url, callback, header=`null`, statusCode=200){
        let _this = this,
            asyncFuns = this.getAsync

        const request = () => {
            return new Promise(resolve => {
                asyncFuns(url,resolve,header,statusCode,_this)
            })
            
        }

        let resolve = await request()
        callback(resolve)
        
    }




    // http异步请求:效率高:不好操作
    getAsync(url, callback, header=`null`, statusCode=200, _this=null){
        if(_this == null) _this = this
        let timeout = _this.timeout

        let xhr = new XMLHttpRequest();
        if(timeout != 0) xhr.ontimeout = ()=>{ console.error('请求超时了: ' + url) }
        xhr.onload = function() {
            if (xhr.readyState === 4 && xhr.status === statusCode) {
                callback(JSON.parse(xhr.responseText));
            } else {
                console.log('错误',xhr.statusText);
            }
            
        }

        xhr.open("GET", url, true);
        if(header != null) _this.#setHeader(xhr,header)
        if(timeout != 0) xhr.timeout = timeout;
        
        try{
            xhr.send();
        }catch(e){
            console.log('请求失败')
            xhr.send();
        }
    }
   
}


// 请求头格式
let header = `
    Accept: */*
    scheme: https
    Accept-Encoding: gzip, deflate
    Accept-Language: zh-CN,zh;q=0.9
    Connection: keep-alives
    Host: www.kuwo.cn
    Referer: https://www.baidu.com/
    Sec-ch-ua-platform: macOS
    Set-Cookie: widget_session=abc1235; SameSite=None; Secure
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36
`
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154

# JS性能优化

# 避免if嵌套造成执行效率低下问题

// 例如:这样
if
   if
     if
       if
         do something
       endif
     endif
   endif
 endif
1
2
3
4
5
6
7
8
9
10
编辑 (opens new window)
Electron跨平台开发笔记
常用的ES5和ES6中对象的导出和导入的差异之处

← Electron跨平台开发笔记 常用的ES5和ES6中对象的导出和导入的差异之处→

最近更新
01
theme-vdoing-blog博客静态编译问题
09-16
02
搜索引擎
07-19
03
友情链接
07-19
更多文章>
Theme by Vdoing | Copyright © 2019-2022 Evan Xu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式