目录
22.6 让你的内容可编辑,只需要加一个contenteditable属性
1 懒加载
1.1 什么是懒加载?
懒加载也就是延迟加载,当访问一个页面的时候,先把img元素或是其他元素的背景图片路径替换成一张大小为1*1px图片的路径(这样就只需请求一次,俗称占位图),只有当图片出现在浏览器的可视区域内时,才设置图片正真的路径,让图片显示出来。这就是图片懒加载。
1.2 为什么要使用懒加载?
很多页面很长,图片很多,图片很大,页面如果一次性加载完毕会消耗很多的时间。
1.3 懒加载的原理是什么?
页面中的img元素,如果没有src属性,浏览器就不会发出请求去下载图片,只有通过javascript设置了图片路径,浏览器才会发送请求。 懒加载的原理就是先在页面中把所有的图片统一使用一张占位图进行占位,把真正的路径存在元素的“data-url”属性里,要用的时候就取出来,再设置。
1.4 懒加载的实现步骤?
不要将图片地址放到src属性中,而是放到其它属性(data-original)中。 页面加载完成后,根据scrollTop判断图片是否在用户的视野内,如果在,则将data-original属性中的值取出存放到src属性中。 在滚动事件中重复判断图片是否进入视野,如果进入,则将data-original属性中的值取出存放到src属性中。
2 预加载
2.1 什么是预加载?
提前加载图片,当用户需要查看时可直接从本地缓存中渲染。
2.2 为什么使用预加载
图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度。这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速、无缝地发布,也可帮助用户在浏览你网站内容时获得更好的用户体验。
2.3 怎么实现预加载
2.3.1 CSS和JavaScript实现预加载
1,单纯使用CSS,可容易、高效地预加载图片
#preload-01 { background: url(http://domain.tld/image-01.png) no-repeat -9999px -9999px; }
#preload-02 { background: url(http://domain.tld/image-02.png) no-repeat -9999px -9999px; }
#preload-03 { background: url(http://domain.tld/image-03.png) no-repeat -9999px -9999px; }
2,使用上述加载的图片会同页面的其他内容一起加载,增加了页面的整体加载时间。为了解决这个问题,我们增加了一些JavaScript代码,来推迟预加载的时间,直到页面加载完毕。
function preloader() {
if (document.getElementById) {
document.getElementById("preload-01").style.background = "url(http://domain.tld/image-01.png) no-repeat -9999px -9999px";
document.getElementById("preload-02").style.background = "url(http://domain.tld/image-02.png) no-repeat -9999px -9999px";
document.getElementById("preload-03").style.background = "url(http://domain.tld/image-03.png) no-repeat -9999px -9999px";
}
}
2.3.2 JavaScript实现预加载
<div class="hidden">
<script type="text/javascript">
var images = new Array()
function preload() {
for (i = 0; i < preload.arguments.length; i++) {
images[i] = new Image()
images[i].src = preload.arguments[i]
}
}
preload(
"http://domain.tld/gallery/image-001.jpg",
"http://domain.tld/gallery/image-002.jpg",
"http://domain.tld/gallery/image-003.jpg"
)
</script>
</div>
2.3.3 Ajax
使用Ajax,加载文件不会应用到加载页面上。从这点上看,Ajax方法优越于JavaScript。
window.onload = function() {
setTimeout(function() {
// reference to <head>
var head = document.getElementsByTagName('head')[0];
// a new CSS
var css = document.createElement('link');
css.type = "text/css";
css.rel = "stylesheet";
css.href = "http://domain.tld/preload.css";
// a new JS
var js = document.createElement("script");
js.type = "text/javascript";
js.src = "http://domain.tld/preload.js";
// preload JS and CSS
head.appendChild(css);
head.appendChild(js);
// preload image
new Image().src = "http://domain.tld/preload.png";
}, 1000);
};
3 线程和进程的区别
3.1 进程
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
3.2 线程
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源,但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
3.3 区别
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,单线程应用的线程死掉就等于整个进程死掉,所以多进程的程序要比单线程的程序健壮。
-
一个程序至少有一个进程,一个进程至少有一个线程。
-
线程的划分尺度小于进程,使得多线程程序的并发性高。
-
进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
-
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
-
多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
4 如何判断变量类型
如何判断一个变量是对象还是数组
4.1 length属性
-
对象没有length属性值,其值为undefiend。
-
数组的length值为number类型,一般不用,当对象的属性存在length。
4.2 instanceof
var arr = [1, 2, 3];
var obj = {
name: 'lyl',
age: 18,
1: 'name'
}
console.log(arr instanceof Array); //true
console.log(obj instanceof Array); //false
4.3 constructor
var arr = [1, 2, 3];
var obj = {
name: 'lw',
age: 18,
1: 'name'
}
console.log(arr.constructor === Array); //true
console.log(obj.constructor === Array); //false
4.4 toString
toString()方法,数组原型和对象原型定义的toString()方法不同
var arr = [1, 2, 3];
var obj = {
name: 'lyl',
age: 18,
1: 'name'
}
console.log(Object.prototype.toString.call(arr) === '[object Array]'); //true
console.log(Object.prototype.toString.call(boj) === '[object Array]'); //false
5 GET和POST
-
GET - 从指定的资源请求数据。
-
POST - 向指定的资源提交要被处理的数据
5.1 一般答案
-
GET使用URL或Cookie传参。而POST将数据放在BODY中。
-
GET的URL会有长度上的限制,则POST的数据则可以非常大。
-
POST比GET安全,因为数据在地址栏上不可见。
5.2 其他答案
-
浏览器。据说早期的浏览器会对URL长度做限制。据说IE对URL长度会限制在2048个字符内。
-
服务器。URL长了,对服务器处理也是一种负担。如果有人恶意地构造几个几M大小的URL,并不停地访问你的服务器。服务器的最大并发数显然会下降。另一种攻击方式是,把告诉服务器Content-Length是一个很大的数,然后只给服务器发一点儿数据,服务器消耗很大。有鉴于此,多数服务器出于安全啦、稳定啦方面的考虑,会给URL长度加限制。但是这个限制是针对所有HTTP请求的,与GET、POST没有关系。
6 session和Cookie的区别
6.1 HTTP协议
协议:指计算机通信网络中两台计算机之间进行通信所必须共同遵守的规定或规则,超文本传输协议(HTTP)是一种通信协议,它允许将超文本标记语言(HTML)文档从Web服务器传送到客户端的浏览器。
HTTP协议:无状态的协议。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话。
6.2 会话跟踪
用户登录网站后的一系列动作,比如浏览商品添加到购物车并购买。会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术。是Cookie与Session。Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。
6.3 Cookie
HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份。用户A购买了一件商品放入购物车内,当再次购买商品时服务器已经无法判断该购买行为是属于用户A的会话还是用户B的会话了。服务器Cookie对客户进行辨别。
Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。Cookie具有不可跨域名性,浏览器访问网易不会带上腾讯的cookie。
6.4 Session
Sessions在服务器记录客户端信息。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。每个用户访问服务器都会建立一个session,通过SessionId对用户进行识别。
6.5 总结
-
cookie数据存放在客户的浏览器上,session数据放在服务器上。
-
cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。
-
session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。
-
单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
-
可以考虑将登陆信息等重要信息存放为session,其他信息如果需要保留,可以放在cookie中。
7 call 和apply的区别
7.1 call
a对象的方法应用到b对象上
7.1.1 继承式
一个对象没有这个方法,就继承另外一个对象的方法。
function cat(){ } //做一个原型扩展 cat.prototype={ food:"fish", say: function(){ alert("I love "+this.food); } } var blackCat = new cat(); blackCat.say(); //当我需要一条黑狗也说它喜欢什么时: blackDog = {food:"bone"}; //我们不想对它重新定义say方法,那么我们可以通过call用blackCat的say方法: blackCat.say.call(blackDog);
7.1.2 替换式
A对象里面有name的属性,但是没有值,就借用了B对象的A对象里面有name的属性的值。
function NameShowing(){
this.showName = function(){
document.write(this.name);
}
}
function Person(name){
this.name = null;
this.Init = function(name){
this.name = name;
}
this.Init(name);
};
var nameShowing = new NameShowing();
var jeremy = new Person("Jeremy")
//替换this指向 jeremy
nameShowing.showName.call(jeremy);
7.1.3 实例继承
一个对象继承另外一个对象
function NameShowing(){
this.showName = function(){
document.write(this.name);
}
}
function Person(name){
this.name = null;
this.Init = function(name){
this.name = name;
}
this.Init(name);
};
var person = new Person("Jeremy")
NameShowing.call(person);
jeremy.showName();
7.1.4 带有构造函数
function Person(name, age){
this.name = null;
this.age = null;
this.showPersonInfo = function(){
document.write("Name: " + this.name + "");
document.write("Age: " + this.age + "");
};
this.Init = function(){
this.name = name;
this.age = age;
};
this.Init();
}
var jeremy = new Object();
Person.call(jeremy, "Jeremy", 20);
jeremy.showPersonInfo();
7.2 apply
劫持另外一个对象的方法,继承另外一个对象的属性.
Function.apply(obj,args)
obj:这个对象将代替Function类里this对象
args:数组
实例:
/*定义一个人类*/
function Person(name,age)
{
this.name=name;
this.age=age;
}
/*定义一个学生类*/
function Student(name,age,grade)
{
Person.apply(this,arguments);
this.grade=grade;
}
//创建一个学生类
var student=new Student("qian",21,"一年级");
8 数据类型
8.1 基本数据类型
Number、String 、Boolean、Null和Undefined,保存在栈内存。
8.2 引用类型数据
对象类型Object type,比如:Object 、Array 、Function 、Data等。javascript的引用数据类型是保存在堆内存中的对象。引用类型数据在栈内存中保存的实际上是对象在堆内存中的引用地址。通过这个引用地址可以快速查找到保存中堆内存中的对象。
8.3 区别
8.3.1 存储位置
基本数据类型是存储在栈(stack)中的简单数据段。引用类型,存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存地址。
8.3.2 访问机制
-
javascript中不允许直接访问堆内存中的对象,访问一个对象时,首先得到的是这个对象在堆内存中的地址,按照这个地址去获得这个对象中的值,
-
原始类型的值则是可以直接访问到的
8.3.3 复制变量的不同
-
基本类型复制后的值是不同的两个值。
-
引用类型复制后,只是不同的指针,但是都是指向同一个对象。
8.3.4 参数传递的不同
-
基本类型把变量里的值传递给参数,之后参数和这个变量互不影响。
-
引用类型对象变量它里面的值是这个对象在堆内存中的内存地址。
9 浏览器渲染机制
10 http请求理解
10.1 URL的理解
web浏览器、服务器和相关的web应用程序都是通过HTTP相互通信的,HTTP是现代的全球因特网中使用的通用语言。JPEG图片、HTML页面、文本文件、MPEG电影、WAV音频文件、Java程序等都是存储在web服务器上的资源,HTTP可以从全世界的web服务器上将这些资源迅速、便捷可靠地传送到客户端、浏览器或者其他应用程序。下面用一次浏览器通过HTTP访问位于远端服务器上的一个HTML页面资源的全过程加深对HTTP的理解。
10.2 访问资源的过程
-
浏览器从URL中解析出服务器的主机名(域名);
-
浏览器将服务器主机名通过DNS(域名服务)转换成服务器的IP地址;
-
浏览器将端口号从URL中解析出来;
-
浏览器建立一条与web服务器的TCP(传输控制协议)连接;
-
浏览器向服务器发送一条HTTP请求报文;
-
服务器向客户端发送一条HTTP响应报文;
-
关闭连接,浏览器显示文档。
10.3 深入理解
10.3.1 解析主机名
浏览器从URL中解析出服务器的主机名。Web上可用的每种资源 ——HTML文档、图像、视频片段、程序等 - 由一个通用资源标识符(Uniform Resource Identifier, 简称"URI")进行定位.URL都遵循一种标准格式。
-
第一部分是协议(或称为服务方式),说明访问资源时使用的协议类型。这部分通常是HTTP协议(http://)。
-
第二部分是存有资源的web服务器的主机名(比如,www.baidu.com)。
-
第三部分是主机资源的具体地址。,如目录和文件名等。(比如,/articles/1)。
10.3.2 转换IP地址
浏览器将服务器主机名通过DNS(域名服务)转换成服务器的IP地址。DNS(Domain Name System,域名系统),因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。通过主机名,最终得到该主机名对应的IP地址的过程叫做域名解析(或主机名解析)
10.3.3 解析端口
浏览器将端口号从URL中解析出来,各种传输协议都有默认的端口号,http的默认端口为80。如果输入时省略,则使用默认端口号,例如,http://www.netscape.com/index.html(假设使用默认端口) 。有时候出于安全或其他考虑,可以在服务器上对端口进行重定义,即采用非标准端口号,此时,URL中就不能省略端口号这一项,例如,http://www.netscape.com:90/index.html 。
10.3.4 建立TCP连接
浏览器建立一条与web服务器的TCP(传输控制协议)连接。TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。在因特网协议族(Internet protocol suite)中,TCP层是位于IP层之上,应用层(HTTP就是属于应用层)之下的中间层。在TCP中需要用到IP和服务器上运行特定软件相关的TCP端口号。
10.3.5 发送报文
浏览器向服务器发送一条HTTP请求报文以及服务器向客户端发送一条HTTP响应报文。从Web客户端发往Web服务器的HTTP报文称为请求报文(request message)。从服务器发往客户端的报文称为响应报文(response message)。
11 跨域
11.1 什么事跨域
跨域是指从一个域名的网页去请求另一个域名的资源。比如从www.baidu.com 页面去请求 www.google.com 的资源。跨域的严格一点的定义是:只要 协议,域名,端口有任何一个的不同,就被当作是跨域
11.2 为什么限制跨域访问
如果一个网页可以随意地访问另外一个网站的资源,那么就有可能在客户完全不知情的情况下出现安全问题。
11.3 跨域处理方式
11.3.1 利用script标签请求
使用script标签请求前,先进行回调函数的申明调用
<script>
function 回调函数名(data数据){ 。。。。 }
</script>
<script src="http://....jsp?callback=回调函数名"></script>
服务器返回字符串
var data = '回调函数名( {"name1":"data1","name2","data2"} )';
res.write(data);
res.end();
11.3.2 ajax跨域
var request = require('request');
var url ="https://c.y.qq.com/v8/fcg-bin/fcg_v8_toplist_cp.fcg?g_tk=5381&uin=0&format=json&inCharset=utf-8&outCharset=utf-8¬ice=0&platform=h5&needNewCode=1&tpl=3&page=detail&type=top&_=1515738119612&topid=";
app.get('/toplist',function (req, res) {
var id =req.query.id;
request(url+id, function (error, response, body) {
if (!error && response.statusCode == 200) {
res.write(body);
res.end();
}
})
})
11.3.3 nodejs后台跨域
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
next();
});
12 js和jq的转换
js它是动态的弱类型的语言,是JavaScript的缩写,而jquery是对js的封装、扩展,jquery是使用js封装的框架。
12.1 js对象转换为jquery对象
原生js的外围加上 $
12.2 jquery对象转换为原生js
jquery的js后面加上get(0)来获取该jquery对象所对应的原生js
12.3 具体代码
<body>
<input type="text" value="123" id="test">
<input type="button" value="测试" onclick="test_()">
</body>
<script>
function test_() {
//将原生的js转换为jquery的js--只需要在外围加上 $
var test=document.getElementById("test").value;
var testJquery=$(document.getElementById("test")).val();
//alert(testJquery);
//将jquery的js转换为原生的js,是加上get(0)
var jqueryTest=$("#test").val();
var testJs=$("#test").get(0).value;
alert(testJs);
}
</script>
13 Ajax
13.1 工作原理
在客户端与服务端之间加了一个抽象层(Ajax引擎),使用户请求和服务器响应异步化,并不是所有的请求都提交给服务器,像一些数据验证和数据处理都交给Ajax引擎来完成,只有确认需要向服务器读取新数据时才右Ajax引擎向服务器提交请求。
13.2 优点
13.2.1 无刷新更新数据
Ajax最大的优点就是能在不刷新整个页面的情况下维持与服务器通信
13.2.2 异步与服务器通信
使用异步的方式与服务器通信,不打断用户的操作
13.2.3 前端与后端负载均衡
将一些后端的工作移到前端,减少服务器与带宽的负担
13.2.4 基于规范被广泛支持
不需要下载浏览器插件或者小程序,但需要客户允许JavaScript在浏览器上执行。
13.2.5 界面与应用分离
Ajax使得界面与应用分离,也就是数据与呈现分离
13.3 缺点
13.3.1 破坏History功能
Ajax干掉了Back与History功能,即对浏览器机制的破坏。在动态更新页面的情况下,用户无法回到前一页的页面状态,因为浏览器仅能记忆历史纪录中的静态页面。
13.3.2 安全问题
AJAX技术给用户带来很好的用户体验的同时也对IT企业带来了新的安全威胁,Ajax技术就如同对企业数据建立了一个直接通道。这使得开发者在不经意间会暴露比以前更多的数据和服务器逻辑。
13.3.3 对搜索引擎支持较弱
13.3.4.破坏程序的异常处理机制
13.3.5.违背URL与资源定位的初衷
14 jq如何获得兄弟节点
$('#id').siblings() 当前元素所有的兄弟节点 $('#id').prev() 当前元素前一个兄弟节点 $('#id').prevaAll() 当前元素之前所有的兄弟节点 $('#id').next() 当前元素之后第一个兄弟节点 $('#id').nextAll() 当前元素之后所有的兄弟节点
15 jsonp解决跨域以及工作原理
15.1 原理
JSONP的最基本的原理是:动态添加一个<script>标签,而script标签的src属性是没有跨域的限制的。
JSONP即JSON with Padding。由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源。如果要进行跨域请求, 我们可以通过使用html的script标记来进行跨域请求,并在响应中返回要执行的script代码,其中可以直接使用JSON传递javascript对象。 这种跨域的通讯方式称为JSONP。
<script>
function 回调函数名(data数据){ 。。。。 }
</script>
<script src="http://....jsp?callback=回调函数名"></script>
15.2 优缺点
15.2.1 优点
不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都 可以运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。
15.2.2 缺点
它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
16 CSS
16.1引入的方式
-
link
-
@import
16.2他们的区别
-
link可以用js修改,@import不可以
-
link比@import先载入
-
@import只能引入css
-
link兼容性高
16.3 初始化CSS的作用以及好处
因为浏览器的品种很多,每个浏览器的默认样式也是不同的,所以定义一套初始化css可以使各浏览器的默认样式统一。以便项目在不同浏览器上的效果是一致的
17 HTM4和HTML5的区别
17.1 格式
如果是<!DOCTYPE html>就是html5,其它的就是html4了,这是一个格式上的区别
17.2 起源
HTML4是1999年出来的,HTML5还在持续发展变化中....
HTML5 是 W3C 与 WHATWG 合作的结果。W3C 指 World Wide Web Consortium,万维网联盟。WHATWG 指 Web Hypertext Application Technology Working Group。WHATWG 致力于 web 表单和应用程序,而 W3C 专注于 XHTML 2.0。在 2006 年,双方决定进行合作,来创建一个新版本的 HTML。 为 HTML5 建立的一些规则
-
新特性应该基于 HTML、CSS、DOM 以及 JavaScript。
-
减少对外部插件的需求(比如 Flash)
-
更优秀的错误处理
-
更多取代脚本的标记
-
HTML5 应该独立于设备
-
开发进程应对公众透明
17.3 新特性
-
HTML5支持了视频的标签
-
HTML5支持了音频的标签
-
用于绘画的 canvas 元素
-
用于媒介回放的 video 和 audio 元素
-
对本地离线存储的更好的支持
-
新的特殊内容元素,比如 article、footer、header、nav、section
-
新的表单控件,比如 calendar、date、time、email、url、search
18 浏览器兼容性
世界上没有任何一个浏览器是一样的,同样的代码在不一样的浏览器上运行就存在兼容性问题。
不同浏览器其内核亦不尽相同,相同内核的版本不同,相同版本的内核浏览器品牌不一样,各种运行平台还存在差异、屏幕分辨率不一样,大小不一样,比例不一样。兼容性主要可以分类为:
-
CSS兼容
-
JavaScript兼容
-
HTML兼容
##
18.1 CSS设置
1,div的垂直居中问题: vertical-align:middle;
将行距增加到和整个DIV一样高: line-height:200px; 然后插入文字,就垂直居中了。 缺点是要控制内容不要换行
2,margin加倍的问题
设置为float的div在ie下设置的margin会加倍。这是一个ie6都存在的bug。 解决方案:在这个div里面加上 display:inline;
3,浮动ie产生的双倍距离
#box{ float:left; width:100px; margin:0 0 0 100px; /*这种情况之下IE会产生200px的距离, */ display:inline; /使浮动忽略/}
block与inline两个元素: block元素的特点:总是在新行上开始,高度、宽度、行高、边距都可以控制(块元素); Inline 元素的特点:和其他元素在同一行上,不可控制(内嵌元素)。
4,IE与宽度和高度的问题
IE 不认得min-这个定义,但实际上它把正常的width和height当作有min的情况来使。这样问题就大了,如果只用宽度和高度,正常的浏览器里这两个值就不会变,如果只用min-width和min-height的话,IE下面根本等于没有设置宽度和高度。 比如要设置背景图片,这个宽度是比较重要的。
要解决这个问题,可以这样:
box{ width: 80px; height: 35px;} html>body #box{ width: auto; height: auto; min-width: 80px; min-height: 35px;}
5,页面的最小宽度
min -width是个非常方便的CSS命令,它可以指定元素最小也不能小于某个宽度,这样就能保证排版一直正确。
但IE不认得这个,而它实际上把width当做最小宽度来使。为了让这一命令在IE上也能用,可以把一个<div> 放到 <body> 标签下,然后为div指定一个类,然后CSS这样设计:
#container{ min-width: 600px; width:expression(document.body.clientWidth < 600? "600px": "auto" );}
第一个min-width是正常的;但第2行的width使用了Javascript,这只有IE才认得,这也会让你的HTML文档不太正规。它实际上通过Javascript的判断来实现最小宽度。
6,DIV浮动IE文本产生3象素的bug 左边对象浮动,右边采用外补丁的左边距来定位,右边对象内的文本会离左边有3px的间距.
<style type="text/css">
#box{ float:left; width:800px;background-color: #000066;//可以优化为#006;}
#left{ float:left; width:50%;background-color: #006600;//可以优化为#060;}
#right{ width:50%;}
*html #left{ margin-right:-3px; //这句是关键}
</style>
<div id="box">
<div id="left"> </div>
<div id="right"> </div>
</div>
7,IE捉迷藏的问题
当div应用复杂的时候每个栏中又有一些链接,这个时候容易发生捉迷藏的问题。 有些内容显示不出来,当鼠标选择这个区域时发现内容确实在页面。
解决办法:对#layout使用line-height属性或者给#layout使用固定高和宽。页面结构尽量简单。
8,float的div闭合;清除浮动;自适应高度
实例1
<style type="text/css">
.float_a,.float_b,.float_c { float:left; }
.clear { clear:both; }
</style>
<div class="float_a">内容1</div>
<div class="float_b">内容2</div>
<div class="clear"></div>
<div class="float_c">内容3</div>
实例2
<style type="text/css">
.float_a,.float_b { float:left; }
.fl_l { float:left;}
.fl_r { float:right;}
.clear:after{ content: "."; display: block; height: 0; clear: both; visibility: hidden; }
.clear { zoom: 1; }
</style>
<div class="clear aa">
<div class="float_a fl_l"><div class="float_a fl_r">这是内容</div></div>
</div>
作为外部 wrapper 的 div 不要定死高度,为了让高度能自动适应,要在wrapper里面加上overflow:hidden; 当包含float的 box的时候,高度自动适应在IE下无效,这时候应该触发IE的layout私有属性(万恶的IE啊!)用zoom:1;可以做到,这样就达到了兼容。
例如某一个wrapper如下定义: .colwrapper{ overflow:hidden; zoom:1; margin:5px auto;}
9,高度不适应
高度不适应是当内层对象的高度发生变化时外层高度不能自动进行调节,特别是当内层对象使用margin 或padding 时。 例:
<style type="text/css">
#box {background-color:#eee; }
#box p {margin:20px 0; text-align:center;//原样式margin-top:20px; margin-bottom:20px; }
</style>
<div id="box">
<p>p对象中的内容</p>
</div>
解决方法:在P对象上下各加2个空的div对象CSS代码:.1{height:0px;overflow:hidden;}或者为div加上 border属性。
10,IE6下为什么图片下有空隙产生
解决这个BUG的方法也有很多,可以是改变html的排版,或者设置img 为display:block 或者设置vertical-align 属性为 vertical-align:top | bottom |middle |text-bottom 都可以解决。
13,如何对齐文本与文本输入框
加上 vertical-align:middle;
<style type="text/css">
<!-- input { width:200px; height:30px; border:1px solid red; vertical-align:middle;
//垂直方向样式是重点!} -->
</style>
14,web标准中定义id与class有什么区别吗
-
web标准中是不容许重复id的,比如 div id="aa" 不容许重复2次,而class 定义的是类,理论上可以无限重复,这样需要多次引用的定义便可以使用他;
-
属性的优先级问题 id 的优先级要高于class,看上面的例子三.方便JS等客户端脚本,如果在页面中要对某个对象进行脚本操作,那么可以给他定义一个id,否则只能利用遍历页面元素加上指定特定属性来找到它,这是相对浪费时间资源,远远不如一个id来得简单。
15,li中内容超过长度后以省略号显示的方法 (此方法适用与IE与OP浏览器)
<style type="text/css">
<!-- li { width:200px; white-space:nowrap; text-overflow:ellipsis; -o-text-overflow:ellipsis; overflow: hidden; } -->
</style>
16,eb标准中IE无法设置滚动条颜色了
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "网址">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<style type="text/css">
<!-- html { scrollbar-face-color:#f6f6f6; scrollbar-highlight-color:#fff; scrollbar-shadow-color:#eeeeee; scrollbar-3dlight-color:#eeeeee; scrollbar-arrow-color:#000; scrollbar-track-color:#fff; scrollbar-darkshadow-color:#fff; } -->
</style>
17, 为什么无法定义1px左右高度的容器
IE6下这个问题是因为默认的行高造成的。解决的方法也有很多,例如:overflow:hidden | zoom:0.08 | line-height:1px 。
18,怎么样才能让层显示在Flash之上呢
解决的办法是给Flash设置透明 <param name="wmode" value="transparent" />
19,怎样使一个层垂直居中于浏览器中
这里我们使用百分比绝对定位,与外补丁负值的方法,负值的大小为其自身宽度高度除以二
18.2 javascript兼容
1,关于获取行外样式 currentStyle 和 getComputedStyle 出现的兼容性问题。
js通过style不可以获取行外样式,当我们需要获取行外样式时: 我们一般通过这两个方法获取行外样式:
(1)IE下: currentStyle
(2)Chrome,FF下: getComputedStyle(oDiv,false) 兼容两个浏览器的写法:
if(oDiv.currentStyle){
alert(oDiv.currentStyle.width);
}else{
alert(getComputedStyle(oDiv,false).width);
}
//*注:在解决很多兼容性写法时,都是用if..else..
封装一个获取行外样式的函数:(兼容所有浏览器,包括低版本IE6,7)
funtion getStyle(obj,name){
if(obj.currentStyle){
//IE
return obj.currentStyle[name];
}else{
//Chrom,FF
return getComputedStyle(obj,false)[name];
}
}
//调用:getStyle(oDiv,'width');
2,用“索引”获取字符串每一项出现的兼容性问题
对于字符串也有类似于 数组 这样的通过 下标索引 获取每一项的值,
var str="abcde";
aletr(str[1]);
//但是低版本的浏览器IE6,7不兼容
//兼容方法:str.charAt(i) //全部浏览器都兼容
var str="abcde";
for(var i=0;i<str.length;i++){
alert(str.charAt(i)); //放回字符串中的每一项
}
3,DOM中 childNodes 获取子节点出现的兼容性问题
childNodes:获取子节点,
-
IE6-8:获取的是元素节点,正常
-
高版本浏览器:但是会包含文本节点和元素节点(不正常)
解决方法: 使用nodeType:节点的类型,并作出判断
-
nodeType=3-->文本节点
-
nodeTyPE=1-->元素节点
例: 获取ul里所有的子节点,让所有的子节点背景色变成红色
获取元素子节点兼容的方法:
var oUl=document.getElementById('ul');
for(var i=0;i<oUl.childNodes.length;i++){
if(oUl.childNodes[i].nodeType==1){
oUl.childNodes[i].style.background='red';
}
}
注:上面childNodes为我们带来的困扰完全可以有children属性来代替。 children属性:只获取元素节点,不获取文本节点,兼容所有的浏览器, 比上面的好用所以我们一般获取子节点时,最好用children属性。
var oUl=document.getElementById('ul');
oUl.children.style.background="red";
4,关于使用 firstChild,lastChild 等,获取第一个/最后一个元素节点时产生的问题
-
IE6-8下: firstChild,lastChild,nextSibling,previousSibling,获取第一个元素节点(高版本浏览器IE9+,FF,Chrome不兼容,其获取的空白文本节点)
-
高版本浏览器下: firstElementChild,lastElementChild,nextElementSibling,previousElementSibling(低版本浏览器IE6-8不兼容)
兼容写法: 找到ul的第一个元素节点,并将其背景色变成红色
var oUl=document.getElementById('ul');
if(oUl.firstElementChild){
//高版本浏览器
oUl.firstElementChild.style.background='red';
}else{
//IE6-8
oUl.firstChild.style.background='red';
}
5,关于使用 event对象,出现的兼容性问题
(1)获取鼠标位置
IE/Chrom: event.clientX;event.clientY FF/IE9以上/Chrom: 传参ev--> ev.clientX;ev.clientY
(2)获取event对象兼容性写法:
var oEvent==ev||event;
document.oncilck=function(ev){
var oEvent==ev||event;
if(oEvent){
alert(oEvent.clientX);
}
}
6,关于为一个元素绑定两个相同事件:attachEvent/attachEventLister 出现的兼容问题。
事件绑定:(不兼容需要两个结合做兼容if..else..)
-
IE8以下用: attachEvent('事件名',fn);
-
FF,Chrome,IE9-10用: attachEventLister('事件名',fn,false);
多事件绑定封装成一个兼容函数:
function myAddEvent(obj,ev,fn){
if(obj.attachEvent){
//IE8以下
obj.attachEvent('on'+ev,fn);
}else{
//FF,Chrome,IE9-10
obj.attachEventLister(ev,fn,false);
}
}
myAddEvent(oBtn,'click',function(){
alert(a);
});
myAddEvent(oBtn,'click',function(){
alert(b);
});
7,关于获取滚动条距离而出现的问题
当我们获取滚动条滚动距离时:
-
IE,Chrome: document.body.scrollTop
-
FF: document.documentElement.scrollTop 兼容处理:
var scrollTop=document.documentElement.scrollTop||document.body.scrollTop
19 前端页面优化
19.1 html
-
加载顺序:css放head里面(用户看到顺畅页面),js放尾部(会阻塞dom渲染,且dom树没搭建好时,js里面的dom操作会有问题)
-
减少页面请求:合并img,合并css,避免使用@import方式引入css文件
-
减少文件大小:主要减少img文件大小,选用合适的格式并且用工具进行压缩(ImageOptim,ImageAlpha,JPEGmini),删除不必要的标签
19.2 css
-
选择器:越简单越短越好,同样的样式进行选择器合并
-
css值缩写:margin等,值为0的省略单位,
font:normal small-caps bold 14px/1.5em '宋体',arial,verdana; 等价于: font-style:normal; font-variant:small-caps; font-weight:bold; font-size:14px; line-height:1.5em; font-family:'宋体',arial,verdana;
-
减少文件大小:YUI Compressor,cssmin
-
少用耗性能的属性:expresion,border-radius,filter,box-shadow,gradients等
-
图片设置宽高,不要缩放,减少浏览器的回流和重绘。
-
所有表现用css实现
-
模块化
-
命名规范、语义化
-
尽量减少hack
由于不同厂商的流览器或某浏览器的不同版本(如IE6-IE11,Firefox/Safari/Opera/Chrome等),对CSS的支持、解析不一样,导致在不同浏览器的环境中呈现出不一致的页面展现效果。这时,我们为了获得统一的页面效果,就需要针对不同的浏览器或不同版本写特定的CSS样式,我们把这个针对不同的浏览器/不同版本写相应的CSS code的过程,叫做CSS hack!
19.3 javascript
-
页面懒加载
-
通过委托机制等减少dom操作
-
尽量减少对象
20 事件冒泡和事件捕获
20.1 事件捕获
事件捕获指的是从document到触发事件的那个节点,即自上而下的去触发事件
20.2 事件冒泡
事件冒泡是自下而上的去触发事件
HTML结构:
<div id="parent">
<div id="child" class="child"></div>
</div>
绑定事件:
document.getElementById("parent").addEventListener("click",function(e) {
alert("parent事件被触发,"+this.id);
})
document.getElementById("child").addEventListener("click",function(e)
{
alert("child事件被触发,"+this.id)
})
结果:
child事件被触发,child parent事件被触发,parent
结论:先child,然后parent。事件的触发顺序自内向外,这就是事件冒泡。
20.3 事件捕获
改变绑定事件的第三个参数的值为true
document.getElementById("parent").addEventListener("click",function(e){
alert("parent事件被触发,"+e.target.id);
},true)
document.getElementById("child").addEventListener("click",function(e){ alert("child事件被触发,"+e.target.id)
},true)
结果:
parent事件被触发,parent child事件被触发,child
结论:先parent,然后child。事件触发顺序变更为自外向内,这就是事件捕获。
21 响应式布局
响应式网页设计就是一个网站能够兼容多个终端-而不是为每个终端做一个特定的版本。
21.1 四个步骤
21.1.1 布局及设置meta标签
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="HandheldFriendly" content="true">
user-scalable属性能够解决ipad切换横屏之后触摸才能回到具体尺寸的问题。
21.1.2 设置样式media query
通过媒体查询来设置样式media query,media query 是响应式设计的核心,它能够和浏览器进行沟通,告诉浏览器页面如何呈现,假如一个终端的分辨率小于980px,那么可以这样写。
@media screen and (max-width:980px){ #head { … } #content { … } #footer { … } }这里面的样式会覆盖掉之前所定义的样式。
21.1.3 设置多种视图宽度
假如我们要兼容ipad和iphone视图,我们可以这样设置:
/**ipad**/ @media only screen and (min-width:768px)and(max-width:1024px){} /**iphone**/ @media only screen and (width:320px)and (width:768px){}
21.1.4 字体设置
开发人员用到的字体单位大部分都是像素,虽然像素在普通网站上是Ok的,但是我们仍然需要响应式字体。一个响应式的字体应关联它的父容器的宽度,这样才能适应客户端屏幕。
css3引入了新的单位叫做rem,和em类似但对于Html元素,rem更方便使用。 rem是相对于根元素的,不要忘记重置根元素字体大小:
html{font-size:100%;} 完成后,你可以定义响应式字体: @media (min-width:640px){body{font-size:1rem;}} @media (min-width:960px){body{font-size:1.2rem;}} @media (min-width:1200px){body{font-size:1.5rem;}}
21.2 注意的问题
21.2.1 宽度使用百分比
#head{width:100%;} #content{width:50%;}
21.2.2 图片处理
在html页面中的图片,比如文章里插入的图片我们都可以通过css样式max-width来进行控制图片的最大宽度,如:
#wrap img{
max-width:100%;
height:auto;
}
如此设置后ID为wrap内的图片会根据wrap的宽度改变已达到等宽扩充,height为auto的设置是为了保证图片原始的高宽比例,以至于图片不会失真。
除了img标签的图片外我们经常会遇到背景图片,比如logo为背景图片:
#log a{display:block;
width:100%;
height:40px;
text-indent:55rem;
background-img:url(logo.png);
background-repeat:no-repeat;
background-size:100% 100%;
}
background-size是css3的新属性,用于设置背景图片的大小,有两个可选值,
第1个值用于指定背景图的width,
第2个值用于指定背景图的height,如果只指定一个值,那么另一个值默认为auto。
-
background-size:cover; 等比扩展图片来填满元素
-
background-size:contain; 等比缩小图片来适应元素的尺寸
21.3 总结
移动端优先,交互和设计以移动端为主,pc则作为移动端的扩展,一个页面需要兼容不同终端,那么有两个关键点是我们需要去做到响应式的:响应式布局和响应式内容。
22 H5新特性
22.1 新的Doctype
尽管使用<!DOCTYPE html>,即使浏览器不懂这句话也会按照标准模式去渲染
22.2 Figure元素
用figure和figcaption来语义化地表示带标题的图片
<figure>
<img src=”path/to/image” alt=”About image” />
<figcaption>
<p>This is an image of something interesting. </p>
</figcaption>
</figure>
22.3 重新定义的small
<small>已经被重新定义了,现在被用来表示小的排版,如网站底部的版权声明
22.4 去掉link和script标签里面的type属性
22.5 加/不加 括号
HTML5没有严格的要求属性必须加引号,闭合不闭合,但是建议加上引号和闭合标签
22.6 让你的内容可编辑,只需要加一个contenteditable属性
22.7 Email Inputs
如果我们给Input的type设置为email,浏览器就会验证这个输入是否是email类型,当然不能只依赖前端的校验,后端也得有相应的校验
22.8 Placeholders
这个input属性的意义就是不必通过javascript来做placeholder的效果了
22.9 Local Storage
使用Local Storage可以永久存储大的数据片段在客户端(除非主动删除),目前大部分浏览器已经支持,在使用之前可以检测一下window.localStorage是否存在
22.10 语义化的header和footer
22.11 更多的HTML5表单特性
22.12 IE和HTML5
默认的,HTML5新元素被以inline的方式渲染,不过可以通过下面这种方式让 其以block方式渲染
header, footer, article, section, nav, menu, hgroup {
display: block;
}
不幸的是IE会忽略这些样式,可以像下面这样fix:
document.createElement(”article”);
document.createElement(”footer”);
document.createElement(”header”);
document.createElement(”hgroup”);
document.createElement(”nav”);
document.createElement(”menu”);
22.13 hgroup
一般在header里面用来将一组标题组合在一起,如
<header>
<hgroup>
<h1> Recall Fan Page </h1>
<h2> Only for people who want the memory of a lifetime. </h2>
</hgroup>
</header>
22.14 Required属性
required属性定义了一个input是否是必须的,你可以像下面这样声明
<input type=”text” name=”someInput” required>
或者
<input type=”text” name=”someInput” required=”required”>
22.15 Autofocus属性
正如它的词义,就是聚焦到输入框里面
<input type=”text” name=”someInput” placeholder=”Douglas Quaid” required autofocus>
22.16 Audio支持
HTML5提供了audio标签,你不需要再按照第三方插件来渲染音频,大多数现代浏览器提供了对于HTML5 Audio的支持,不过目前仍旧需要提供一些兼容处理,如
<audio autoplay=”autoplay” controls=”controls”>
<source src=”file.ogg” /><!–FF–>
<source src=”file.mp3″ /><!–Webkit–>
<a href=”file.mp3″>Download this file.</a>
</audio>
22.17 Video支持
和Audio很像,video标签提供了对于video的支持,由于HTML5文档并没有给video指定一个特定的编码,所以浏 览器去决定要支持哪些编码,导致了很多不一致。Safari和IE支持H.264编码的格式,Firefox和Opera支持Theora和Vorbis 编码的格式,当使用HTML5 video的时候,你必须都提供:
<video controls preload>
<source src=”cohagenPhoneCall.ogv” type=”video/ogg; codecs=’vorbis, theora’” />
<source src=”cohagenPhoneCall.mp4″ type=”video/mp4; ’codecs=’avc1.42E01E, mp4a.40.2′” />
<p> Your browser is old. <a href=”cohagenPhoneCall.mp4″>Download this video instead.</a> </p>
</video>
22.18 预加载视频
preload属性就像它的字面意思那么简单,你需要决定是否需要在页面加载的时候去预加载视频
<video preload>
22.19 显示视频控制
<video preload controls>
22.20 正则表达式
由于pattern属性,我们可以在你的markup里面直接使用正则表达式了
<form action=”" method=”post”>
<label for=”username”>Create a Username: </label>
<input type=”text” name=”username” id=”username” placeholder=”4 <> 10″ pattern=”[A-Za-z]{4,10}” autofocus required>
<button type=”submit”>Go </button>
</form>
22.21 检测属性支持
除了Modernizr之外我们还可以通过javascript简单地检测一些属性是否支持,如:
<script>
if (!’pattern’ in document.createElement(’input’) ) {
// do client/server side validation
}
</script>
22.22 Mark元素
把mark元素看做是高亮的作用,当我选择一段文字的时候,javascript对于HTML的markup效果应该是这样的:
<h3> Search Results </h3>
<p> They were interrupted, just after Quato said, <mark>”Open your Mind”</mark>. </p>
22.23 什么时候用div
HTML5已经引入了这么多元素,那么div我们还要用吗?div你可以在没有更好的元素的时候去用。
22.24. 哪些不是HTML5
-
SVG
-
CSS3
-
Geolocation
-
Client Storage
-
Web Sockets
22.25 Data属性
<div id=”myDiv” data-custom-attr=”My Value”> Bla Bla </div>
CSS中使用:
<style>
h1:hover:after {
content: attr(data-hover-response);
color: black;
position: absolute;
left: 0;
}
</style>
<h1 data-hover-response=”I Said Don’t Touch Me!”> Don’t Touch Me </h1>
22.26 Output元素
output元素用来显示计算结果,也有一个和label一样的for属性
22.27 用Range Input来创建滑块
HTML5引用的range类型可以创建滑块,它接受min, max, step和value属性 可以使用css的:before和:after来显示min和max的值
<input type=”range” name=”range” min=”0″ max=”10″ step=”1″ value=”">
<script>
input[type=range]:before { content: attr(min); padding-right: 5px; }
input[type=range]:after { content: attr(max); padding-left: 5px;}
</script>
23 xhtml和html之间的区别
23.1 功能上的差别
XHTML可兼容各大浏览器、手机以及PDA,并且浏览器也能快速正确地编译网页
23.2 书写习惯的差别
23.2.1 标签必须小写
错误:<Head></Head><Body></Body> 正确:<head></head><body></body>
23.2.2 标签必须成双成对
错误:大家好<p>我是muki 正确:<p>大家好</p><p>我是muki</p>
23.2.3 标签顺序必须正确
错误:<div><h1>大家好</div></h1> 正确:<div><h1>大家好</h1></div>
23.2.4 所有属性都必须使用双引号
错误:<div style=font-size:11px>hello</div> 正确:<div style="font-size:11px">hello</div
23.2.5 不允许使用target="_blank"
错误:<a href="http://blog.mukispace.com" target="_blank">MUKI space</a> 正确:<a href="http://blog.mukispace.com" rel="external">MUKI space</a>
24 回流 重绘
24.1 概念
页面的显示过程的几个阶段:
-
生成DOM树(包括display:none的节点)
-
在DOM树的基础上根据节点的集合属性(margin,padding,width,height等)生成render树(不包括display:none,head节点,但是包括visibility:hidden的节点)
-
在render树的基础上继续渲染颜色背景色等样式
回流:当render树的一部分或者全部因为大小边距等问题发生改变而需要重建的过程。
重绘:当诸如颜色背景等不会引起页面布局变化,而只需要重新渲染的过程。
24.2 什么会引起回流
-
页面渲染初始化
-
DOM结构变化,比如删除了某个节点;骨头都被打断了,肯定比抽脂更严重,所以会引发回流
-
render树变化,比如减少了padding;也就是进行抽脂手术
-
窗口resize事件触发
-
获取某些属性,引发回流 很多浏览器会对回流做优化,他会等到足够数量的变化发生,在做一次批处理回流。 但是除了render树的直接变化。 当获取一些属性时,浏览器为了获得正确的值也会触发回流。这样就使得浏览器的优化失效了,这些属性包括以下
1. offsetTop, offsetLeft, offsetWidth, offsetHeight 2. scrollTop/Left/Width/Height 3. clientTop/Left/Width/Height 4. width,height 5. 调用了getComputedStyle(), 或者 IE的 currentStyle
var s = document.body.style;
s.padding = "2px"; // 回流+重绘
s.border = "1px solid red"; // 再一次 回流+重绘
s.color = "blue"; // 再一次重绘
s.backgroundColor = "#ccc"; // 再一次 重绘
s.fontSize = "14px"; // 再一次 回流+重绘
// 添加node,再一次 回流+重绘
document.body.appendChild(document.createTextNode('abc!'));
24.3 减少回流
-
避免逐项更改样式。最好一次性更改style属性,或者将样式列表定义为class并一次性更改class属性。
-
避免循环操作DOM。创建一个documentFragment或div,在它上面应用所有DOM操作,最后再把它添加到window.document。
-
避免多次读取offsetLeft等属性。无法避免则将它们缓存到变量。
-
将复杂的元素绝对定位或固定定位,使它脱离文档流。否则回流代价十分高
改变字体大小会引发回流 display:none和visibility:hidden会产生回流与重绘吗?
-
display:none指的是元素完全不陈列出来,不占据空间,涉及到了DOM结构,故产生reflow与repaint
-
visibility:hidden指的是元素不可见但存在,保留空间,不影响结构,故只产生repaint
25 闭包
25.1 变量作用域
变量的作用域分两种:全局变量和局部变量。
javascript语言的特别之处就在于:函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量
25.2 什么是闭包
function f1(){
var n=999;
function f2(){
alert(n); // 999
}
}
let hello = f1();
hello();
函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1就是不可见的。就是Javascript语言特有的"链式作用域"结构(chain scope),对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的。
f2可以读取f1中的局部变量,把f2作为返回值,f1就可以读取f2的内部变量了。f2函数,就是闭包。闭包就是能够读取其他函数内部变量的函数。
闭包可以简单理解成“定义在一个函数内部的函数。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
25.3 闭包的用途
闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中,不会在f1调用后被自动清除。
f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。
25.4 闭包的注意点
1,由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
2,闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
26 事件代理机制
26.1 概述
事件委托也是事件代理,就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
26.2 为什么用事件委托
前端代码:
<ul id="ul1">
<li>111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
js代码
window.onload = function(){
var oUl = document.getElementById("ul1");
var aLi = oUl.getElementsByTagName('li');
for(var i=0;i<aLi.length;i++){
aLi[i].onclick = function(){
alert(123);
}
}
}
在JavaScript中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断的与dom节点进行交互,访问dom的次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间,这就是为什么性能优化的主要思想之一就是减少DOM操作的原因;如果要用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样就能大大的减少与dom的交互次数,提高性能;
每个函数都是一个对象,是对象就会占用内存,对象越多,内存占用率就越大,自然性能就越差了,比如上面的100个li,就要占用100个内存空间,如果用事件委托,那么我们就可以只对它的父级(如果只有一个父级)这一个对象进行操作,这样我们就需要一个内存空间
26.3 事件委托
26.3.1 案例
window.onload = function(){
var oUl = document.getElementById("ul1");
oUl.onclick = function(ev){
var ev = ev || window.event;
var target = ev.target || ev.srcElement;
if(target.nodeName.toLowerCase() == 'li'){
alert(123);
alert(target.innerHTML);
}
}
}
26.3.2 案例
前端代码:
<div id="box">
<input type="button" id="add" value="添加" />
<input type="button" id="remove" value="删除" />
<input type="button" id="move" value="移动" />
<input type="button" id="select" value="选择" />
</div>
事件委托
window.onload = function(){
var oBox = document.getElementById("box");
oBox.onclick = function (ev) {
var ev = ev || window.event;
var target = ev.target || ev.srcElement;
if(target.nodeName.toLocaleLowerCase() == 'input'){
switch(target.id){
case 'add' :
alert('添加');
break;
case 'remove' :
alert('删除');
break;
case 'move' :
alert('移动');
break;
case 'select' :
alert('选择');
break;
}
}
}
}
27 JS原型、原型链
JavaScript是一种基于对象的语言,JavaScript中的所有对象,都具有prototype属性。prototype属性返回对象的所有属性和方法,所有 JavaScript 内部对象都有只读的 prototype 属性,可以向其原型中动态添加属性和方法,但该对象不能被赋予不同的原型。但是自定义的对象可以被赋给新的原型。
对象分为函数对象和普通对象,区分:凡是通过 new Function() 创建的对象都是函数对象,其他的都是普通对象。(Object ,Function 是JS自带的函数对象)
27.1 原型对象
函数对象其中一个属性:原型对象 prototype。普通对象是没有prototype属性,但有proto属性。 原型的作用就是给这个类的每一个对象都添加一个统一的方法,在原型中定义的方法和属性都是被所以实例对象所共享。
var person = function(name){
this.name = name
} ;
person.prototype.getName = function(){//通过person.prototype设置函数对象属性
return this.name;
}
var zxj= new person(‘zhangxiaojie’);
zxj.getName(); //zhangxiaojie //zxj继承上属性
27.2 原型链
proto:js创建对象的内置属性,用于指向创建它的函数对象的原型对象prototype。
当我们实例一个对象之后,调用它的内部方法,他的运行顺序是先找自身有没有该方法,如果没有就会通过proto属性想上层寻找,一直寻找到Object对象中,如果还没有才会报错null
p.proto----->Persion.proto---->object.proto----->null
28 屏幕适配
-
把页面做成100%自动,页面随屏幕的大小而变化,屏幕多大页面多大。
-
通过媒体查询来判断屏幕的大小,根据不同大小的屏幕加载不同样式
29 内存泄漏
29.1 内存问题
javascript具有自动垃圾回收机制,一旦数据不再使用,可以将其设为"null"来释放引用
29.2 循环引用
一个很简单的例子:一个DOM对象被一个Javascript对象引用,与此同时又引用同一个或其它的Javascript对象,这个DOM对象可能会引发内存泄露。这个DOM对象的引用将不会在脚本停止的时候被垃圾回收器回收。要想破坏循环引用,引用DOM元素的对象或DOM对象的引用需要被赋值为null。
29.3 闭包
在闭包中引入闭包外部的变量时,当闭包结束时此对象无法被垃圾回收(GC)
var a = function() {
var largeStr = new Array(1000000).join('x');
return function() {
return largeStr;
}
}();
29.4 dom泄露
当原有的COM被移除时,子结点引用没有被移除则无法回收。
29.5 定时器泄露
for (var i = 0; i < 90000; i++) {
var buggyObject = {
callAgain: function() {
var ref = this;
var val = setTimeout(function() {
ref.callAgain();
}, 90000);
}
}
buggyObject.callAgain();
//虽然你想回收但是timer还在
buggyObject = null;
}
29.6 调试内存
Chrome自带的内存调试工具可以很方便地查看内存使用情况和内存泄露: 在 Timeline -> Memory 点击record即可。
29.7 垃圾回收机制
说到内存管理,自然离不开JS中的垃圾回收机制,有两种策略来实现垃圾回收:标记清除 和 引用计数;
29.7.1 标记清除
垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记,然后,它会去掉环境中的变量的标记和被环境中的变量引用的变量的标记,此后,如果变量再被标记则表示此变量准备被删除。 2008年为止,IE,Firefox,opera,chrome,Safari的javascript都用使用了该方式。
29.7.2 引用计数
跟踪记录每个值被引用的次数,当声明一个变量并将一个引用类型的值赋给该变量时,这个值的引用次数就是1,如果这个值再被赋值给另一个变量,则引用次数加1。相反,如果一个变量脱离了该值的引用,则该值引用次数减1,当次数为0时,就会等待垃圾收集器的回收。
30 测试函数性能
function testFn(fn,param){
var start = new Date().getTime();
fn(param);//调用某个函数
var end = new Date().getTime();
console.log(fn.name+"耗时:"+(end - start)+"毫秒"); //IE不支持fn.name
}
31 promise
31.1 为什么使用promise
避免界面冻结
同步:假设你去了一家饭店,找个位置,叫来服务员,这个时候服务员对你说,对不起我是“同步”服务员,我要服务完这张桌子才能招呼你。那桌客人明明已经吃上了,你只是想要个菜单,这么小的动作,服务员却要你等到别人的一个大动作完成之后,才能再来招呼你,这个便是同步的问题:也就是“顺序交付的工作1234,必须按照1234的顺序完成”。
异步:则是将耗时很长的A交付的工作交给系统之后,就去继续做B交付的工作,。等到系统完成了前面的工作之后,再通过回调或者事件,继续做A剩下的工作。 AB工作的完成顺序,和交付他们的时间顺序无关,所以叫“异步”。
31.2 promise是什么
promise是一个对象,对象和函数的区别就是对象可以保存状态,函数不可以,promise并未剥夺函数return的能力,因此无需层层传递callback,进行回调获取数据,多个异步等待合并便于解决。
代码:
new Promise(
function (resolve, reject) {
// 一段耗时的异步操作
resolve('成功') // 数据处理完成
// reject('失败') // 数据处理出错
}
).then(
(res) => {console.log(res)}, // 成功
(err) => {console.log(err)} // 失败
)
resolve:将Promise对象的状态从“未完成”变为“成功”,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject:将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
31.3 三个状态
1、pending[待定]初始状态 2、fulfilled[实现]操作成功 3、rejected[被否决]操作失败
当promise状态发生改变,就会触发then()里的响应函数处理后续步骤;Promise对象的状态改变,只有两种可能:
-
从pending变为fulfilled
-
从pending变为rejected
实例1:
new Promise(resolve => {
setTimeout(() => {
resolve('hello')
}, 2000)
}).then(res => {
console.log(res)
})
实例2:
new Promise(resolve => {
setTimeout(() => {
resolve('hello')
}, 2000)
}).then(val => {
console.log(val) // 参数val = 'hello'
return new Promise(resolve => {
setTimeout(() => {
resolve('world')
}, 2000)
})
}).then(val => {
console.log(val) // 参数val = 'world'
})
32 js数组
-
slice
-
unshift
-
shift
-
reverse
-
forEach
-
every
-
some
-
map
-
filter
33 深拷贝、浅拷贝
深拷贝在计算机中开辟了一块内存地址用于存放复制的对象,而浅拷贝仅仅是指向被拷贝的内存地址,如果原地址中对象被改变了,那么浅拷贝出来的对象也会相应改变。