2017-1-17
(面试题:http://www.qdfuns.com/notes/35376/2fada0407dae579a95d1622436f5e0ab.html)
(前端面试,大漠:http://www.w3cplus.com/css/write-to-front-end-developer-interview.html)
(html5:http://blog.csdn.net/baihuaxiu123/article/details/51585718)
(干货:http://tools.jb51.net/table/javascript_event)
js篇:
*作用域、作用域链
每当去执行函数的时候,函数就会创建一个自己的执行环境,这个执行环境就是一个作用域;当函数被定义的时候,函数就创建了一个内部属性[scop],
[scop]里面包含的就是一个作用域链,这个作用域链就是一个指向变量对象的指针列表;函数被创建的时候作用域链中只包含全
局变量对象,函数被执行时,当前的活动对象就被添加到作用域链的最前端。作用域链决定了哪些变量可以被访问到。
当访问一个函数中的标识符时,首先会从作用域链的前端开始查找,如果作用域链的前端不存在该标识符,就会沿着作用域链向上一个包含环境查找,直到
查找到全局变量环境。
*闭包,闭包的作用,为什么闭包不会被回收变量和函数
闭包: 能够访问另一个函数中的变量的函数;
闭包的作用:
在函数外部访问函数内部中的变量
将函数内部中的变量保存在内存中
闭包的应用场景:
模仿块级作用域,避免变量污染全局执行环境
创建私有变量和函数,向外提供公共接口来访问私有变量和函数
垃圾回收机制:
垃圾回收机制的方式有两种: 标记清除和引用计数。
常用的是标记清除,垃圾收集器在运行时,首先会将内存中的所有变量都加上标记,然后会给环境中的变量以及被环境中的变量引用的变量去掉标记;最后标记了的变量
都是不再需要了的变量,垃圾收集器最后会将这些标记了的变量的内存回收。
不常用的是引用计数,引用计数即跟踪记录每个值被引用的次数,只有变量的引用次数为0时,变量才会被垃圾收集器回收;在ie9之前的ie中,BOM与DOM对象都是以
COM对象的形式实现的,COM垃圾回收机制是基于引用计数策略。引用计数策略容易导致循环引用的问题,变量无法被垃圾收集器回收,从而引起内存泄露的问题。
将被引用的变量设置为null,解除引用。将变量设置为null的目的是让变量与变量之前引用的值断开连接,垃圾回收器再下次运行时可以回收变量的占用的内存。
为什么闭包不会被回收变量和函数:
如果闭包在全局环境中一直被引用着,闭包的函数和变量就不会被回收。局部环境中的变量在离开执行环境之后会自动被解除引用,而全局变量在不需要的时候
需要手动解除引用。
注释部分,没有保存外部环境变量中的this,访问的是全局环境中的name,函数被调用时,函数活动对象中包含了this,arguments、命名参数、局部变量;
所以在查找this的时候只会查找到活动对象为止,this指向的是函数的直接调用者,匿名函数被调用是在全局环境中,所以this===window。
var name = "The window"; var object = { name : "my object", getNameFunc : function() { var that = this; return function() { // return this.name;//The window return that.name;//my object }; } // getNameFunc : function() { // return this.name;//my object // } }; //console.log(object.getNameFunc()); console.log(object.getNameFunc()());
var message = "ok"; var hander = { message: "event hander", handleClick: function() { // return function () { console.log(this.message); // }; } }; // hander.handleClick()(); var btn = document.getElementById("btn"); btn.addEventListener('click', hander.handleClick);//undefied btn.addEventListener('click', function() { hander.handleClick();//event hander });
this指向函数的直接调用者
* 内存泄露,什么时候会发生内存泄露,如何防止内存泄露。
* 函数声明和函数表达式
非严格模式下,函数声明方式定义的函数可以在函数定义前调用,函数表达式定义的函数不可以在函数定义前调用。
函数声明后面不能直接跟圆括号,函数表达式可以。
匿名函数后面不能直接跟圆括号,JavaScript会将function关键字当作函数声明的开始。可以将函数声明转化成函数表达式。外面加括号。
* 函数声明提升和变量声明提升的区别
函数声明提升和变量声明提升都是在代码执行之前优先被处理,如果函数名和变量名是同一标识符,函数声明会覆盖变量声明,不管
两者的顺序如何,但是函数声明不会覆盖变量赋值。
var a; var c = 1; a = 1; function a() { return true; } console.log(a); //1 //undefined var a; var c = 1; console.log(a); a = 1; function a() { return true; } //function a() { return true; } //1
*什么是面向对象编程
面向对象编程首先实现的是一个类,这个类里面包含的是这一类对象所共有的属性和方法;
面向对象具有封装、继承、多态的特点;
面向对象编程的好处是:将某一类对象所具有的特性封装起来,再需要这个类的某个特性的时候,直接去调用对应的接口,不需要再关心功能实现的具体细节。
封装之后的程序,可以复用,节省了开发成本,提高开发效率。
*创建对象的几种方式
字面量
工厂模式: new 一个object类型对象,然后给对象添加属性和方法(解决了创建多个相似对象创建问题,但没解决对象识别的问题)
构造函数模式: 创建有参的构造函数,通过this来指定上下文(公共方法无法复用)
原型模式: 创建一个构造函数,然后在函数的原型上定义属性和方法(包含的引用对象,例如数组,那么一个实例对这个数组做了改变,其他实例上也能反应出来)
构造函数模式和原型模式的组合模式(将每个实例都需要拥有一份的变量定义在构造函数中,将公共变量或方法定义在原型对象上)
* 原型、原型链
* 继承,如何实现继承
子类原型指向父类实例
子类构造函数中通过apply方法来继承父类构造函数
* 如何判断一个对象是否属于某一个类
instanceOf用来检测引用类型
isPrototypeOf用于判断某个对象是否包含指向某个类型对象的指针,从而来判断对象类型。
* 如何判断一个属性是在实例对象上还是在实例原型上
用hasOwnProperty()判断某个实例对象是否包含某个属性
* 函数的几种调用方式
通过函数名直接调用,this指向window
函数作为对象中的一个方法来调用,this指向函数的直接调用者
new关键字来调用构造函数,this指向new出来的对象,指向当前构造函数的原型
通过apply/call来调用函数,第一个参数为null时,this指向window;为对象时,this指向这个对象
* apply/call的区别
都是用来在特定作用域中调用函数。
第一个参数都为对象(运行函数的作用域),主要区别是其他的参数的传递形式不一样;
apply接受两个参数,第二个参数可以是Array实例,也可以是arguments对象
call方法传递给函数的参数必须逐个传递
使用场景(传递参数、扩充函数运行的作用域):
在子类构造函数中通过call/apply调用父类构造函数,实现继承
arr.push.apply(arr, arguments);将一个包含参数的伪数组直接添加到一个数组里面
* bind()
返回一个在指定作用域中运行的函数的函数
实现原理:就是通过apply来指定函数运行的作用域
使用场景: 事件处理(this指向当前点击对象)、setTimeout/setInterval(this指向window)
*this对象的理解
this指向new关键字创建的对象;(调用构造函数,如果没有加new关键字,就会创建全局变量)
this指向函数的直接调用者;
this指向当前点击的事件对象,但是在ie中采用attachEvent处理的事件处理程序,this指向的是window。(这也是ie事件处理程序与dom0事件处理程序的区别)
* new关键字都做了什么
创建一个新对象、this对象指向这个新对象、为新对象添加属性和方法、返回新对象。
=============================================================================================
* 事件、事件流、ie与火狐事件处理的区别
事件流,即从页面中接收事件的顺序
ie事件流中没有事件捕获阶段,只有事件冒泡;火狐中有事件处理分三个阶段:捕获阶段、处理目标、事件冒泡
标准浏览器(包括火狐)在添加事件、删除事件、阻止默认行为、阻止事件冒泡、获取事件对象、获取目标对象上与旧版本ie都有区别
标准浏览器通过addEventListener添加事件处理程序、removeEventListener删除事件处理程序;
ie浏览器对应的是attachEvent、detachEvent;
标准浏览器获取目标对象是通过target属性,ie是通过srcElement
ie的事件处理程序的事件对象指向的是window,而不是当前的点击对象
标准浏览器阻止默认行为是通过preventDefult(),而ie是通过将属性returnValue设置为false
阻止冒泡是通过stopPropagation(),ie是通过将cancelBubble设置为true
* JavaScript的事件模型
原始事件模型:即通过on+事件名的形式来处理的事件
捕获事件模型: 即指事件从Document传递直到目标对象(事件发生地)
冒泡事件模型: 与捕获相反,事件是从目标对象到Document
* 编写一个通用的事件机制
* js事件总结
1、事件分为dom0级事件和dom2级事件:
dom0级事件即通过on加事件名称的方式来添加事件处理程序,所有的浏览器都兼容
dom2级事件即通过addEventListener方式来添加事件处理程序,高版本浏览器才兼容
兼容Dom的浏览器都会将event对象传入到事件处理程序中
(addEventListener第三个参数为true,事件在捕获阶段调用事件处理程序;为false,事件在冒泡阶段调用事件处理程序)
2、事件流又分为事件冒泡和事件捕获:
所有的浏览器都具有事件冒泡
只有高版本浏览器才具有事件捕获,ie8及ie8之前的浏览器都只有事件冒泡,没有事件捕获
3、ie与火狐浏览器处理事件的区别:见上面
添加、删除事件处理方式不一样
获取事件对象、目标元素不一样
阻止冒泡、阻止默认行为不一样
4、onclick方法可以兼容任何浏览器,添加addEventListener、attachEvent的好处是可以为同一个元素绑定多个事件处理程序
onclick在给一个元素绑定多个事件处理程序时,以最后一个事件处理程序为准
addEventListener在为同一个元素绑定多个事件处理程序时,事件的执行顺序,是代码的书写顺序
attachEvent在高版本ie浏览器中同addEventListener处理多个事件处理程序一样,在ie8及之前的浏览器中执行顺序正好相反
5、为什么要有事件捕获?事件冒泡?
获取的事件可能在目标对象之前,或是之后。
*==与===的区别
==是等同,===是完全相等
===,在比较两个基本类型的值时,值的类型相等、值相等即相等
==,在比较两个不同类型的值时,这两个值仍然有可能相等;在比较两个不同类型的值时,有一个隐式转化的过程,
字符串和数字进行比较,会先将字符串转化数字然后再比较;true会转化为1再与数值比较,false转化成0再与数值比较;
==比较null和undefined返回true,===比较null和undefined返回false。
NAN永远不会和其他任何值相等包括它自身。
* 类型转化
* 如何检测JavaScript数据类型
typeof一般用来检测基本数据类型,但是null一般用===/!==来判断;
instanceOf一般用来检测引用类型,但是检测function的最好的方式是用typeOf,可以跨帧检测;
检测数组用Array.isArray或Object.protypeof.toString.call(),两者都可以跨帧使用,但是前者
存在兼容性的问题,ie9之前的浏览器不兼容。
* 通过点属性名的形式添加的自定义属性,除了ie浏览器,其他浏览器都不能通过 getAttribute()方法来获取自定义的属性的值
* setInterval与setTimeOut的区别,以及它们的原理
* 程序、线程与进程(http://www.qdfuns.com/notes/17659/7cb0a395fea126caceeb64909b594b0f.html)
http://www.cnblogs.com/way_testlife/archive/2011/04/16/2018312.html
javascript为什么是单线程:http://www.cnblogs.com/zhongxinWang/p/4334510.html
* 严格模式
超时调用的方法运行在全局环境中,非严格模式下,this等于window,严格模式下this等于undefined
(关于网络:http://www.cnblogs.com/haoyijing/p/5898420.html#html8)
==================================================================================================
* ajax的执行过程
创建一个异步请求对象;初始化请求,指定请求的方式、url、是否为异步请求; 然后创建一个响应请求变化的函数;如果是post请求,要设置头信息(设置发送的内容类型);
最后发送请求。获取异步请求返回的数据,最后通过JavaScript和DOM实现局部刷新。
* get请求与post请求的区别
两者都是数据请求的方式;
get的数据是通过网址后面加?加参数的形式来传递数据,而post的数据是通过HTTP包体传递数据的。
get传递数据是有限制的,而post没有;
get的安全性可能没有post高,所以一般用get来获取数据,post修改数据。
=======================================================================
* http协议的理解(http://www.tuicool.com/articles/Ufmy6j)
http即超文本传输协议,它是基于请求/响应模式的、无状态的、应用层的协议。
http的主要特点:
1、基于请求/响应模式
2、简单快速
3、 灵活
4、无连接
5、无状态
http的工作流程:
建立TCP/IP连接,客户端与服务器端通过socket三次握手建立连接;
然后客户端向服务端发送http请求(请求行:请求的方式、请求路径、http协议的版本);
其次客户端向服务端发送请求头、请求内容;
服务器接受请求,然后给客户端作出应答(发送响应行,响应行:http协议的版本、状态码、状态码文本描述);
其次服务器向客户端发送响应头、响应内容;
服务器关闭tcp连接,如果客户端头部或服务器端头部添加了connection为keep-alive,客户端与服务器端的连接会继续保持,
在下次请求时会继续使用这次的连接。
http请求由三部分组成:请求行、消息报头、消息正文
http响应:响应行、响应报头、响应正文
通用首部:
date 消息发送时间
cache-control指定客户端和服务器遵循的缓存机制
pragma:同cache-control一致
connection允许客户端或服务器端任何一方通过设置该字段来确定在请求响应完成之后,是关闭TCP连接还是继续保持TCP连接
upgrade用来指定完全不同的通信协议
请求报文包含的字段:
accept:浏览器能够处理的内容类型
accept-ecoding: 浏览器能够处理的压缩编码
accept-charset: 浏览器能够处理的字符集
accept-language: 浏览器当前设置的语言
host: 当前页面所在的域
referer: 发出请求的页面的uri
use-angent: 浏览器的用户代理字符串
cookie
authorization: 授权信息
if-none-mach
if-modified-since
响应报文包含的字段:
server: 数据的服务器类型
x-powered-by: 自定义的响应头
vary: 告诉下游代理是使用缓存数据还是从原始服务器请求
set-cookie
ETag: 缓存有关的头
Last-modified: 请求资源的最后修改的时间
请求消息和响应消息都可以包含实体,所以都可能包含的实体头部字段有:
content-type:消息类型
content-length: 消息长度
content-encoding:消息的压缩类型
expires: 设置资源的缓存时间
状态码:
============================================================================================
* 关于客户端存储:
cookie的结构: cookie中的变量通过"属性=值"的形式保存
响应的cookie保存在set-cookie字段里面
字段的组成:
名称: 唯一标识cookie
值
有效时间: cookie的过期时间
域: cookie在哪些域下有效
路径: 指定域下的那个路径,在向服务器发送请求时,要发送cookie
安全标示:cookie只有在使用ssl连接的时候才发送给服务器
名称和值是必须有的字段,且必须被URL编码(encodeURIComponent编码)
cookie的限制:
cookie绑定在特定的域名下,在创建了cookie之后,在给创建它的域名发送请求时,都会包含这个cookie。
将cookie绑定在特定域下,是出于安全性考虑,确保cookie中的信息只有批准的接受方才能访问。
每个域下的cookie总数是有限的,不同的浏览器之间各不同,有的浏览器下没有限制,有的每个域下最多50个cookie,有
的30个cookie。
为什么要限制每个域下cookie数量:
因为cookie是存在客户端的计算机中,有限制是为了确保cookie不会被恶意使用,同时不会占用太多内存。
cookie在不设置过期时间时默认生命周期为会话时间,cookie存在内存中;设置过期时间,cookie存在计算机的磁盘中。
cookie的应用场景以及安全问题:
记录用户的登录状态、用户的浏览信息等
为什么要有cookie和session:
http协议是无状态的,对事务处理没有记忆功能;cookie和session的存在是为了用于客户端的状态管理。
例如:记录用户的登录状态,将用户的用户名和密码通过加密之后存在cookie中。
为什么要限制cookie大小:
因为cookie会通过http请求发送给服务器,cookie越小对传输性能的影响就越小。
cookie与session的区别:
cookie、localstorage、sessionstorage的区别:
获取、设置cookie的方法:
var CookieUtil = { getCookie: function ( name ) { var cookieName = decodeURIComponent( name ) + "="; var cookieStart = document.cookie.indexOf( cookieName ); var cookieValue = null; if ( cookieStart > -1) { var cookieEnd = document.cookie.indexOf(";", cookieStart); if (cookieEnd === -1) { cookieEnd = document.cookie.length; } cookieValue = decodeURIComponent( document.cookie.substring(cookieStart + cookieName.length, cookieEnd) ); } return cookieValue; }, setCookie: function (name, value, expires, path, domain, secure) { var cookieText = encodeURIComponent( name )+ "=" + encodeURIComponent( value ); if ( expires instanceof Date ) { cookieText += "; expires=" + expires.toGMTString(); } if ( path ) { cookieText += "; path=" + path; } if ( domain ) { cookieText += "; domain=" + domain; } if ( secure ) { cookieText += "; secure=" + secure; } document.cookie = cookieText; }, unset: function( name, path, domain, secure ) { this.set(name, "", new Date(0), path, domain, secure); } };
===========================================================================================
* 关于缓存
禁止浏览器缓存资源的方式:
将expires设置为0或-1
cache-control设置为 no-cache
pragma设置为no-cache
浏览器缓存就是浏览器端保存数据用于快速读取或避免重复性地请求资源的一种优化机制
1、http缓存,基于http协议的浏览器文件级缓存机制。
强缓存和协商缓存的命中管理过程:
当浏览器下载资源时,首先会根据资源的http头部信息判断资源是否命中强缓存,如果命中强缓存,浏览器就会直接从自己的缓存中调用资源,不会再将请求
发送到服务器;
如果没有命中强缓存,就会将请求发送到服务器,然后根据http头部中的信息判断是否命中协商缓存,如果命中,就会向浏览器返回请求,但是不会返回资源,
而是告诉浏览器可以直接从缓存中下载该资源;如果未命中,就从服务器中加载资源数据。
强缓存和协商缓存的共同点及区别:
共同点是:命中都从浏览器缓存中加载资源
区别: 强缓存不发请求到服务器,协商缓存要发请求到服务器
强缓存:
通过给http 响应头中设置expries或cache-control字段来实现
expries即给资源设置过期时间,设置的是绝对时间,时间设置取决于服务器,http1.0提出的,原理:
1、浏览器第一次向服务器请求资源时,服务器成功处理请求,并将资源返回给浏览器的同时,会将expires字段添加到响应头中
2、浏览器接受到服务器返回的资源,会将资源连同所有响应头全部缓存下来
3、浏览器下次再请求这个资源时,会首先去缓存中查找这个资源,查找到后会将字段中的expires同当前请求的时间做比较,如果
请求时间在expries之前,就会命中缓存
4、如果没有命中缓存,就直接去服务器加载资源,再重新设置expries的值。
cache-control:设置缓存时间,设置的是相对时间,以秒为单位,http1.1提出的,cache-control:max-age:222222;原理:
和expries类似,只是在浏览器的缓存中查找到资源后,会根据第一次请求和cache-control计算出一个资源过期时间,然后再拿这
个值与当前请求的时间比较,在过期时间之前,即命中缓存;否则,请求服务器重新加载资源,同时重新更新cache-control的值。
expries与cache-control的差异:
expries设置的时间是服务器返回的时间,如果客户端的时间与服务器端的时间不一致,最后结果就会有偏差。
而cache-control设置的是相对时间,不依赖于服务器端的时间,所以用cache-control设置缓存管理会更有效。
使用问题:
可以同时使用,也可以只使用其中一个
同时使用时,cache-control的优先级高于expries
协商缓存:
协商缓存就是通过ETag/ If-none-match Last-modified/If-modified-since这两对来设置缓存
Last-modified/If-modified-since控制缓存的原理,如果修改了服务器端的时间或篡改客户端缓存,这个协商缓存就不可靠:
1、浏览器第一次向服务器端请求资源时,服务器在向浏览器返回这个资源的同时会向响应头中添加last-modified字段,
表示这个资源在服务器上最后修改的时间。
2、浏览器再次向服务器请求这个资源时,就会在请求头部添加if-modified-since字段,这个字段的值就是上次请求时
返回的last-modified的值。
3、服务器再次收到请求,会将浏览器传过来的if-modified-since与资源在服务器上最后修改的时间做比较,如果一致,
服务器返回304 not modified,不用返回资源,响应头中也不包含last-modified,因为last-modified未改变。
4、浏览器接受到服务器返回的304 not modified,就会从缓存中加载资源。
5、如果协商缓存没有命中,就向服务器请求资源,last-modified在资源重新加载的时候被更新。
ETag/ If-none-match控制缓存的原理:
1、浏览器第一次向服务器端请求资源时,服务器在向浏览器返回这个资源的同时会向响应头中添加ETag字段,这个字段的值
是服务器根据请求的资源生成的一个唯一的标识,这个唯一的标识是一个字符串,只要资源变化这个值就不同。
2、浏览器下次再请求服务器时,就会将if-none-match字段添加到请求头中,这个字段的值就是上次请求返回的ETag的值。
3、服务器再次收到请求,就会将请求头中的if-none-match的值与服务器根据请求资源新生成的ETag进行比较,如果相同,就向浏览器
返回304 not modified,同时返回ETag(只要重新生成过就会返回,尽管没有变化)。如果不想同,就正常返回资源。
4、浏览器端接收到服务器端返回的304 not modified,就从缓存中获取资源
浏览器行为对缓存的影响:
ctrl+f5刷新页面,会跳过强缓存和协商缓存,直接向服务器加载资源
f5刷新页面,会跳过强缓存,检测协商缓存
(关于浏览器缓存:http://blog.csdn.net/longxibendi/article/details/41630389)
2、应用缓存(http://www.jianshu.com/p/98cd7a6985ac)
HTML5的appcache,专门为开发离线web应用而设计的
1、创建一个后缀为manifest的描述文件,描述文件中包含需要下载和缓存的文件
CACHE MANIFEST
#Comment(注释)
XX.js //需要缓存的资源
xx.css
NETWORK:
xx.js //在线状态才加载的资源
FALLBACK:
/ /index.html //备选资源路径,第一个路径代表任何匹配的资源都不被缓存,第二个路径代表被缓存的资源
2、在页面的html标签中添加manifest,设置值为描述文件的路径。
注意: 应用缓存被添加就不会被改变
改变应用缓存的方式:删除描述文件、修改描述文件、删除页面html中的manifest属性(否则应用缓存再资源改变之后,也不会被刷新)
======================================================================================
* 从输入网址到页面呈现内容这个过程中都发生了什么
在浏览器地址栏输入地址,首先会将地址发送给DNS进行域名解析,客户端获取到对应的ip地址
然后向对应的网络服务器发送http请求
传输到传输层,客户端与服务器端建立TCP三次握手连接,数据包被分割
然后数据包传输到网络层,通过ip地址获取到对应的MAC地址
数据包被传输到数据链路层,然后根据接受方的MAC地址,将数据发送给服务器
服务器在链路层获取到数据然后又通过层层上传,直到应用层;这个过程包括在传输层TCP将数据包组合的过程
服务器在接受到客户端发送的HTTP请求之后,查找到客户端请求资源,并返回响应报文
客户端成功接受到服务器端的响应,并下载资源,资源包括html文件、html中可能含有的css、js、图片等资源
然后客户端开始解析html,生成DOM树
解析css,生成渲染树
然后渲染每一个节点
* 浏览器如何加载、解析、渲染页面
用户在浏览器地址栏输入地址,然后将地址发送给DNS进行域名解析,获取到对应的ip地址。
客户端获取到ip地址,并向ip地址对应的网络服务器发送HTTP请求。
网络服务器接受到客户端的请求,并去请求数据库服务器获取数据。
数据库服务器接受到请求并返回请求数据给网络服务器,网络服务器接受到数据,并解析生成html文件。
网络服务器通过http response将html文件发送给客户端。
客户端接受服务器端的响应,并下载html文件,以及html文件中可能包含的外部引入的css文件、js文件、图片等资源。
页面加载顺序是由上至下
在加载js文件、css文件、图片时都分别会发送http请求来获取资源
在加载js文件时,js会立即执行,js加载执行的时候,会阻塞后面代码的加载执行。
在加载css文件时,不会阻塞后面的js文件的加载,但是会阻塞后面js文件的执行。
在加载图片时,是异步加载,不会影响html文档的加载。
解析:
客户端在下载了html,然后解析html生成DOM树
下载css文件,就会解析css生成css规则树
然后根据DOM树和css规则树来构建渲染树
(计算节点位置,布局渲染树)
最后遍历渲染树渲染节点
渲染树不包括不可见元素:head、display:none的元素
DOM树的元素和文档中含有的标签元素一样。
注意: 渲染引擎为了更好的用户体验,html在一边解析就在一边被渲染(css已获取到,如果因为网速原因,css未被下载完成,也不会影响后面的html文档的加载),
而不是 等到html全部加载完再渲染。
渲染:
渲染过程依赖于dom树和css规则树,也就是页面渲染受到dom结构、css选择器的写法影响。
在查找元素匹配的css选择器时,查找过程是从选择器的右到左开始查找的,所以选择器嵌套的越深查找的就越慢。
Reflow和Repaint:
Reflow:回流或是重排,页面某个地方发生了变化,影响了页面布局。页面需要重头开始渲染。
Repaint: 重绘,页面某个元素的样式发生变化,但是没有影响页面布局,页面重新渲染变化的部分。
导致Reflow的条件:
操作dom,例如:删除、修改、添加、移动dom,给dom添加动画效果。
改变窗口大小
改变页面字体大小
增加删除样式表
导致Repaint的条件:
页面中的元素属性发生变化,例如:改变了背景颜色,页面布局没有影响,只会导致重绘。
Reflow比Repaint更耗时间。
重绘和重排都会影响用户体验,所以应尽量减少页面的重绘与重排:
1、不要一条一条的修改样式,可以预先定义好css的class,然后修改dom的className;
2、减少对DOM的操作
3、为要添加动画的html元素,设置绝对定位或固定定位,让元素脱离文档流(脱离文档流的元素在另一个渲染树上,添加动画不会影响文档页面的渲染);
4、不要使用table布局,table中的一个小改动,就会造成整个table的重新布局。
(table布局不够灵活,不便于维护,不易于seo)
明白了浏览器加载、解析、渲染文件的过程,就知道如何来优化网站的文件和资源了
====================================================================
* 如何对网站的文件和资源进行优化?
1、合并文件(减少http请求),对于图片的合并可以使用css sprites将多张图片合并成一张,然后通过background-position等css属性来获取
图片(页面请求数越多页面加载的就越慢)。
2、压缩文件,减少数据量(请求中传输数据量越小,传输的越快 )
3、静态资源利用cdn托管(尽可能的避开互联网上可能影响数据传输速度和稳定性的瓶颈和环节,解决的是internet网络拥挤的状态,提高用户访问网站的响应速度)
4、利用缓存:
服务器端设置cache-control、expries、last-modified、ETag,缓存文件。
5、将css放在头部,js放在尾部
6、图片设置宽高,避免页面的重排。
7、用多个域名来存储资源(浏览器同一时刻对同一个域下下载资源个数是有限制的,采用不同域来存储可以加快浏览器下载资源的速度)
* 前端性能优化
1、减少http请求:合并js、css、图片等文件,减少加载资源时的请求次数,节省网络请求时间,加快页面的加载
2、静态资源采用cdn托管: 尽可能避开网络上影响资源传输速度和稳定性的瓶颈和环节,提高用户访问网站的速度
3、css放到顶部:页面加载资源顺序是从上到下,css放到顶部可以优先渲染页面,让用户感觉页面加载很快
4、js放到底部
5、将css、js放到外部文件中,缓存文件
6、css不要采用css表达式:表达式会持续在页面上计算样式,影响性能,并且表达式只被ie支持
7、压缩文件,减小文件大小
8、使用gizp压缩内容:gizp能够压缩任何文本类型的响应(xml、html、json),大大缩小请求返回的数据量
9、减少对dom的操作(对dom的操作会导致页面重排,增加浏览器解析负担)
10、避免空的src、href
11、避免404错误: 404错误会破坏浏览器的并行加载
12、设置可缓存的ajax
13、使用get方式来完成ajax请求获取数据
14、减少cookie大小
15、使用无cookie的域来存放静态资源
16、权衡dns查找次数:大量的dns查询,会影响页面响应速度
17、请求地址最后加上/,避免默认跳转
18、不要使用滤镜
19、不要再html缩放图片:图片需要多大就设置多大尺寸(避免页面重排)
20、缩小favicon.ico并缓存
* 为什么利用多个域名来存储资源会更有效?
浏览器在同一时间同一域下可同时下载的资源是有限的。
* 浏览器同一时间可以从同一域名下载多少资源?
不同浏览器不同: 2、4、6、8不等
=====================================================================
* 什么是同源策略,为什么要有同源策略
同源策略主要针对的是通过XHR实现的ajax通信
一个XHR对象只能访问与包含它的页面处在同一域中的资源
* 跨域
* 前端安全: xss和csrf
====================================================================
* 异步编程(http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html)
javascript执行任务的模式有两种: 同步和异步
同步和异步的区别:
异步的好处: 对于非常耗时的操作应该进行异步处理,避免程序一直运行让浏览器失去响应。
js提供的异步编程的方法:
回调函数:
事件监听:
发布与订阅:
promise:
* 如何来获取UA
===================================================================
* 事件:
* 事件代理:
*CMD与AMD、commentJS的区别
commentJS服务器端JavaScript的编码规范,AMD和CMD是客户端JavaScript的编码规范;
commentJS通过export向外导出接口,用require来引入模块;
AMD利用define来明确定义模块,通过返回的方式向外提供接口,在声明模块的时候,需要指定所有的依赖,同样也是通过require来引入模块;
define(['dep1', 'dep2'], function (dep1, dep2) {
return function () {};
});
CMD也是利用define来明确定义模块,支持动态引入依赖,require、module、exports通过形参传递给模块,在需要依赖模块时,随时调用require()引入。
define( function( require, exports, module) {
});
(AMD与CMD的区别在于定义模块和依赖引入部分的不同)
* 如何区别nodejs环境和浏览器环境
node环境中没有window全局对象,全局对象为global;浏览器的全局对象为window。
* 异步编程
css3:
* 优雅降级和渐进增强
优雅降级:先实现只有高版本浏览器支持的功能,再针对低版本浏览器实现兼容
渐进增强:先针对低版本浏览器实现功能,再到实现只有高版本浏览器支持的功能,让页面都能够有更好的用户体验
* 制定一个标准的过程
* display和visiblity的区别
* box-sizing的理解(https://developer.mozilla.org/zh-CN/docs/Web/CSS/box-sizing)
* animation和transfrom、transition的区别
三者都可用来制作动画效果,但是transform是一个静态属性,主要用于做元素的特殊变形;
transition是一个动态属性,是animation的简单版,它作用于元素的样式属性,必须需要用事件来触发才能实现动画效果;
animation也是一个动态属性,它作用于元素本身,可以利用关键帧keyframe来实现更自由的动画效果,不使用事件触发也能实现动画效果。
==================================================================================
* BFC
块级格式化上下文,设置为BFC的元素中的子元素的布局不会受容器外部元素的影响,子元素的布局也不会影响外部元素。
生成一个BFC元素的方式:
float不为none
overflow不为visible
display设为table-cell、table-capation、inline-block中的任何一个
position不为static和relative
BFC的用处:
不让元素与浮动元素重叠
清除元素内部浮动
避免两个相邻元素的垂直外边距发生重叠
非浮动元素和浮动元素重叠原理: 在BFC中,每个元素的左边距要与包含块的左边距相接触。创建了BFC的元素不能与浮动元素重叠
普通流中的元素的子元素的高度计算方式: 在普通文档流中,元素的浮动子元素的高度不会计算在内;设为BFC的元素在计算高度时,其浮动子元素的高度会计算在内。
相邻两个垂直外边距重叠: 处在同一个BFC中的两个相邻垂直外边距会发生重叠,设置为BFC的元素不会与其子元素的外边距发生重叠。
根元素生成的是BFC元素
=====================================================================================================
* 外边距重叠
处在 普通文档流 同一环境 中的两个相邻垂直外边距会有重叠现象。(同一环境中的两个浮动元素不会发生垂直外边距重叠)
合并方式: 两个相邻垂直外边距相等时,合并为一个外边距
不相等时,取最大的那个
两个都为负数时,取绝对值较大的那个
一个为正一个为负数时,取两个外边距的和
外边距重叠不仅发生在兄弟元素之间,还发生在父子元素之间(普通流中的元素会和其子元素的垂直方向上的空白边距重叠)、和自身(自身在没有内容填充的情况下/上边距会 重叠)。
(子元素与父元素都处在普通流中,那么它们就是一个整体,子元素设置margin-top/margin-bottom相对的是父容器外面的元素,子元素的垂直外边距与父元素的垂直外边距在同一BFC中;要让子元素的垂直外边距与父元素的垂直外边距在不同的环境中,可将父元素设置为一个BFC的元素,设置为BFC的元素,其子元素会按文档流一个一个排列,垂直方向上的起始位置为包含块的顶部,相邻元素垂直方向上的距离由margin决定)。
哪些元素会有外边距重叠:普通流中块级元素的垂直外边距会发生合并,行内框、浮动元素或绝对定位之间的外边距不会合并。
普通流中块级元素的垂直外边距会发生合并:
<div style="width:400px; margin:40px; ">
<div style="background:gray; margin:20px; " >6666</div>
</div>
垂直外边距遵循上面的合并方式(如果将子元素设置overflow:hidden结果和上面一样)
设置为BFC的元素的垂直外边距不会和子元素的垂直外边距重叠:
<div style="width:400px; margin:40px; overflow:hidden;">
<div style="background:gray; margin:20px; " >6666</div>
</div>
行内框、浮动元素或绝对定位之间的垂直外边距不会合并:
1、 <div style="width:400px; margin:40px;">
<div style="background:gray; margin:20px; display: inline-block;" >6666</div>
</div>
2、 <div style="width:400px; height: 100px; margin:40px; ">
<div style="background:gray; margin:20px; float: left;" >6666</div>
</div>
3、<div style="width:400px; height: 100px; margin:40px; position: relative;">
<div style="background:gray; margin:20px; position: absolute;" >6666</div>
</div>
同2一样,2、3因为设置float、absoulte布局,元素会脱离文档流不会撑开父容器,所以必须给父容器设置高度。
* nomal flow 文档流
==================================================================================================
* 块级元素与行内元素、行内块级元素的区别
块级元素总是独占一行,块级元素由上至下排列,可以设置宽、高、margin、padding值
多个行内元素在一行排列,至到一行排列不下才另起一行,不可以设置宽、高,margin的上下边距,和padding的上下边距
行内块级元素,元素布局类似行级元素,元素中的内容布局类似块级元素,元素可以设置宽、高、margin、padding(input、img、
button等都是可以设置宽、高的行级元素)。
* 对line-height的理解
* 如何给行级元素设置高度:
块级元素: div 、p、h1~h6、li、ul等
行级元素: a、br、strong、img、input、button、textarea等
行级元素例如:a,本身不能设置宽、高
可以将元素display:block/inline-block 、float:left/right、position:absolute
.floatest { /*margin: 20px;*/ /*float: left;*/ position: absolute; height: 100px; width: 100px; background: #FF0; } .floatTest2 { /*display: inline ; float: left;*/ margin: 20px; height: 100px; width: 100px; background: #FF0000; }
<div class="floatTest2"> 66666 </div> <a class="floatTest"> 77777</a>
(再一次补充:设置为inline-block或absolute定位或设置了float的元素,它们的垂直外边距不会和相邻的垂直外边距发生重叠)
================================================================================================
* css的盒模型的理解
文档中的每个节点都会被描绘成一个矩形盒子,渲染引擎的目的就是判定盒子的大小、背景颜色、边框、位置等方面,盒模型由元素的margin、padding、border、
元素内容构成。
盒模型分为2种:标准盒子模型和ie盒子模型。
两种盒模型的区别: 标准盒模型的元素的属性宽、高不包含元素的padding和border的值,而ie盒子模型的元素的属性宽、高包含。
页面在标准模式下,元素按标准盒模型的方式渲染,页面在各浏览器上呈现都如此;页面在怪异模式下,并在ie9及以下浏览器上呈现,元素按ie盒子模型的方式渲染,其他高版本浏览器均按标准盒模型的方式渲染。
* 什么是标准模式,什么是怪异模式
标准模式:浏览器按w3c标准来解析执行页面;怪异模式:浏览器以一种向后兼容的方式呈现页面,主要是模拟老式浏览器的行为,以防止老式站点无法工作。
* 如何触发标准模式和怪异模式:
1、页面没有写Doctype,或是Doctype格式不正确会触发怪异模式,Doctype必须声明在页面的第一行
2、对于html4.01,包含严格DTD的Doctype会以标准模式呈现页面;包含过渡DTD和URI的Doctype以标准模式呈现页面,
只包含DTD不包含URI的会以怪异模式呈现。框架集DTD和过渡类似。
* box-sizing改变盒模型的计算方式
box-sizing: centent-box 标准盒模型计算
border-box ie盒模型计算
inherit 继承父元素的属性
==================================================================================================
* float的理解
设置了浮动的元素会脱离文档
一个浮动元素,如果前面的元素也是一个浮动元素,该元素就会紧跟前面的元素在后面排列(前提是一行能够容纳的下这两元素。否则,后面的元素会在新的一行显示);
如果前面的元素是一个在标准文档流中的元素,则在新的一行排列。浮动元素的顶部和上一个元素的底部对齐。
清除浮动的方式:
1、 clear:none,默认值允许两边有浮动元素
left,元素左边不允许有浮动元素
right
both
作用的是使用清除的元素本身
2、给浮动元素添加父元素,并给其设置
overflow:hidden/auto(将超出部分裁剪去掉)
zoom: 1
清除浮动的原理是:将浮动元素包含在一个BFC的容器里,这样BFC中的浮动元素就不会对容器外面的元素产生影响。
3、利用:after给浮动元素的父元素添加一个空元素
.clearfloat:after{display:block;clear:both;content:"";visibility:hidden;height:0}
.clearfloat{zoom:1}//支持ie6
* div居中的方式
1、水平居中: 元素左右外边距设置为auto
2、水平垂直居中:
已知元素大小:
position+margin:auto
.center1 {
position: absolute;
width: 200px;
height: 200px;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
/*margin: 0 auto;*/
background: #FF0;
}
position+absolute/relative +margin-left、margin-top
.center2 {
position: absolute;//relative
width: 200px;
height: 200px;
top: 50%;
left: 50%;
margin: -100px 0 0 -100px;
/*margin: 0 auto;*/
background: #FF0;
}
父元素设置为table-cell,然后设置vertical-align:middle,子元素设置margin:0 auto。(父元素不能居中)
.div1{
display: table-cell;
width: 500px;
height: 500px;
/*margin-right: auto;
margin-left: auto;*/
border:1px solid red;
vertical-align: middle;
}
.div2{
width: 100px;
height: 200px;
background: blue;
margin:0 auto; /*为了水平居中*/
}
未知子元素大小,子元素相对于父元素居中:
transform(ie9以下不支持),子元素设置样式如下:
.center3 {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
/*margin: 0 auto;*/
background: #FF0;
}
子元素相对于父元素居中,宽高由父元素决定
.div3{
position: relative;
width: 500px;
height: 500px;
border: 1px solid red;
margin:auto;
}
.div4{
position: absolute;
left: 30%;
right:30%;
top: 20%;
bottom:20%;
background: blue;
text-align: center;//让文字居中
line-height: 300px;
}
flex布局(ie11+才支持,存在兼容性问题):
.flex1 {
margin-top: 20px;
display: flex;
justify-content: center;
align-items: center;
height: 400px;
background: #000;
}
.sub_flex1 {
width: 100px;
height: 100px;
background: #009246;
}
注: vertical-align
* inline-block布局,以及兼容性:
需要设置宽度,否则元素大小就由元素内容决定
行内块元素之间一行显示时会有间隙
vertical-align: top对inline-block有影响
* columns多列布局
* flexbox布局,以及使用场景
* div自适应布局
1、两列显示,一端固定,一端自适应(下面两种方法两个元素都是重叠的)
左边的元素固定宽高,右边元素宽度自适应
<div style="width: 100px; height: 100px; background: #0000FF; float: left; "></div>
<div style="background: #FF0; margin-left: -100px; height: 150px; "></div>
左边元素宽度由内容撑开,右边元素宽度自适应
<div style=" background: #0000FF; float: left;">666</div>
<div style="background: #FF0; margin-left: -10000px; padding-left: 10000px; height: 40px; "></div>
2、 左边元素宽度由内容撑开,右边元素宽度自适应,且不重叠
<div style="width: 100px; height: 100px; background: #0000FF; float: left; "></div>
<div style="background: #FF0; margin-left: 100px; height: 150px; "></div>
* margin负外边距
<div style="background: #f00; padding-bottom: 10000px;margin-bottom: -10000px;">666</div>
全屏:margin-bottom并未抵消padding-bottom
<div style="background: #f00; padding-top: 10000px;margin-top: -10000px;">666</div>
margin-top抵消了padding-top的值
* css3多列布局
===========================================================================================
* css选择器类型,以及css样式优先级,计算方式
* 浏览器的重绘与重排
操作DOM
改变
html
* html语义化的理解
其他:
* 原生app、webapp、混合app
http://bbs.csdn.net/topics/392051313?page=1
未完待续...