1)IE:IE浏览器支持冒泡事件
2)火狐:狐火浏览器支持冒泡事件和捕获事件
1)在IE浏览器中使用:event.cancleBubble=true;
2)在火狐浏览器中使用:event.stopPropagation();
/*构造函数中有个默认返回值,即return this---不写返回值时,默认返回该对象*/
function Func(){
}
var func=new Func()
1)首先是创建了一个空对象
var obj = new OBject()
2)设置原型链,即是使这个实例对象的原型proto指向构造函数Func的原型Func(这时便创建了obj对象的原型链:obj —>Func.prototype—>Object.prototype—>null
obj.__proto__=Func.prototype
3)改变this的指向,即是使构造函数Func中this的指向指向所创建的对象obj,并指向构造函数体
var result=Func.call(this)
4)判断构造函数的返回值,当返回值为值类型时,返回所创建的对象;如果时引用类型,就返回这个引用类型的对象
if(typeof(result)==='object'){
//如果返回值为引用类型,则返回该引用类型
func=result;
}else{
//如果值是值类型,则返回所创建的对象
func=obj;
}
总结:
---------js数据结构---->JSON-------->js数据结构--------
一个特点:基于文本的轻量级的数据交换格式
两个方法(JSON.stringify() JSON.parse() )
<head>
<script type="text/javascript">
var ul = document.getElementsByTagName('ul')[0]; //获取ul
var list = ul.getElementsByTagName('li');
for(var i =0;i<list.length;i++){
ul.appendChild(document.createElement('li'));
}
script>
head>
<body>
<ul>
<li>111li>
<li>222li>
<li>333li>
ul>
body>
html>
出错原因:这就是因为js加载执行于DOM结构之前,所以获取不到。简单的解决办法是把
js中延迟加载的流种方式
实现:
问题:
实现:
说明:
实现:
说明:
问题:
2)不同点
3)使用场景
实现:
//这些代码应被放置在标签前(接近HTML文件底部)
<script type="text/javascript">
//创建script标签引入js脚本
function downloadJSAtOnload(){
var element = document.createElement("script");
element.src = "defer.js";
document.body.appendChild(element);
}
//为文档的加载事件设置监听
if (window.addEventListener) //添加监听事件
window.addEventListener("load",downloadJSAtOnload,false); //事件在冒泡阶段执行
else if (window.attachEvent)
window.attachEvent("onload",downloadJSAtOnload);
else
window.onload =downloadJSAtOnload;
</script>
代码如下:
<script type="text/javascript">
function A(){
$.post("/lord/login",{name:username,pwd:password},function(){
alert("Hello World!");
})
}
$(function (){
setTimeout("A()",1000); //延迟1秒
})
</script>
getScript() 方法通过 HTTP GET 请求载入并执行 JavaScript 文件。
语法:jQuery.getScript(url,success(response,status))
url(必写):将要请求的 URL 字符串
success(response,status)(可选):规定请求成功后执行的回调函数。
其中的参数
response - 包含来自请求的结果数据
status - 包含请求的状态(“success”, “notmodified”, “error”, “timeout” 或 “parsererror”)
//加载并执行 test.js:
$.getScript("test.js");
//加载并执行 test.js ,成功后显示信息
$.getScript("test.js", function(){
alert("Script loaded and executed.");
});
延迟js加载的6中方式
详细解析看我写的写篇文章:深入了解XMLHttpRequest对象
是什么:
怎么创建:
1)首先是创建一个异步调用对象,即XMLHttpRequest()对象;
2)然后调用open()方法建立与服务器的连接,open()方法接收三个参数,第一个参数是method即请求的方法(get、post、put等),第二个参数是请求url,第三个参数接收一个布尔值,用来表示是否发送异步请求;此时嗲用open()方法并不是真正的向服务器发送了请求,而是一个准备阶段;
3)在发送请求前,我们可以为这个对象添加一些信息和监听函数,比如可以通过setRequestHeader方法来添加请求头信息等。一个XMLHttpRequest对象一共有五种状态,为这个对象状态的变化添加监听函数。由于向服务器发送了请求之后,响应状态时一直在改变的,且每一次改变,都会触发触发onreadstatechange事件,通常情况下对readySteta=4时进行判断,代表服务器返回的数据全部接收完成;同时判断服务器的响应状态码大于等于200或者小于300时代表返回值横穿,我们便可以对服务器返回的数据进行相应的处理。进而对页面进行更新;(以上也可以使用onload事件进行判断)
3)当对象的属性和监听函数设置完成之后,调用send()方法,向服务器发送请求。send()方法可以接收参数作为发送的数据体,该参数类型可以为json、blob等,当你不需要向服务器发送数据时,传入null值;
创建:
//一般实现
const xhr = new XMLHttpRequest();
xhr.open('get', '/server', true);
//设置响应类型
xhr.responseType = 'json'
//设置请求头信息
xhr.setRequestHeader('MyHeader', 'MyValue');
//设置请求失败监听函数
xhr.onload = function () {
console.log('请求失败了...')
}
//为XMLHttpRequest对象的状态设置监听事件(监听onreadystatechange)
xhr.onreadystatechange = function () {
if (this.readyState !== 4) {
return;
}
if (this.status >= 200 && this.status < 300) {
//响应正常
console.log(this.responseText)
} else {
console.log(this.statusText)
}
}
//发送请求
xhr.send(null);
说明:
解决思路:
1.禁掉缓存
2.更新请求URL(但不是改变URL),因为只要URL不变,那么浏览器就不会取检查服务器是否已经更新,那么浏览器用的数据仍是换粗中的数据
解决:
1)在ajax发送请求前加上
//本质是让缓存过期
anyAjaxObj.setRequestHeader("If-Modified-Since","0");
2)在ajax发送请求前加上
//本质是设置不允许产生缓存
anyAjaxObj.setRequestHeader("Cache-Control","no-cache");
3)在URL上加上一个随机数,
"fresh"=Math.random()
4)在URL上加上时间戳
"nowtime"=+new Date().getTime();
//如:request.jsp?q=q&date=(new Date()).getTime()
//运用实例:
//例如在用户登录验证的时候,点击验证码更新,只需要在发送验证码的请求上加上时间戳或者随机数的形式以更行URL,那么就可以请求得到新的数据
//又如短信发送的状态,如果隔几秒查询以此,URL不变的话,显示出来的状态则不会发生改变
5)如果是使用jQuery,直接适应$.ajacSetuo({cache:false})。这样页面的所有ajax就会执行这条语句就不需要保存缓存记录;
通俗的讲,同步是值客户端向服务端发送请求,在等待客户端响应请求时,客户端不能进行其他操作,直到服务器返回请求;
异步就是客户端向服务器发送请求,在等待服务端响应的时候,客户端不必等到服务端响应结束,可以进行其他操作;
详细解析可以参看我写的这篇文章:前端常见的跨域解决方法
详细解析可以查看我写的这篇文章:聊一聊cookie
对于CommonJS、AMD、CMD以及ES6 Module模块规范详细解析可以参考我写的这篇文章:JS中的几种模块化规范
在这里再总结一下:
概念
requireJS时基于AMD模块化加载规范,使用回调函数来解决模块化加载问题
原理
requireJS是使用script元素,通过script元的的src属性来引入模块
特点
实现js文件的异步加载
管理模块之间的依赖,便于代码的编程和维护
总:requireJS的核心原理是通过动态创建script脚本来异步引入模块,然后对每个脚本的load事件进行监听,如果每个脚本都加载完成了,再调用回调函数执行模块!
1.class的基本语法
创建类实例对象不同于构造方法,需要使用new关键字来创建
class Point{
constrctor(){}
}
let p=new Point();
2.class是ES6新增的语法,我的理解是为了补充js中缺少的一些面向对象语言的特性。通过class可以有利于我们更好的组织代码,但class还是具有原型继承的思想,比如class中属性和方法可以添加在原型上,为所有类的实例对象所共享;
再详细一点关于ES6中class的说明可以参考我写的这篇文章:
ES6中的class
1)类对象:拥有length属性和若干索引属性的对象都可以被称为类数组;
2)类数组对象和数组对象类似,只是类数组对象不能使用数组对象特有的方法(若想使用,需要将类数组对象转换为数组对象)
3)常见的数组是对象:arguments、DOM方法返回结果(NodeList、HTMLCollection)
function fun() {
console.log('arguments', arguments);
//Array.prototype.slice.call(类数组);
const arr1 = Array.prototype.slice.call(arguments)
console.log('arr1', arr1)
//[].slice.call(类数组);
const arr2 = [].slice.call(arguments)
console.log('arr2', arr2)
//Array.from
const arr3 = Array.from(arguments)
console.log('arr3', arr3)
//扩展运算符
const arr4 = [...arguments]
console.log('arr4', arr4)
}
fun(1, 2, 3, 4)
toString(),join()
,其中join可以接收特定字符串参数,将作为将数组转换为字符串时的分割符pop(),push()
unshift(),shift()
reverse(),sort()
,其中sort几首一个函数作为参数,该函数规定了排序的方式every(),forEach(),filter(),map()
indexOf(),indexLastOd()
concat()
,返回的是拼接好的数组,不影响原数组slice()
,用于截取数组的一部分返回,不影响原数组splice()
,影响原数组即当我们使用一个未声明的变量时,实质上意外的创建了一个全局变量,而这个变量会一直留在内存中无法被收回
function foo(arg) {
bar = "this is a hidden global variable";
}
真相是:
function foo(arg) {
window.bar = "this is an explicit global variable";
}
函数foo内部忘记使用var,意外创建了一个全局变量,而使这个变量一直保存在内存中;
function foo() {
this.variable = "potential accidental global";
}
// Foo 调用自己,this 指向了全局对象(window)
// 而不是 undefined
foo();
如何避免这种情况呢?
在javascript文件头部加上’use strict‘,可以避免此类错误的发生。使用严格模式解析javascript,避免意外的全局变量
即当我们设置了定时器如setInterval,而忘记取消它的时候,如果循环函数有对外局部变量的引用的话,那么这个变量会一直保存再保存着
即是当我们获取一个DOM元素的引用的时候,而后面这个DOM元素被删除,我由于我们一直保留着这个元素的引用,所以它也无法被回收
闭包的不合理使用,从而导致某些变量一直被留在内存中
if(typeof window !== 'undefined'){
console.log('browser');
}
if(typeof global !== 'undefined'){
console.log('node');
}
或者
this===window?console.log('browser'):console.log('node');
通过判断Global对象是否未window,使window则允许再浏览器种,如果为undefined,则当前脚本运行再node环境下
移动端的点击延迟时间是300ms,因为移动端有默认的双击缩放操作,浏览器通过判断用户第一个此点击与第二次点击的时间,来确认用户是否是需要进行双击缩放的操作。(即浏览器点击后要等待300ms,看用户有没有下一次点击,来判断是不是双击)
1)使用meta标签来禁用页面的缩放
ps:但是这种方式的缺点是牺牲了页面的缩放,我们不想要的只是双击双击缩放行为,我们还是希望能够通过双指来实现缩放的,
<meta name="viewport" content="user-scalable=no">
<meta name="viewport" content="initial-scale=1,maximum-scale=1">
2)调用FastClick库
FastClick库的相关介绍:FastClick是专门为解决移动端浏览器300毫秒点击延迟问题所开发的一个轻量级的库。FastClick的实现原理是在检测到touched事件的时候,会通过DOM自定义事件立即触发模拟一个click事件,并把浏览器在300ms之后的click事件阻止掉,实现如下:
//引入fastclick
<script src="js/fastclick.min.js"></script>
// 原生js初始化
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function() {
FastClick.attach(document.body);
}, false);
}
总:使用FastClick是最好的方案,不存在点击创投现象(对于点击穿透不熟悉的可以自行查一下资料)
可以参考这篇文章:https://blog.csdn.net/qq_42532128/article/details/106176195
1.前端路由:前端路由就是把路由对应的内容或者页面的任务交给前端来做,以前是通过服务器根据url的不同返回不同的页面实现的。
2.使用:在单页面应用中,大部分页面结构不变,只改变内容的使用。
3.一般有两种形式的前端路由,一是hash模式(#),二是pushState的方式
4.优缺点:
有两种方式:
1.通过检测window.navigator.userAgent的值,但是这种方式不是很可靠,因此这个值可以被改变(如早期的ei会伪装userAgent的值为Mozilla来躲过服务器的检测)
2.可以通过功能检测,根据每个浏览器独有的特性进行判断,如ie下独有的ActiveAObject
if(!Number.isNaN){
Number.isNaN=function(num){
//(假如浏览器没有Number.isNan方法,那么就给它添加上去)
return (num!=num)
}
}
<head>
<script type="text/javascript">
function fnGetExtension() {
//通过id获得文件输入元件
var fileInput = document.getElementById('myFile');
//获得文件名
var fileName = fileInput.files[0].name;
//获得文件扩展名
var fileExtension = fileName.split('.').pop();
alert(fileExtension);
}
script>
head>
<body>
<form action="/uploadFile" onsubmit="return false;">
<input id="myFile" type="file" name="file">
<button onclick="fnGetExtension()">获得扩展名button>
form>
body>
html>
###Vue部分
https://zhuanlan.zhihu.com/p/111310865
节流技术是用于设定在固定事件内,执行特定的功能代码,如果同一单位事件内某事件被多次触发,那么只有一次生效(节流可以用在scroll函数的事件监听上,通过事件节流来降低事件调用的频率)
1.防抖的实现
//防抖的实现
function debounce(fun, wait) {
let timer = null;
//所以下面的匿名函数适应的函数外部的变量,这里是闭包的作用
return function () {
//清空计时器是为了当事件又被触发时,重新计时
clearInterval(timer)
timer = setInterval(() => {
fun.apply(this)
}, wait)
}
}
var result = debounce(fun1, 1000)
result()
2.节流的实现
function limtfun(fun, wait) {
var perTime = 0;
return function () {
var nowTime = new Date()
if (nowTime - perTime > wait) {
fun.call(this)
perTime = nowTime//由于闭包的原因,这里的nowTime不会被清空
}
}
}
JS在执行的过程中会产生一个执行环境,js的代码在这个执行环境中按顺序执行,当遇到异步代码时,会被挂起到事件队列中(Task),对于这个队列中的任务则会涉及到微任务和宏任务,当执行栈的为空时,由于事件循环机制,就会从事件队列中拿出需要执行的代码到执行栈中执行,此时执行的循序时先执行微任务,当微任务执行完毕之后,再执行宏任务。
1)语法
var obj=new Object()
obj instanceof Object //true
2)底层原理
function myInstanceof(left, right) {
left = left.__proto__;
right = right.prototype;
while (true) {
if (left === null || left === undefined) {
return false
}
if (left === right) {
return true
}
//即上面均不满足时,继续往原型链上查找
left = left.__proto__;
}
}
参考文章:https://zhuanlan.zhihu.com/p/105487552
function jsonp(url, data, callback) {
//产出随机的回调函数名(因为可能有多个请求,这里可以区别开来)
var funcName = 'jsonp_' + Date.now() + Math.random().toString().substr(2, 5);
//如果存在其他传入参数,需要进行拼接
if (typeof data === 'object') {
var tempArr = [];
for (var key in data) {
var value = data[key];
tempArr.push(key + '=' + value)
}
//将数组以&拼接成字符串,如name=h$age=21
data = tempArr.join('&')
}
var script = document.createElement('script')
script.src = url + '?' + data + 'callback=' + funcName
document.body.appendChild(script);
//这里得到请求的数据,在回调函数中执行处理
window[funcName] = function (data) {
callback(data)
}
}
//使用
jsonp('http:127.0.0.1:3000/api', {}, function (res) {
console.log(res)
})
参考文章:
https://blog.csdn.net/weixin_40483654/article/details/106434990
实现存储功能:Cookie、localStorage、sessionStorage、indexDB
特性 | Cookie | localStroage | sessionStorage | indexDB |
---|---|---|---|---|
数据生命周期 | 一般由服务器生成,可以设置过期事件 | 除非被清理,否则一直存在 | 页面关闭时就被清理 | 除非被清理,否则一直存在 |
数据存储大小 | 4kb | 5mb | 5mb | 无限 |
与服务端的通信 | 会一直携带在请求头 | 不参与下 | 不参与 | 不参与 |
PS:没有大量的数据需求的话,可以使用localStorage和sessionStorage,对于不怎么改变的数据,尽量使用localStorage。
接下来我们将通过以下几个方面来探讨浏览器的缓存机制
我知道的浏览器的缓存位置有Service Worker、网络请求,并且有各自的优先级,当一次查找缓存并且都没有命中的时候,才会请求网络。
通常浏览器的缓存策略可以分为两种:强缓存和协商缓存。并且这两种缓存策略都是通过设置 HTTP Header 来实现的
1)强缓存(有两种设置方式)
Expires:缓存受限于本地的时间
Cache-Control:通过max-age来设置缓存的时间期限
2)协商缓存(两种设置方式)
简单的说,如果缓存过了,就需要发起请求验证资源是否更新。即当浏览器发送请求验证时,如果资源没有发生改变,那么服务器就返回304状态码,并更新浏览器的缓存有效期。(相当于浏览器和服务器进行协商,是否返回新的数据)
Last-Modified
Last-Modified表示本地文件最后修改日期,当 Last-Modified的值发送给服务器,循环服务器在该日期后资源是否有变更,有则返回新的资源,否则返回304状态码
ETag
当ETag的值发送给服务器,询问该资源是否有更新,有则返回新的资源(并且ETag的资源比Last-Modified高)
一般来说,现在都会使用工具来打包代码,那么我们可以对文件名进行哈希处理,只有当代码修改之后生产新的文件名。基于此,我们就可以给代码设置缓存有效期一年Cache-Control:max-age=3153600,这样只有html文件中引入的文件名发生了改变,才回去下载新的代码,否则就一直使用缓存。
虚拟滚动:原理时只渲染可视区域内的内容,非可视区的则不渲染,当用户在滚动的时候就实时去替换渲染的内容。
我们知道,在浏览器的渲染线程和JS引擎线程时互斥的,因此在渲染时,若遇到script标签时,则此时会渲染会停止下来,等待script代码加载完毕,再从暂停的地方重新渲染。也就是说,当你想首屏渲染越快,那么就不应该再首屏加载js文件,也就是建议将script标签放在body标签底部的原因。当然,你也可以给script标签添加defer或者async属性,那么此时的script可以放在任意位置,因为此时js文件会并行下载,若时defer,会等待页面渲染结束才执行,而async会在加载完毕之后立即执行。
只是defer和async表示js文件的加载和解析不会阻塞渲染。‘
1.使用transform替换top
2.使用visibility替换display:none,因为前者只会引发重绘,而后者会引发回流
3.少用table布局,因为table布局很小的一个改动会引发整个table的重新布局
4.将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点。(比如video标签,浏览器会自动将该节点变为图层)
XSS(Cross-Site Scripting)—跨站脚本攻击,简称XSS,是一种代码注入攻击,攻击者通过在目标网址注入恶意脚本,使之在用户的的浏览器上运行。利用这些恶意脚本,攻击者获取用户敏感信息如Cookie、SessionID等,进而危害数据安全
XSS的本质:恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行
由于问题的源头是js代码的注入,那么我们便想办法不让js生效
方式1:使用转义字符
即需要注意两头的防范:
1)输入
在提交表单时,前端最好将文本内容转成html实体编码,也就是过滤掉