Ajax实现音乐播放器
//获取随机频道信息
function getChannel(){
$.ajax({
url: 'http://api.jirengu.com/fm/getChannels.php',
dataType: 'json',
Method: 'get',
success: function(response){
var channels = response.channels;
var num = Math.floor(Math.random()*channels.length);
var channelname = channels[num].name;//获取随机频道的名称
var channelId = channels[num].channel_id;//获取随机频道ID
$('.record').text(channelname);
$('.record').attr('title',channelname);
$('.record').attr('data-id',channelId);//将频道ID计入data-id中
getmusic();
}
})
}
// 通过ajax获取歌曲
function getmusic(){
$.ajax({
url: 'http://api.jirengu.com/fm/getSong.php',
dataType: 'json',
Method: 'get',
data:{
'channel': $('.record').attr('data-id')
},
success: function (ret) {
var resource = ret.song[0],
url = resource.url,
bgPic = resource.picture,
sid = resource.sid,//获取歌词的参数
ssid = resource.ssid,//获取歌词的参数
title = resource.title,
author = resource.artist;
$('audio').attr('src',url);
$('.musicname').text(title);
$('.musicname').attr('title',title)
$('.musicer').text(author);
$('.musicer').attr('title',author)
$(".background").css({
'background':'url('+bgPic+')',
'background-repeat': 'no-repeat',
'background-position': 'center',
'background-size': 'cover',
});
play();//播放
}
})
};
Ajax请求五个步骤
-
创建XMLHttpRequest异步对象
var xhr = new XMLHttpRequest()
-
设置回调函数
xhr.onreadystatechange = callback
-
与服务器建立连接
- open(method,url,async):规定请求的类型、URL 以及是否异步处理请求。
- method:请求的类型;GET 或 POST
- url:文件在服务器上的位置
- async:true(异步)或 false(同步)
- send(string):将请求发送到服务器。
- string:仅用于 POST 请求
xmlhttp.open("GET","ajax_info.txt",true); xmlhttp.send(); // open - get 方式 xhr.open("get", "test.php", true) // open - post 方式发送数据 需要设置请求头 xhr.open("post", "test.php", true) xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
- open(method,url,async):规定请求的类型、URL 以及是否异步处理请求。
-
向服务器发送数据
// get 不需要传递参数 xhr.send(null) // post 需要传递参数 xhr.send("name=jay&age=18")
-
在回调函数中针对不同的响应状态进行处理
function callback() { // 判断异步对象的状态 if(xhr.readyState == 4) { // 判断交互是否成功 if(xhr.status == 200) { // 获取服务器响应的数据 var res = xhr.responseText // 解析数据 res = JSON.parse(res) } } }
-
如果需要获取服务器的响应
POST和GET的区别
Get和Post都是向服务器发送的一种请求,只是发送机制不同。
1、发送的数据数量
在Get中,只能发送有限数量的数据,因为数据是在URL中发送的;
在POST中,可以发送大量的数据,因为数据是在正文主体中发送的。
2、安全性
GET方法发送的数据不受保护,因为数据在URL栏中公开,这增加了漏洞和黑客攻击的风险。
POST方法发送的数据是安全的,因为数据未在URL栏中公开,还可以在其中使用多种编码技术,这使其具有弹性。
3、加入书签中
GET查询的结果可以加入书签中,因为它以URL的形式存在;而POST查询的结果无法加入书签中。
4、编码
在表单中使用GET方法时,数据类型中只接受ASCII字符。
在表单提交时,POST方法不绑定表单数据类型,并允许二进制和ASCII字符。
5、可变大小
GET方法中的可变大小约为2000个字符。而,POST方法最多允许8 Mb的可变大小。
6、缓存
GET方法的数据是可缓存的,而POST方法的数据是无法缓存的。
7、主要作用
GET方法主要用于获取信息。而,POST方法主要用于更新数据。
get请求和post请求在服务器端的区别:
- 在客户端使用get请求时,服务器端使用Request.QueryString来获取参数,而客户端使用post请求时,服务器端使用Request.Form来获取参数.
HTTP标准包含这两种方法是为了达到不同的目的。POST用于创建资源,资源的内容会被编入HTTP请示的内容中。例如,处理订货表单、在数据库中加入新数据行等。
当请求无副作用时(如进行搜索),便可使用GET方法;当请求有副作用时(如添加数据行),则用POST方法。一个比较实际的问题是:GET方法可能会产生很长的URL,或许会超过某些浏览器与服务器对URL长度的限制。
若符合下列任一情况,则用POST方法:
* 请求的结果有持续性的副作用,例如,数据库内添加新的数据行。
* 若使用GET方法,则表单上收集的数据可能让URL过长。
* 要传送的数据不是采用7位的ASCII编码。
若符合下列任一情况,则用GET方法:
* 请求是为了查找资源,HTML表单数据仅用来帮助搜索。
* 请求结果无持续性的副作用。
* 收集的数据及HTML表单内的输入字段名称的总长不超过1024个字符。
访问一个URL过程
客户端获取URL - > DNS解析 - > TCP连接 - >发送HTTP请求 - >服务器处理请求 - >返回报文 - >浏览器解析渲染页面 - > TCP断开连接
DNS解析
当用户输入一个网址并按下回车键的时候,浏览器得到了一个域名。而在实际通信过程中,我们需要的是一个IP地址。因此我们需要先把域名转换成相应的IP地址,这个过程称作DNS解析。
1、浏览器首先搜索浏览器自身缓存的DNS记录。
2、如果浏览器缓存中没有找到需要的记录或记录已经过期,则搜索hosts文件和操作系统缓存。
在Windows操作系统中,可以通过 ipconfig /displaydns 命令查看本机当前的缓存。
通过hosts文件,你可以手动指定一个域名和其对应的IP解析结果,并且该结果一旦被使用,同样会被缓存到操作系统缓存中。
Windows系统的hosts文件在%systemroot%\system32\drivers\etc下,linux系统的hosts文件在/etc/hosts下。
3、如果在hosts文件和操作系统缓存中没有找到需要的记录或记录已经过期,则向域名解析服务器发送解析请求。
4、如果域名解析服务器也没有该域名的记录,则开始递归+迭代解析。
TCP三次握手
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接.
- 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认; SYN:同步序列编号(Synchronize Sequence Numbers)
- 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
- 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手.
TCP为什么是三次握手?
-
为了实现可靠数据传输, TCP 协议的通信双方, 都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤。
-
一次握手的情况:
由于TCP是面向连接的,一次很明显时不可能的,因为客户端发出连接消息后,却没有接收到来自服务端的回应,客户端就无法确定服务端接是否收到了连接请求,当然也就不能确定是否连接成功。
-
两次握手的情况:
防止已失效的连接请求又传送到服务器端,因而产生错误。
如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认。
TCP四次挥手
1)客户端进程发出连接释放报文,并且停止发送数据。
2)服务器收到连接释放报文,发出确认报文,服务端就进入了CLOSE-WAIT(关闭等待)状态。
3)客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
4)服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
5)客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。
6)服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
主动方发送标志位:(ACK + FIN)+(发送序号= 200 +确认序号= 500)第一次挥手
被动方接收后发送标志位:ACK +(发送序号=主动方确认序号500 +确认序号=主动方发送序号+1201)第二次挥手
标志位:(ACK + FIN)+(发送序号=主动方确认序号+1 501)第三次挥手
主动方接收后发送标志位:(ACK)+(发送序号=被动方的确认序号201 +确认序号=被动方的发生序号+1502)
TCP为什么是四次挥手?
关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,我们也未必全部数据都发送给对方了,所以我们不可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接。因此,我们的ACK和FIN一般都会分开发送。
TCP、UDP区别总结
1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
Tcp通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。
3、UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
4.每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
5、TCP对系统资源要求较多,UDP对系统资源要求较少。
TCP滑动窗口机制
首先我们知道TCP可靠传输原理中的停止等待协议,该协议就是发送方每发送一个报文段后就停止发送,一直等收到接收方的确认后再发送下一个报文段。
- TCP通信是全双工的,我们假定A为发送方,B为接收方。A会有一个发送窗口,B有一个接收窗口。
- 发送窗口表示在没有收到B确认的情况下,A也可以连续把发送窗口的数据发送出去。但是已经发送过的数据在未收到确认之前,它还需要暂时保留,以便于超时重传时使用。发送窗口越大,它就可以在收到对方确认之前发送更多的数据,因而获得更高的传输效率。
- 1比特滑动窗口协议:发送窗口等于1,接收窗口等于1
- 当发送窗口和接收窗口的大小固定为1时,滑动窗口协议退化为停等协议。该协议规定发送方每发送一帧后就要停下来,等待接收方已正确接收的确认(ACK)返回后才能继续发送下一帧。由于接收方需要判断接收到的帧是新发的帧还是重新发送的帧,因此发送方要为每一个帧加一个序号。由于停等协议规定只有一帧完全发送成功后才能发送新的帧,因而只用一比特来编号就够了,具有累计确认机制。
- 回退N帧协议(发送窗口大于1,接收窗口大于1)
- 由于停等协议要为每一个帧进行确认后才继续发送下一帧,大大降低了信道利用率,因此又提出了后退n协议。后退n协议中,发送方在发完一个数据帧后,不停下来等待应答帧,而是连续发送若干个数据帧,即使在连续发送过程中收到了接收方发来的应答帧,也可以继续发送。且发送方在每发送完一个数据帧时都要设置超时定时器。只要在所设置的超时时间内仍收到确认帧,就要重发相应的数据帧。如:当发送方发送了N个帧后,若发现该N帧的前一个帧在计时器超时后仍未返回其确认信息,则该帧被判为出错或丢失,此时发送方就不得不重新发送出错帧及其后的N帧。
- 选择重传协议(发送窗口大于1,接收窗口大于1)
- 在后退n协议中,接收方若发现错误帧就不再接收后续的帧,即使是正确到达的帧,这显然是一种浪费。另一种效率更高的策略是当接收方发现某帧出错后,其后继续送来的正确的帧虽然不能立即递交给接收方的高层,但接收方仍可收下来,存放在接收缓冲区中,同时要求发送方重新传送出错的那一帧。一旦收到重新传来的帧后,就可以原已存于缓冲区中的其余帧一并按正确的顺序递交高层。这种方法称为选择重发(SELECTICE REPEAT)。显然,选择重发减少了浪费,但要求接收方有足够大的缓冲区空间
为什么UDP有时比TCP更有优势?
UDP以其简单、传输快的优势,在越来越多场景下取代了TCP,如实时游戏。
(1)网速的提升给UDP的稳定性提供可靠网络保障,丢包率很低,如果使用应用层重传,能够确保传输的可靠性。
(2)TCP为了实现网络通信的可靠性,使用了复杂的拥塞控制算法,建立了繁琐的握手过程,由于TCP内置的系统协议栈中,极难对其进行改进。
采用TCP,一旦发生丢包,TCP会将后续的包缓存起来,等前面的包重传并接收到后再继续发送,延时会越来越大,基于UDP对实时性要求较为严格的情况下,采用自定义重传机制,能够把丢包产生的延迟降到最低,尽量减少网络问题对游戏性造成影响。
网络七层模型(OSI模型)
- 五层模型即应用层、表示层、会话层统称为应用层。
【1】应用层(Application Layer)
应用层是最靠近用户的OSI层。这一层为用户的应用程序(例如电子邮件、文件传输和终端仿真)提供网络服务。 主要负责对软件提供接口以使程序能使用网络服务。术语“应用层”并不是指运行在网络上的某个特别应用程序 ,应用层提供的服务包括文件传输、文件管理以及电子邮件的信息处理。
协议有:HTTP FTP TFTP SMTP SNMP DNS TELNET HTTPS POP3 DHCP等。
【2】表示层(Presentation Layer)
数据的表示、安全、压缩。可确保一个系统的应用层所发送的信息可以被另一个系统的应用层读取。表示层管理数据的解密与加密,如系统口令的处理。除此之外,表示层协议还对图片和文件格式信息进行解码和编码。
格式有:JPEG、ASCll、DECOIC、加密格式等。
【3】会话层(Session Layer)
建立、管理、终止会话,对应主机进程,指本地主机与远程主机正在进行的会话。负责在网络中的两节点之间建立、维持和终止通信。
会话层的功能包括:建立通信链接,保持会话过程通信链接的畅通,同步两个节点之间的对话,决定通信是否被中断以及通信中断时决定从何处重新发送。
【4】传输层(Transport Layer)
定义传输数据的协议端口号,以及流控和差错校验。
协议有:TCP UDP等,数据包一旦离开网卡即进入网络传输层。
【5】网络层(Network Layer)
进行逻辑地址寻址,实现不同网络之间的路径选择。OSI模型的第三层,其主要功能是将网络地址翻译成对应的物理地址,并决定如何将数据从发送方路由到接收方。网络层负责在源机器和目标机器之间建立它们所使用的路由。这一层本身没有任何错误检测和修正机制,因此,网络层必须依赖于端端之间的由D L L提供的可靠传输服务。
协议有:ICMP IGMP IP(IPV4 IPV6) ARP RARP等。
【6】数据链路层(Datalink Layer)
建立逻辑连接、进行硬件地址寻址、差错校验等功能。(由底层网络定义协议),定义了如何让格式化数据以进行传输,以及如何让控制对物理介质的访问。这一层通常还提供错误检测和纠正,以确保数据的可靠传输。OSI模型的第二层,它控制网络层与物理层之间的通信。它的主要功能是如何在不可靠的物理线路上进行数据的可靠传递。
数据链路层协议的代表包括:SDLC、HDLC、PPP、STP、帧中继等。
数据链路层在不可靠的物理介质上提供可靠的传输。该层的作用包括:物理地址寻址、数据的成帧、流量控制、数据的检错、重发等。
【7】物理层(Physical Layer)
建立、维护、断开物理连接。(由底层网络定义协议),主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后在转化为1、0,也就是我们常说的数模转换与模数转换)。这一层的数据叫做比特。
OSI模型的最低层或第一层,该层包括物理连网媒介,如电缆连线连接器。
浏览器渲染页面的原理及流程
1.根据html文件构建DOM树和CSSOM树。构建DOM树期间,如果遇到JS,阻塞DOM树及CSSOM树的构建,优先加载JS文件,加载完毕,再继续构建DOM树及CSSOM树。
2.构建渲染树(Render Tree)。
3.页面的重绘(repaint)与重排(reflow,也有称回流)。页面渲染完成后,若JS操作了DOM节点,根据JS对DOM操作动作的大小,浏览器对页面进行重绘或是重排。
重绘和重排
重绘是指一个元素外观的改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。
重排(重构/回流/reflow):当渲染树中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建, 这就称为回流(reflow)。每个页面至少需要一次回流,就是在页面第一次加载的时候。
重排必定会引发重绘,但重绘不一定会引发重排。
原型和原型链
- 原型是什么 ?
一个对象,我们也称为 prototype 为原型对象。是一个对象上面的原型,这个原型通常是它的构造器的prototype属性 - 什么时候用 prototype
使用 prototype的好处是不会额外产生内存,所有实例化后的对象都会从原型上继承这个方法。也就是需要一个子类拥有父类的某些特性(同种特性可以覆盖),又可以添加自己的特性,而不会影响父类时候使用prototype。 - 原型的作用是什么 ?
共享方法。
闭包
闭包就是能够读取其他函数内部变量的函数。由于在javascript中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成“定义在一个函数内部的函数“。所以,在本质上,闭包是将函数内部和函数外部连接起来的桥梁
-
闭包的好处有:
1.缓存
2.面向对象中的对象
3.实现封装,防止变量跑到外层作用域中,发生命名冲突
4.匿名自执行函数,匿名自执行函数可以减小内存消耗
-
闭包的坏处:
1.内存消耗
通常来说,函数的活动对象会随着执行期上下文一起销毁,但是,由于闭包引用另外一个函数的活动对象,因此这个活动对象无法被销毁,这意味着,闭包比一般的函数需要更多的内存消耗。2.性能问题
使用闭包时,会涉及到跨作用域访问,每次访问都会导致性能损失。因此在脚本中,最好小心使用闭包,它同时会涉及到内存和速度问题。不过我们可以通过把跨作用域变量存储在局部变量中,然后直接访问局部变量,来减轻对执行速度的影响。
px、em、rem的区别
一、px是固定的像素,一旦设置了就无法因为适应页面大小而改变。
二、em和rem相对于px更具有灵活性,他们是相对长度单位,意思是长度不是定死了的,更适用于响应式布局。
三、em是相对于其父元素来设置字体大小的,一般都是以的“font-size”为基准。这样就会存在一个问题,进行任何元素设置,都有可能需要知道他父元素的大小。而Rem是相对于根元素,这样就意味着,我们只需要在根元素确定一个参考值。
js内存管理机制
-
会在创建变量(对象,字符串等)时分配内存,并且在不再使用它们时“自动”释放内存,这个自动释放内存的过程称为垃圾回收。
-
内存生命周期
JS 环境中分配的内存有如下声明周期:
- 内存分配:当我们申明变量、函数、对象的时候,系统会自动为他们分配内存
- 内存使用:即读写内存,也就是使用变量、函数等
- 内存回收:使用完毕,由垃圾回收机制自动回收不再使用的内存
如果两个对象相互引用,尽管他们已不再使用,垃圾回收不会进行回收,导致内存泄露。
标记清除算法
标记清除算法将“不再使用的对象”定义为“无法达到的对象”。简单来说,就是从根部(在JS中就是全局对象)出发定时扫描内存中的对象。凡是能从根部到达的对象,都是还需要使用的。那些无法由根部出发触及到的对象被标记为不再使用,稍后进行回收。
工作流程:
1、垃圾收集器会在运行的时候会给存储在内存中的所有变量都加上标记。
2、从根部出发将能触及到的对象的标记清除。
3、那些还存在标记的变量被视为准备删除的变量。
4、最后垃圾收集器会执行最后一步内存清除的工作,销毁那些带标记的值并回收它们所占用的内存空间
造成内存泄漏的几种情况
- 闭包
function fn1(){
var n=1;
}
//我想取到里面的局部变量n
function fn1(){
var n=1;
function fn2(){//在加一个fn2当他的子集
alert(n);
}
}
//但是我在外面还是访问不到那就return出来
function fn1(){
var n=1;
function fn2(){//在加一个fn2当他的子集
alert(n);
}
return fn2();
//return出来后 他就给 window了所以一直存在内存中。因为一直在内存中,在IE里容易造成内存泄漏
}
fn1();
//尽量书写的时候,避免这种情况。
2.意外的全局变量
一个未声明变量的引用会在全局对象中创建一个新的变量。在浏览器的环境下,全局对象就是 window,也就是说:
function foo(arg) {
bar = "aaaaa";
}
//实际上等价于
function foo(arg) {
window.bar = "aaaaa";
}
function foo() {
this.variable = "qqqqq";
}
//this 指向全局对象(window)
foo();
//为了防止这种错误的发生,可以在你的 JavaScript 文件开头添加 'use strict'; 语句
3.定时器setTimeout setInterval
当不需要setInterval或者setTimeout时,定时器没有被clear,定时器的回调函数以及内部依赖的变量都不能被回收,造成内存泄漏。比如:vue使用了定时器,需要在beforeDestroy 中做对应销毁处理。js也是一样的。
clearTimeout(***)
clearInterval(***)
4.如果在mounted/created 钩子中使用了 o n , 需 要 在 b e f o r e D e s t r o y 中 做 对 应 解 绑 ( on,需要在beforeDestroy 中做对应解绑( on,需要在beforeDestroy中做对应解绑(off)处理
beforeDestroy() {
this.bus.$off('****');
}
5、给DOM对象添加的属性是一个对象的引用
var testObject = {};
document.getElementById('idname').property = testObject; //如果DOM不被消除,则testObject会一直存在,造成内存泄漏
解决方法:
//在window.onunload事件中写上:
window.onunload=function(){
document.getElementById('idname').property = null; //释放内存
};
6.DOM对象与JS对象相互引用
function testObject(element) {
this.elementReference = element; // 为testObject(js)对象的属性绑定element(DOM)对象
element.property = this; // 为element(DOM)对象的属性绑定testObject(js)对象
}
new testObject(document.getElementById('idname'));
解决方法:
在window.onunload事件中写上:
document.getElementById('idname').property = null;
7.从外到内执行appendChild。这时即使调用removeChild也无法释放
var parentDiv = document.createElement("div");
var childDiv = document.createElement("div");
document.body.appendChild(parentDiv);
parentDiv.appendChild(childDiv);
//解决方法:
//从内到外执行appendChild:
var parentDiv = document.createElement("div");
var childDiv = document.createElement("div");
parentDiv.appendChild(childDiv);
document.body.appendChild(parentDiv);
8.反复重写同一个属性会造成内存大量占用(但关闭IE后内存会被释放)
for(i = 0; i < 5000; i++) {
hostElement.text = "asdfasdfasdf";
}
//这种方式相当于定义了5000个属性!
9.注意程序逻辑,避免“死循环”之类的
10.echarts配合循环计时器等出现的内存泄漏
数据库操作的基本四类语法
查询语句
select * from dual
插入语句,将某一条数据插入进’dual’。
insert into dual(dummy) values(‘xxxxxx’)
更新语句,将’dual’数据中的某一条数据更新。
update dual set dummy = ‘xx’
删除语句,将’dual’表中数据全部删除。
delete dual
数据库事务
-
MySQL 事务主要用于处理操作量大,复杂度高的数据。
-
事务的特性(ACID)
原子性:构成事务的的所有操作必须是一个逻辑单元,要么全部执行,要么全部不执行。 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则。 隔离性:并发事务之间不会相互影响。 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。事务执行成功后必须全部写入磁盘。
vue实现双向数据绑定
vue实现数据双向绑定的原理就是用Object.defineproperty()重新定义(set方法)对象设置属性值和(get方法)获取属性值的操纵来实现的;
vue的数据双向绑定是通过数据劫持和发布-订阅者功能来实现的:
实现步骤:
- 实现一个监听者Oberver来劫持并监听所有的属性,一旦有属性发生变化就通知订阅者
- 实现一个订阅者watcher来接受属性变化的通知并执行相应的方法,从而更新视图
- 实现一个解析器compile,可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相对应的订阅者
这个方法会直接在一个对象上定义一个新属性或者修改对象上的现有属性,并返回该对象,通过Object.defineProperty()方法来实现,Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
Object.defineProperty()方法有三个参数:
Object.defineProperty(obj, key, options)
参数 | 功能/作用 |
---|---|
obj | 要修改或定义key值的对象 |
key | 对应obj对象的里面某有已有或要修改的属性 |
options | 这个参数对象里面有get,set两个函数,用来定义属性值 |
options有两种主要形式:数据描述符和存取描述符
数据描述符是一个具有值的属性,该值可能是可写的,也可能不是可写的
存取描述符是由getter-setter函数对描述的属性
描述符必须是这两种形式之一;不能同时是两者
JS清除左边空格
- trim()
- replace
- 字符串作数组判断空格
ES6模板字符串
在ES5中经常会用到拼接字符串,比如
let year = 3, pos = "前端";
"我已经有" + year + "年" + pos + "开发经验了";
输出结果是 => "我已经有3年前端开发经验了"
ES5中的拼接字符串在实际使用中效率不高,可读性极差;所以ES6对此作出了改进,推出了模板字符串,以上的代码就变成了
let year = 3, pos = "前端";
输出结果是 => "我已经有3年前端开发经验了"
模板字符串使用的是反引号(Tab键上边那个)
// 定义一个字符串
let year = 3, pos = "前端";
let str = "我已经有${year}年${pos}开发经验了";
function replace(str){
// 原理是通过正则匹配,替换原字符串中的变量
return str.replace(/\$\{([^}])\}/g,function(matched,key){
console.log(arguments) // arguments见下面
return eval(key)
})
}
console.log(replace(str)) => "我已经有3年前端开发经验了"
// 字符串repalce方法的arguments
{ '0': '${year}', // 大正则匹配项
'1': 'year', // 正则小分组匹配项
'2': 4, // 匹配项第一个元素在字符串中的索引
'3': '我已经有${year}年${pos}开发经验了' } // 原字符串
{ '0': '${pos}',
'1': 'pos',
'2': 12,
'3': '我已经有${year}年${pos}开发经验了' }
正则表达式
- 通过调用 RegExp 对象的构造函数创建 var 变量名 = new RegExp(/表达式/);
- 通过字面量创建var 变量名 = /表达式/;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H4H46vHI-1603003678191)(3A53931177B2473984B2159BF6918545)]
AMD 和 CMD 的区别
AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。
区别:
-
对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。
-
CMD 推崇依赖就近,AMD 推崇依赖前置。
-
AMD 的 API 默认是一个当多个用,CMD 的 API 严格区分,推崇职责单一。
HTTP,HTTPS
-
http:超文本传输协议,是一个客户端和服务端请求和应答的标准,用于从www服务器传输超文本到本地浏览器的传输协议。
-
https:是以安全为目标的http通道,http的安全版,即http下加入ssl层。
-
区别:
- 工作层:在OSI网络模型中,HTTP工作于应用层,而HTTPS工作在传输层。
- 连接端口:HTTP标准端口是80,而HTTPS的标准端口是443。
- 传输方式:HTTP是超文本传输协议,信息是明文传输,而HTTPS是SSL加密传输协议。
- 工作耗时:HTTP耗时=TCP握手,而HTTPS耗时=TCP握手+SSL握手。
- 显示形式:HTTP的URL以http://开头,而HTTPS的URL以https://开头。
- 费用:HTTP无需费用,而HTTPS需要到CA申请证书,一般免费证书较少,需要一定费用。
- 安全性:HTTP的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比HTTP协议安全。
http2.0
-
特性
1)内容安全:HTTP2.0是基于https的,天然具有安全性,通过http2.0的特性可以避免单纯使用https的性能下降。
2)二进制格式:http1.x的解析是基于本文的,http2.0将所有的传输信息分割为更小的消息和帧,并对他们采用二进制的格式编码。
3)多路复用:每个request请求可以随机的混杂在一起,接收方可根据request请求的id将其归属到各自不同的服务端请求内。
拷贝
如果想要把某个对象拷贝(合并) 给另外一个对象使用,此时可以使用 $.extend() 方法
语法:
$.extend([deep], target, object1, [objectN])
- deep: 如果设为true 为深拷贝, 默认为false 浅拷贝
- target: 要拷贝的目标对象
- object1:待拷贝到第一个对象的对象。
- objectN:待拷贝到第N个对象的对象。
- 浅拷贝目标对象引用的被拷贝的对象地址,修改目标对象会影响被拷贝对象。
- 深拷贝,前面加true, 完全克隆,修改目标对象不会影响被拷贝对象。
多库共存
jQuery 解决方案:
- 把里面的 $ 符号 统一改为 jQuery。 比如 jQuery(’‘div’’)
- jQuery 变量规定新的名称:$.noConflict() var xx = $.noConflict();
arguments 的使用
当我们不确定有多少个参数传递的时候, 可以 用 arguments 来 获取。
在JavaScript 中 arguments 实际上是当前函数的一个内置对象。所有函数都内置了一个 arguments对象,arguments对象中存储了传递的所有实参。
arguments展示形式是一个伪数组,因此可以进行遍历。伪数组具有以下特点:
- 具有length属性
- 按索引方式储存数据
- 不具有数组的push、pop等方法
验证arguments不是数组
//arguments 是没有数组的slice等方法的,所以不是Array类型的。
//验证:
function testargs(){
var arr=[1,2,3];
console.log(typeof arguments.slice);
console.log(typeof arr.slice);
}
testargs();
//输出:
undefined
function
arguments转为数组
function arg2arr(){
var arr = Array.prototype.slice.call(arguments);
//Array.prototype.slice.call(arguments, 0)
console.log(arr);
}
arg2arr(1,2,3);
剩余参数和arguments对象的区别
- 剩余参数只包含那些没有对应形参的实参,而arguments对象包含了传给函数的所有实参。
- arguments对象不是一个真正的数组,而剩余参数是真正的Array实例,也就是说你能够在它上面直接使用所有的数组方法,比如sort,map,forEach或pop。
- arguments对象还有一些附加的属性 (如callee属性)。
日期对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G18N5Baq-1603003678193)(A81241F4C9B64647B18C9BEDBF609AE1)]
- date:选取日、月、年
- month:选取月和年
- week:选取周和年
- time:选取时间(小时和分钟)
字符串操作方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8B074E6C-1603003678195)(9F4377BEA73541799BEC3D9A03B53C72)]
堆栈空间分配区别
1、栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;
简单数据类型存放到栈里面
2、堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。
复杂数据类型存放到堆里面
注意:JavaScript中没有堆栈的概念,通过堆栈的方式,可以让大家更容易理解代码的一些执行方式,便于将来学习其他语言。
根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部 函数 访问 就 称作 作用域 链
作用域链 :采取 就近原则 的方式 来 查找变量最终 的 值。
预解析
预解析: 在当前作用域下 , JS 代码执行之前,浏览器会默认把 带有 var 和 function 声明的变量在内存中进行提前声明或者定义。
代码执行: 从上到下 执行 JS 语句 。
预解析只会发生在通过var 定义的变量和 function 上 。 学习预解析能够让我们知道为什么在变量声明之前访问变量 的 值是 undefined 为什么在函数声明之前就可以调用函数 。
预解析也叫做变量、函数提升。
变量提升:变量的声明会被提升到 当前作用域 的最上面,变量的赋值不会提升。
函数提升: 函数 的声明会被提升到 当前作用域的 最上面,但是不会调用函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9kFqYGVl-1603003678196)(0FA8A5A5FBC643DBBA75868790B091A9)]
创建对象的三种方式
在JavaScript 中,现阶段我们可以采用 三种方式 创建对象 object
利用 字面量 创建对象
利用 new Object 创建对象
利用 构造函数 创建对象
变量、属性、函数、方法总结
变量:单独声明赋值 单独 存在
属性:对象 里面 的变量 称 为属性,不 需要 声明,用来 描述该对象的特征
函数:单独 存在 的, 通过“ 函数名 ()()”的方式 就可以 调用
方法:对象 里面 的函数 称 为方法, 方法 不 需要 声明, 使用“ 对象 方法 名 ()()”的方式就可以调用,方法 用来描述 该 对象的行为和功能 。