秋招复习计划-JavaScript知识点4

  |  

前言

Array.sort()方法与实现机制,Ajax的请求过程,JS的垃圾回收机制,JS中的String、Math方法,addEventListener和onClick()的区别。


26



Array.sort()方法与实现机制

Array.sort()的定义与使用方法

sort()方法在适当的位置对数组进行排序,并且返回数组。

arrayObject.sort(sortby)

sortby参数是可选的,必须是一个函数,函数为比较函数,规定排序顺序。

sort()默认的排序是升序,且它的排序是按照字符串的Unicode码的顺序,举个例子

1
2
let arr = [1, 3, 10, 4, 2];
arr.sort(); // [1, 10, 2, 3, 4]

如果想要按照特定的方式排序,就需要提供比较函数。比较函数接收两个参数。该函数比较两个值的代销,然后返回要给用于说明这两个值的相对顺序的数字。

如果第一个参数应该位于第二个参数前则返回一个负数,如果两个参数相等返回0,如果第一个参数应该位于第二个之后则返回一个正数。

Ajax请求过程

GET请求

创建请求对象

1
2
3
4
5
if(window.XMLHttpRequest) {
var xhr = new XMLHttpRequest;
} else {
var xhr = ActiveXObject("Microsoft.XMLHTTP");
}

设置对xhr对象请求状态的监听函数,并对获取到的后台数据进行处理

readystate: xhr请求对象的请求状态

  • 1:请求建立连接(open,但没有执行send)
  • 2:请求已发送,正在处理(send)
  • 3:请求已处理,并且已经得到部分数据
  • 4:请求已完成,并且已经获取到所有数据
1
2
3
4
5
6
7
8
9
xhr.onreadystatechange = function() {
if(xhr.readystate == 4) {
if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
var arr = JSON.parse(xhr.responseText);
} else {
console.log("请求失败");
}
}
}

创建请求,并设置请求方式,URL和同步还是异步请求

1
2
xhr.open("GET", "ajax.php?username" + username + "&password=" + password, false);
//默认为异步,设置为true为异步,false为同步

发送请求

1
xhr.send()

POST请求

前两步和GET方法一致

设置请求方式、网址和同异步

1
xhr.open("POST", "ajax.php", true)

设置请求头

1
2
3
4
5
6
7
8
9
10
11
12
xhr.setRequestHeader("Content-type","application/json; charset=utf-8");
//发送JSON格式数据
xhr.setRequestHeader("Content-type","application.x-www-form-urlencoded;charset=utf-8");
//发送表单数据
xhr.setRequestHeader("Content-type","text/plain;charset=utf-8");
//发送纯文本
xhr.setRequestHeader("Content-type","text/html;charset=utf-8");
//发送html文本
xhr.setRequestHeader("Content-type","application/json");
//编码可带可不带
xhr.setRequestHeader("Content-type","Application/Json");
//大小写不敏感,但是最好保持小写

发送请求

1
xhr.send("username=" + username + "&password=" + password)

JS的垃圾回收机制

JavaScript内存管理于我们来说是自动的、不可见的。当我们创建原始类型、对象、函数等等时,都会占用内存。虽然我们不用自己去管理内存,但是了解一下当数据不在被需要时,JavaScript引擎如何发现并清除它们,可以在我们遇到问题的时候快速的找到解决方法。

可触及

JavaScript内存管理的关键概念是可触及(REachability)

可触及的值是可访问且可用的,它们被安全的存储在内存中。

必定可触及的值:

  • 当前函数的局部变量和参数
  • 当前调用链中所有函数的局部变量和参数
  • 全局变量
  • 其它内部变量

这些值都被称为root。

而其它值是否可触及则要看它是否被root及其引用链引用。

JavaScript引擎有一个垃圾回收的后台进程,监控着所有对象,当对象不可触及时会将其删除。

互相引用下的不可触及

1
2
3
4
5
6
7
8
9
10
function marry(man, women) {
man.wife = women;
women.husband = man;
return {
father: man,
mother: women
}
}

let family = marry({name: 'John'}, {name: 'Ann'}),

在这个示例中marry函数让传入的两个参数对象互相引用,返回一个包含两者的新对象,结构如下:

互相引用1

如果我们在这时切断对father对象的所有引用

1
2
delete family.father;
delete family.mother.husband

那么结构就变成了这样的

互相引用2

那么father这个对象已经变得不可触及了,虽然它人保持对其它对象的引用,但它还是会被移除

互相引用3

移除后的结构就变成了

互相引用4

孤岛

当一堆互相引用的对象整块都不可触及时(就像一个孤岛)

譬如针对相面这个例子

1
family = null

那么marry函数返回的对象就变成了一个孤岛,等待的只有被垃圾回收进程回收。

垃圾回收算法

标记—清除法

大概的流程如下:

  • 垃圾收集器为所有存储在内存中的变量加上标记
  • 变量进入执行环境或被进入执行环境的变量引用时,去掉标记
  • 当被去掉标记的变量不可触及时,再次加上标记
  • 垃圾收集器根据标记销毁对应的值,释放它们的内存空间。

引用计数法

这个方法并不常用,简单的来说就i是当一个变量被引用时,则它的引用次数加一,不再被引用时减一,当它的计数为0时,说明他不再被引用,垃圾收集器将其回收。但是这种方法存在对应的问题,就是当两个对象会像引用时,他们的的引用计数就不可能变成0,将永远不会被回收。

减少垃圾回收

从垃圾回收的机制来说,虽然它减少了内存的占用,但是,如果每次程序执行都有大量的内存需要回收,那么垃圾回收机制的执行将阻碍程序的执行的性能,所有我们需要尽量减少垃圾回收。

对象优化

很多时候我们在定义函数的时候会存在将一个对象作为函数的返回结果。

1
2
3
4
5
function fun() {
return {
foo: 'bar'
}
}

但是使用这种方法,每调用一次方法,就会占用一个新的内存空间,而当这个返回值不在被使用后,就会触发垃圾回收。解决这个问题的方法是,将需要返回的数据放入一个全局对象中,并返回这个全局对象

1
2
3
4
5
6
7
let value;
function fun() {
value = {
foo: 'bar'
}
return value
}

这样虽然减少了垃圾回收,但是这也意味着每一方法调用都会导致全局对象内容的修改,这可能会导致意外的错误,所以需要谨慎的使用这种方法。

数组的优化

通常情况下,如果我们要清空一个数组,大多将一个[]赋给原有的变量,但是,这种方式只是新建了一个空数组对象,并改变了原有的引用,而原来的数组对象在失去引用后就会变成一小块的内存来及。其实将数组长度赋值为0,及arr.length = 0也能达到清空数组的目的。

方法的优化

方法一般都在初始化时创建,并且以后很少在运行时进行动态内存分配。这也意味着只要是动态创建的方法,很有可能就会存在内存垃圾。例如

1
2
3
4
5
setTimeou((function(self) {
return function() {
self.tick();
}
})(this), 16)

这个函数的功能很明显,就是每16毫秒调用一次this.tick()。但是要知道的是,每隔16毫秒,调用的是立即执行函数,而立即执行函数每次都会返回一个新的方法对象用于执行,这也就意味着会创建大量的内存垃圾。

解决这个问题的方法也很简单,将要执行的函数作为返回值保存起来

1
2
3
4
5
6
this.tickFunc = (function(self) {
return function() {
selft.tick();
}
})(this);
setTimeout(this.tickFunc, 16);

相比于每次都新建一个方法对象,这种方法在每一帧中都重用相同的方法对象。这种思想可以应用于任何以方法为返回值或者在运行时创建方法的情况中。

JS中的String、Math方法

String方法

字符方法:

str.charAt(index):返回对应下标的字符

str.charCodeAt(index):返回对应下标字符的Unicode编码

String.fromCharCode(num1, num2, ... numN):返回由参数中Unicode码值构成的字符串

1
String.fromCharCode(74, 75, 76); // 'JKL'

字符串操作方法

str.concat(str1, str2,....):将字符串str1,str2….拼接到str上,并返回新字符串,并不影响str

字符串截取

str.substring(start, end):两个参数都为正数,返回一个从[start, end-1)的字符串,并不影响原字符串

str.slice(start, end):两个参数可负可正,负数代表从右开始数,但是截取还是从左往右,而且无论正负,start代表的字符一定要在end右边

str.substr(start, length):start可正可负,length表示截取长度,截取还是从左往右

字符串位置方法

str.indexOf(searchString, startIndex):从startIndex下标位置开始查找,返回searchString第一次出现的位置,找不到时返回-1

str.lastIndexOf(searchString, startIndex):从右往左找searchString,找不到时返回-1,返回的还是一个正数下标

Str.trim()方法

删除字符串前后的空格

字符串大小写转换方法

str.toLowerCase():将字符串全部转换为小写

str.toUpperCase():将字符串全部转换为大写

字符串分割函数

str.split(separator, limit):参数1为指定字符或正则表达式,参数2指定数组的最大长度,函数会根据参数1来对字符串进行分割,返回数组

localeCompare方法

str.localeCompare(str2):将str2与str进行比较,如果str在字母表中应该排在str2之前,返回一个负数,相等,返回0,之后返回一个正数

字符串正则匹配

str.match(regExp):接收一个字符串或正则表达式作为参数,返回匹配的子字符串,如果没有匹配的值,返回null

str.search(regExp):接收一个字符串或正则表达式作为参数,返回匹配到的字符串的下标,如果没有匹配的,返回-1

字符串替换方法

str.replace(regExp, replaceText):用replaceText字符串去替换str中符合regExp的内容,如果regExp知识一个字符串,只会替换第一个匹配的,如果是一个正则表达式,替换所有。

math方法

Math.min():返回数组中的最小值

Math.max():返回数组中的最大值

Math.ceil():执行向上舍入

Math.floor():执行向下舍入

Math.round():执行标准舍入

Math.random()返回一个介于0到1之间的一个随机数,不包括0和1

方 法 说 明
Math.abs(num) 返回num的绝对值
Math.exp(num) 返回Math.E的num次幂
Math.log(num) 返回num的自然对数
Math.pow(num,power) 返回num的power次幂
Math.sqrt(num) 返回num的平方根
Math.acos(x) 返回x的反余弦值
Math.asin(x) 返回x的反正弦值
Math.atan(x) 返回x的反正切值
Math.atan2(y,x) 返回y/x的反正切值
Math.cos(x) 返回x的余弦值
Math.sin(x) 返回x的正弦值
Math.tan(x) 返回x的正切值

addEventListener和onClick()的区别。

是否覆盖

onclick添加事件不能绑定多个事件,这也就意味着后面绑定的事件会覆盖之前绑定的事件

1
2
3
4
5
6
box.onclick = function() {
alert(1)
}
box.onclick = function() {
alert(2)
}

alert(2)会覆盖alert(1)

addEventListener能添加多个事件绑定,按顺序执行

1
2
3
4
5
6
box.addEventListener('click', () => {
alert(1)
}, false)
box.addEventListener('click', () => {
alert(2)
})

alert(1)和alert(2)会按顺序触发

触发事件的种类

onclick只能由点击事件触发,而addEventListener则可绑定任何可触发事件

是否可取消

onclick绑定事件后不可取消,而addEventListener绑定后则可以用removeEventListener取消

是否可以采取事件捕获

onclick不能对事件捕获或事件冒泡进行控制,只能使用事件冒泡,无法切换成事件捕获

addEventListener可以通过第三个参数来控制事件的触发是采用那种形式,为true是,浏览器采用事件捕获,为false是,采用冒泡,建议采用冒泡

事件冒泡:事件从最底层的dom节点冒泡到根节点,按此触发对应绑定

事件捕获:事件从最先捕获的元素到最后捕获的元素

文章目录
  1. 1. Array.sort()方法与实现机制
    1. 1.1. Array.sort()的定义与使用方法
  2. 2. Ajax请求过程
    1. 2.1. GET请求
    2. 2.2. POST请求
  3. 3. JS的垃圾回收机制
    1. 3.1. 可触及
    2. 3.2. 互相引用下的不可触及
    3. 3.3. 垃圾回收算法
    4. 3.4. 减少垃圾回收
  4. 4. JS中的String、Math方法
    1. 4.1. String方法
    2. 4.2. math方法
  5. 5. addEventListener和onClick()的区别。
|