一、js中的this指向
1.在全局使用this
console.log(this);
2.函数中的this
function show(){
console.log(this); //window,谁调用,this是谁
}
show();
3.事件绑定中的this
var box = document.querySelector(".box")
box.onclick = function(){
console.log(this); //box, 谁绑定事件,this就是谁
}
4. 事件绑定中,调用其它函数的this
var box = document.querySelector(".box")
function show(){
console.log(this); //window,谁调用,this是谁
}
box.onclick = function () {
console.log(this); //box
show();
}
5.定时器中的this: 无论定时器在哪出现,其内部的this都指window
setInterval(function(){
console.log(this) //window
},3000)
6. 构造函数和原型中的this
this指向new出来的新的实例化对象
二、js中的事件委托
(一)、什么是事件委托:
(1)把目标元素的事件委托给父元素
(2) 利用了事件冒泡的原理
(二)、好处:
1.管理的函数变少了。不需要为每个元素都添加监听函数。对于同一个父节点下面类似的子元素,可以通过委托给父元素的监听函数来处理事件。
2.可以方便地动态添加和修改元素,不需要因为元素的改动而修改事件绑定。(比如后来添加子元素依然拥有事件)
3.JavaScript和DOM节点之间的关联变少了,这样也就减少了因循环引用而带来的内存泄漏发生的概率。
(三)、事件委托的应用场景
1、比如商品的添加购物车按钮上面的逻辑: 用事件委托去解决
(四)、事件委托的解决方案
ulObj.onclick = function(e){
var e = e || event;
var target = e.target || e.srcElement //目标对象的dom
if (target.tagName == "LI"){
console.log(target.innerHTML);
}
}
三、js中的数据类型
两大类:
一、原始数据类型(基本数据类型)
null undefined String Number Boolean
二、引用数据类型
数组和对象
四、如何判断一个变量数数组
var arr = [1,2,3]
console.log(typeof arr ) //object
console.log(arr instanceof Array) //true,说明arr是Array对象的实例化对象
五、js中的时间冒泡
一、什么是事件冒泡:
1、事件捕获:当某个元素触发某个事件(如onclick),顶层对象document就会发出一个事件流,随着DOM树的节点向目标元素节点流去,直到到达事件真正发生的目标元素。在这个过程中,事件相应的监听函数是不会被触发的。
2、事件目标:当到达目标元素之后,执行目标元素事件相应的处理函数。如果没有绑定监听函数,那就不执行。
3、事件起泡:从目标元素开始,往顶层元素传播。途中如果有节点绑定了相应的事件处理函数,这些函数都会被依次触发。如果想阻止事件起泡,可以使用e.stopPropagation()(Firefox)或者e.cancelBubble=true(IE)来阻止事件的冒泡传播。
二、事件冒泡的应用场景
1、 简单场景 : body中有div, div中有img , img上触发了单击事件,则如果img上绑定的有该事件,则触发img的onclick事件处理程序。然后,事件会向上冒泡,冒泡到div上,如果div也绑定的有click事件,则div的事件处理程序也执行。事件会继续向上冒泡,直到document
2、慕课首页的登录效果,就用到了事件冒泡
三、事件冒泡的解决方案
e.stopPropagation || e.cancelBubble= true
六、js数组常用方法
1. 重要: arr.splice(1,3) 将索引为1开始的3个元素删除
arr.splice(1,0,"100")
arr.splice(1,2,"100")
2. 重要:arr.push()
3. 重要: arr.pop()
4. arr.indexOf("3")
5. arr.join("")
6. arr.slice(2,4) : 返回从索引2,到索引4的元素组成的新数组 (不包括索引4)
7. arr.reverse()
七、js中的六种假值
false 0 "" undefined null NaN
八、js中get和post的区别
一、传输方式不同:
get: 数据是附加在url地址后
post: 数据是放在请求体里
二、安全性不同:
get: 不安全
post: 安全
三、大小限制不同
get: 有字节数限制
post: 可以传输大数据
九、前后端如何实现分离
在开展项目之前 ,前端(front-end) 和后端(back-end)要提前约定一下:
1. 接口的地址, 提交的方式
2. 查询的参数 (前端传给后端的)
3.返回的数据类型 (后端传给前端的)
接下来,就可以各自开展工作,中间不用相互沟通,
大家各自的工作完成后,代码放在一起进行项目联调。 打包上线。
十、js中的Ajax工作原理
1、创建 XMLHttpRequest 对象的语法:
var xmr;
if (window.XMLHttpRequest){
// IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
xmr=new XMLHttpRequest();
}else{
// IE6, IE5 浏览器执行代码
xmr=new ActiveXObject("Microsoft.XMLHTTP");
}
2、向服务器发送请求请求
xmr.open("GET","ajax_info.txt",true);
xmr.send();
3、监听服务器的响应
xmr.onreadystatechange=function(){
if (xmr.readyState==4 && xmr.status==200) {
document.getElementById("myDiv").innerHTML=xmr.responseText;
}
}
4、读取内容
十一、jsonp的工作原理
JSONP的最基本的原理是:
是为了解决ajax不能跨域的问题。
动态添加一个<script>标签,而script标签的src属性是没有跨域的限制的。
Jsonp的执行过程如下://以JSONP接口http://www.b.com/search.html?jsonp=jsonpCallback为例
1、首先在客户端注册一个callback(回调函数), 然后把callback的名字传给服务器。
2、服务器先生成json数据,然后以JavaScript语法的方式,生成一个function,function的名字就是传递上来的参数jsonp的值,function的参数为服务器生成好的json数据,然后把用该语法写好的内容返回给客户端。(语法:callback(json数据))
3、客户端浏览器,解析script标签,并执行返回的javascript文档,此时数据作为参数,传入到了客户端预先定义好的callback函数里.(动态执行回调函数)
十二、js中call和apply的区别
相同点:
call()和apply()都是函数对象的方法,都是用来改变this指向的
不同点:
传参的方式不同,call()是以枚举的方式传参,而apply必须是数组的方式传参
十三、js-闭包
一、什么是闭包
1、函数里面包含的子函数,子函数访问父函数的局部变量
2、通过return将子函数暴露在全局作用域,子函数就形成闭包
3、通过闭包,父函数的局部变量没有被销毁,可通过闭包去调用 ,但同时,这个局部变量也不会被全局变量污染
二、简单的闭包
function aaa() {
var a = 0;
return function () {
alert(a++);
};
}
var fun = aaa();
fun(); //1
三、闭包的优点和缺点:
优点: 避免全局变量的污染,同时,局部变量没有被销毁,驻留在内存中,还可以被访问
缺点: 使用不当,会造成内存泄露
十四、构造函数中new一个新的对象经历的四个阶段
1. 创建一个空的实例化对象
2. 让构造函数中的this指向该实例化对象
3. 执行构造函数,构建实例的属性和方法
4. 返回(return)新的实例化对象
十五、原型链的概念
一、原型
每一个构造函数都会生成一个特殊的实例化对象,构造函数的prototype属性指向该对象,这个对象就是原 型对象(prototype对象)
二、__proto__属性
由构造函数new出来的每一个实例化对象,都有一个__proto__属性,该属性指向构造函数的原型对象,原型对象也有自己的__proto__属性,指向它上一级构造函数的原型对象。
三、总结原型链
当实例调用某个属性或方法时,会先在自身查找该属性或方法,如果找到,就执行。如果没有找到,就会沿着__proto__到它的原型对象上去查找,如果没找到,会沿着原型对象的__proto__到上一级原型去查找,一直找到Object的原型,Object原型的__proto__指向null. 这样由一系列_proto_串起来的原型对象就构成了原型链。只要在原型链的任意位置找到了相应的属性和方法,就可以调用 。
十六、jquery封装插件的方法
$.extend()------->$.方法()
$.fn.方法() -----> $().方法()
十七、CSS3过渡与动画的区别
(一)、transition过渡
1、只能实现一个状态到另一个状态的过渡。(强调两种状态之间的过渡,不能有更多状态的过渡)
2、如果纯css来完成动画,则动画只能用hover来触发
3、transition不能实现自动播放
(二)、animation动画
1、可以实现多种状态之间的改变
2、单纯用css,可以实现自动播放,也可以用hover来触发
3、它必须和@keyframes(关键帧)结合使用-- (keyframes定义动画规则,而animation应用动画)
4、animation有非常多的属性来实现更为丰富的动画效果 (循环次数,交替,动画前后的状态)
十八、如何让低版本浏览器兼容HTML5新标签
<!--[if lt IE 9]>
<script src="js/html5shiv.min.js"></script>
<![endif]-->
html5shiv.js 通过JavaScript 来创建HTML5元素(如 main, header, footer等)。
通过引用htmlshiv即可使低版本的IE支持HTML5标签
十九、HTML5中新增的结构标签
main header footer nav article
aside section figure figcaption hgroup
二十、三种客户端存储方式的区别
sessionStorage、localStorage 、cookie的区别
共同点:都是保存在浏览器端,且同源的。区别:
1. 与服务器的数据交换方式不同。
cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。
2. 存储大小限制也不同,
cookie数据不能超过4k,同时因为每次http请求都会携带cookie,所以cookie只适合保存很小的数据,如会话标识。sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
3. 数据有效期不同,
sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。
4. Cookie可以设置有效期,路径(path),域(domain)
二十一、移动端相对长度单位
em % rem vw vh vmin vmax
二十二、防抖和节流
一、场景:
以下场景往往由于事件频繁被触发,而重复执行DOM操作、资源加载等行为、会导致UI停顿甚至浏览器崩溃。
1、window对象的resize、scroll和拖拽时的mousemove事件
2、射击游戏中的mousedown、keydown事件
3、类似百度搜索提示keyup事件
二、debounce(防抖)的特点是当事件快速连续不断触发时,动作只会执行一次。
三、节流(throttle)函数不管事件触发有多频繁,每隔一个时间周期就会执行一次事件处理程序。
二十三、js-this-原型-闭包-面试题
1程序代码如下:
function test(){
for(var i = 5; i < 100 ; i=i+2){
}
console.log(i);
}
test();
该程序的执行结果是多少?并解析下为什么
2.程序代码如下:
var person = function(){
var name = "default";
return {
getName : function(){
return name;
},
setName : function(newName){
name = newName;
}
}
}();
console.log(person.name);
console.log(person.getName());
person.setName("abruzzi");
console.log(person.getName());
该程序的执行结果是多少?
3. var x = 1234;
function test(){
var x = 4567;
console.log(this.x);
}
test();
var testObj = new test();
var o = {};
o.x = 5678;
o.m = test;
o.m();
该程序的执行结果是多少?并解析下为什么
二十四、移动端常见的问题及解决方案
1、 移动端 300ms 延迟的问题 : fastclick.js
2、 zepto的tap事件: 点透问题
二十五、前端性能优化
网络方面
1减少http请求:在YUI35规则中也有提到,主要是优化js、css和图片资源三个方面,因为html是没有办法避免的。因此,我们可以做一下的几项操作:
合并js文件
合并css文件
雪碧图的使用(css sprite)
使用base64表示简单的图片
前面两者我们可以使用webpack之类的打包工具进行打包;雪碧图的话,也有专门的制作工具;图片的编码是使用base64的,所以,对于一些简单的图片,例如空白图等,可以使用base64直接写入html中
2减小资源体积:可以通过以下几个方面进行实施:
gzip压缩
js混淆
css压缩
图片压缩
3缓存:可以通过以下几个方面来描述:
DNS缓存
CDN部署与缓存
http缓存
4移动端优化:使用以下几种方式来加快移动端网络方面的优化:
使用长cache,减少重定向
首屏优化,保证首屏加载数据小于14kb
不滥用web字体
渲染和DOM操作方面
1优化网页渲染:
css的文件放在头部,js文件放在尾部或者异步
尽量避免內联样式
2.DOM操作优化:
避免在document上直接进行频繁的DOM操作
使用classname代替大量的内联样式修改
对于复杂的UI元素,设置position为absolute或fixed
尽量使用css动画
使用requestAnimationFrame代替setInterval操作
适当使用canvas
尽量减少css表达式的使用
使用事件代理
前面三个操作,其实都是希望『减少回流和重绘』。requestAnimationFrame代替setInterval操作」,相信大家都有所耳闻,setInterval定时器会有一定的延时,对于变动性高的动画来说,会出现卡顿现象。而requestAnimationFrame正好解决的整个问题。
3.操作细节注意:
避免图片或者frame使用空src
在css属性为0时,去掉单位
禁止图像缩放
正确的css前缀的使用
移除空的css规则
对于css中可继承的属性,如font-size,尽量使用继承,少一点设置
缩短css选择器,多使用伪元素等帮助定位
4.移动端优化:
长列表滚动优化
函数防抖和函数节流
使用touchstart、touchend代替click
HTML的viewport设置
开启GPU渲染加速
数据方面
1.图片加载处理:
图片预加载
图片懒加载
首屏加载时进度条的显示
「首屏进度条的显示」:往往对于首屏优化后的数据量并不满意的话,同时也不能进一步缩短首屏包的长度了,就可以使用进度条的方式,来提醒用户进行等待。
2.异步请求的优化:
使用正常的json数据格式进行交互
部分常用数据的缓存
数据埋点和统计
二十六、wIndow对象的子对象
1. document
2. history
3. location
4. navigator
5. screen
二十七、js-从输入url到页面展现经过了什么过程
1、DNS 解析: 将域名解析成 IP 地址
在浏览器输入网址后,首先要经过域名解析,因为浏览器并不能直接通过域名找到对应的服务器,而是要通过IP 地址。
2. TCP 连接:TCP 三次握手
在客户端发送数据之前会发起TCP 三次握手用以同步客户端和服务端的序列号和确认号,并交换 TCP 窗口大小信息。
第一次握手,由浏览器发起,告诉服务器我要发送请求了
第二次握手,由服务器发起,告诉浏览器我准备接受了,你赶紧发送吧
第三次握手,由浏览器发送,告诉服务器,我马上就发了,准备接受吧
3.发送 HTTP 请求
TCP 三次握手结束后,开始发送 HTTP 请求报文。
4. 服务器处理请求并返回 HTTP 报文
(1) 如果是静态资源,直接找到资源并返回
(2)如果是动态请求,首先解析动态文件,然后返回静态的html代码
5. 浏览器解析渲染页面
浏览器拿到响应文本HTML 后,解析渲染页面
浏览器解析渲染页面分为一下五个步骤:
根据HTML 解析出 DOM 树
根据CSS 解析生成 CSS 规则树
结合DOM 树和 CSS 规则树,生成渲染树
根据渲染树计算每一个节点的信息
根据计算好的信息绘制页面
断开连接:TCP 四次挥手
二十八、webSocket
1、 WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
2、 HTTP 协议无法实现服务器主动向客户端发起消息,WebSocket 连接允许客户端和服务器之间进行全双工通信,以便任一方都可以通过建立的连接将数据推送到另一端。WebSocket 只需要建立一次连接,就可以一直保持连接状态。
3. 适用场景: 网店客服实时通信
4. Web浏览器和服务器都必须实现 WebSocket 协议来建立和维护连接
二十九、js对象的深拷贝和浅拷贝
浅拷贝:只拷贝对象的基础属性值,对属性值为对象或数组的属性则拷贝指针。
深拷贝:拷贝对象的所有属性作为一个全新的对象。拷贝前后的对象互不影响。
浅拷贝仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么深拷贝出来的对象也会相应改变。
一、对象引用
对象引用容易理解,直接赋值,修改复制后的数组,原对象会随之改变。
//对象引用
var boy = {
age:18
}
var girl = boy;
console.log(boy === girl);//true
girl.age = 20;
console.log(boy.age);//20
理解:使用“=”进行赋值,girl和boy指向了同一内容地址,修改一个,另一个也会修改。
二、浅拷贝
使用Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
//浅拷贝
var boy = {
age:18
}
var girl = Object.assign({}, boy);
console.log(boy === girl);//false
girl.age = 20;
console.log(boy.age);//18
理解:上述代码将原始对象拷贝到一个空对象,就得到原始对象的克隆,原对象和拷贝对象指向不同的内存地址,修改原对象和克隆对象,互补影响。
var boy = {
age:18,
address:{
home:'北京'
}
}
var girl = Object.assign({}, boy);
console.log(boy === girl);//false
girl.address.home = '上海';
console.log(boy.address.home);//上海
理解:上述代码将原始对象拷贝到一个空对象,就得到原始对象的克隆。因为Object.assign()只是浅拷贝girl.address是对栈对象的引用,因此内层对象的修改会影响原始对象。
三、深拷贝
1、JSON.parse()与JSON.stringify()深拷贝
可以通过JSON对象的方法,来进行对象的深拷贝,代码如下:
//纯数据json对象的深度克隆
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
理解:通过对象符串化和字符串对象化进行对象的拷贝。此方法只使用与纯JSON对象的深拷贝
2、对象遍历
//包含其他负责的内容 date对象 null undefined
var obj1={
name:"张三",
age:20,
height:[12,26,46],
address:{
home:'北京'
},
birthday:new Date(),
father:null,
mother:undefined,
school:[
{
middleschool:'北大附中',
},
{
university:'清华大学',
}
]
}
function clone(obj) {
if(obj === null) return null
if(typeof obj !== 'object') return obj;
if(obj.constructor === Date) return new Date(obj);
if(obj.constructor === RegExp) return new RegExp(obj);
var newObj = new obj.constructor (); //保持继承链
for (var key in obj) {
if (obj.hasOwnProperty(key)) { //不遍历其原型链上的属性
var val = obj[key];
newObj[key] = typeof val === 'object' ? arguments.callee(val) : val; // 使用arguments.callee解除与函数名的耦合
}
}
return newObj;
};
console.log(obj1);
console.log(clone(obj1));
理解:
(1)、用 new obj.constructor ()构造函数新建一个空的对象,可以保持原形链的继承;
(2)、用obj.hasOwnProperty(key)来判断属性是否来自原型链上,因为for..in..也会遍历其原型链上的可枚举属性。
(3)、函数用到递归算法,在函数有名字,而且名字以后也不会变的情况下,这样定义没有问题。但问题是这个函数的执行与函数名 factorial 紧紧耦合在了一起。为了消除这种紧密耦合的现象,需要使用 arguments.callee。
原文:https://blog.csdn.net/xuexizhe88/article/details/80989813