-
Notifications
You must be signed in to change notification settings - Fork 7
Description
浏览器常驻的5个线程是什么?
- GUI渲染线程
- JavaScript引擎线程
- 定时器触发线程setTimeout,setInterval
- http异步请求线程
- 事件触发线程
从输入一个Url到浏览器渲染显示页面,中间都发生了什么?
-
浏览器开启一个线程处理这个url请求,然后通过DNS服务将Url域名转换为IP地址。DNS的过程包括DNS缓存查询,递归查询和迭代查询,DNS服务器分为根服务器(root)、顶级域DNS服务器(.com, .org, .cn)、和权威DNS服务器(baidu.com, google.com等)。其中顶级域也称为一级域,权威DNS也称为二级域DNS。DNS查询细节参考这里。
-
拿到服务器IP之后,便开始建立TCP连接,通过三次握手(SYN, SYN|ACK, ACK)建立TCP连接。
-
TCP连接建立之后,浏览器便开始发送HTTPGet请求,请求位于服务器上的资源,如html、css、js、img等,当服务器返回状态200时,就表示请求成功。关于Http详情,可参考:这里。
-
客户端每下载一个资源,都要进行http请求,这样依次构建HTML DOM Tree,CSSOM Tree,Render Tree,然后执行layout和paint操作。其中js脚本的加载和执行会阻塞dom的加载(asyn和defer除外),因为脚本可能会修改dom结构。css一般不会操作dom,所以css的加载不会影响dom加载,但有可能影响js的加载和执行。所以最佳实践是csslink放在head标签内,script标签放在body标签的最底部。不过,现在浏览器一般使用了prefatch优化,即提前并行下载css,js等资源,但并不执行,因为执行顺序存在着依赖关系。
请谈谈你对雅虎军规和前端性能优化的理解?
- 减少http请求,合并图片(css sprites),合并css,js,但要考虑合并后文件的体积。
- 使用CDN (Content Deliver Network)
- 为文件头指定Expires或Cache-Control,使内容具有缓存性。区分静态内容和动态内容,避免以后不必要的http请求
- 避免空的src和href,特别是script、link、img、iframe标签
- 使用gzip来压缩文件
- css放在head标签内,js放在body标签底部
- 尽可能的使用Get来完成ajax请求
- 减少DOM元素个数
- favicon.icon要尽可能小且可缓存
- 配置Etags,(实体标签)用于判断浏览器中缓存内容和服务器中是否一致,比last-modified date更加灵活的机制。
- More On Yacent's Blog
谈谈requestAnimationFrame原理,以及你知道的其他前端动画方法
The window.requestAnimationFrame() method tells the browser that you wish to perform an animation and requests that the browser call a specified function to update an animation before the next repaint. The method takes as an argument a callback to be invoked before the repaint.
requestAnimationFrame(callback fn)的核心原理是__递归__,即在update函数内部递归调用requestAnimationFrame(update),从而完成动画。它是为浏览器专门设计的动画API,当窗口处于未激活状态时,动画会自动停止,降低了CPU开销。
其他实现动画的方法:CSS3 animation @Keyframes || CSS3 transition: all 1s ease-in-out 0.5s; || setInterval setTimeout draw() update() loop()模式 || jQuery 动画API || canvas 等等。
解释下闭包
闭包可以理解为函数中定义的函数,由于存在作用域链,内层函数可以访问外层函数的变量,那么内层函数就可以实时的对那个变量进行操作,而如果把这个内层函数当作返回值的话,那么外层函数的外部就可以突破作用域限制访问那个变量。
通俗的解释就是 function return function,就是由于作用域链的原因,内层函数可以访问外层函数中的变量,那个内层函数就是我们通常所说的闭包,它构成了函数内部和外部的桥梁。
闭包有以下两个作用:
- 访问函数内部的变量
- 可以使这些变量始终保存在内存中
闭包会使函数中的变量保存在内存当中,内存的消耗很大,所以我们不要滥用闭包,在适当的时候才去用
写一下快速排序
function quickSort(arr) {
if (Object.prototype.toString.call(arr) != "[object Array]") {
return;
}
if (arr.length <= 1) {
return arr;
}
var middle = Math.floor(arr.length / 2);
var pivot = arr.splice(middle, 1)[0];
var left = [];
var right = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] < pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat([pivot], quickSort(right));
}那再写一下二分搜索
function binarySearch(arr, target) {
if (Object.prototype.toString.call(arr) != "[object Array]") {
return;
}
// arr前提要是从小到大排列的数组
arr = quickSort(arr);
var bottom = 0;
var top = arr.length - 1;
var position;
while (bottom < top) {
var middle = Math.floor((bottom + top) / 2);
if (arr[middle] == target) {
position = middle;
console.log("Find target at position: " + position);
return position;
} else if (arr[middle] < target) {
bottom = middle + 1;
} else if (arr[middle] > target) {
top = middle;
}
}
return position;
}写一个fibonacci数列函数0, 1, 1, 2, 3....
var fibonacci = (function f(n) {
if (n === 0) return 0;
if (n === 1) return 1;
else {
return f(n - 2) + f(n - 1);
// or: return arguments.callee(n - 2) + arguments.callee(n - 1);
}
});
fibonacci(3);用查表法改进上述算法
好的,查表,查表,查表。。。
var f_result = [];
var fibonacci = (function fn(n) {
if (n == 0) return 0;
if (n == 1) return 1;
if (f_result[n]) {
return f_result[n];
} else {
f_result[n] = fn(n - 2) + fn(n - 1);
return f_result[n];
}
});实现一个函数clone,可以对JavaScript中的5种主要的数据类型(包括Number、String、Object、Array、Boolean)进行值复制
// method 1
function clone(obj) {
var result;
if (Object.prototype.toString.call(obj) == "[object Array]") {
result = [];
for (var i = 0; i < obj.length; i++) {
result[i] = clone(obj[i]);
}
return result;
} else if (Object.prototype.toString.call(obj) == "[object Object]") {
result = {};
for (var key in obj) {
result[key] = clone(obj[key]);
}
return result;
} else {
return obj;
}
}
// method 2 (for object or array)
Object.prototype.clone = function() {
var o = (this.constructor == Array) ? [] : {};
for (var i in this) {
o[i] = (typeof(this[i]) == "object") ? this[i].clone() : this[i];
}
return o;
}数组去重
Array.prototype.unique = function() {
var hash = {};
var result = [];
for(var i = 0; i < this.length; i++) {
var t = this[i];
if (!hash[t]) {
result.push(t);
hash[t] = true;
}
}
return result;
}
var a = [1, 1, 2, 2, 3, 4, 4, 5, 7, 9, 9].unique();
a;自定义console.log方法,使得可以传入多个参数,并且自动加上app前缀
function log(){
var args = Array.prototype.slice.call(arguments); //为了使用unshift数组方法,将argument转化为真正的数组
args.unshift('(app)');
console.log.apply(console, args);
};
log("zhoujihao", "yes!")请封装cookie操作方法
var CookieUtil = {
// 设置cookie的名字,值,有效天数,路径,域,以及安全标志
set: function(name, value, days, path, domain, secure) {
var cookieText = encodeURIComponent(name) + "=" + encodeURIComponent(value);
if (days) {
var exp = new Date();
exp.setTime(exp.getTime() + days * 24 * 60 * 60 * 1000);
cookieText += "; expires=" + exp.toGMTString();
}
if (path) {cookieText += "; path=" + path;}
if (domain) {cookieText += "; domain=" + domain;}
if (secure) {cookieText += "; secure";}
document.cookie = cookieText;
},
// 通过名字获取cookie的值
get: function(name) {
var cookieName = encodeURIComponent(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 = document.cookie.substring(cookieStart + cookieName.length, cookieEnd);
}
return cookieValue;
},
unset: function(name, path, domain, secure) {
this.set(name, "", 0, path, domain, secure);
}
};Cookie和Session
cookie的中文意思是小甜饼,可以看出cookie的确非常小,一般存放的数据量只有4k左右。它的作用是标志用户信息,让服务器了解用户的身份。它的原理图如下所示:
即服务器在用户第一次请求之后,会设置一些cookie信息如sessionID等,然后发送给客户端,客户端每次请求时就会加上相应的cookie信息,这样服务器就了解是哪个用户在访问了。
session意思是会话,是一种存储在服务端的特定数据结构。因为http是一种无状态的协议,所以服务端就要用session的机制记录用户的状态,典型的场景如购物车应用,服务端要为特定的用户创建了特定的SessionID,用于标识这个用户,并且跟踪用户,这样才知道购物车里面有什么东西。Session存放在服务端,可以是内存,数据库或者是文件。
移动端300ms点击延迟
问题来源:safari设计的双击缩放特性
解决方案一:禁用缩放
<meta name="viewport" content="user-scalable=no">
<meta name="viewport" content="initial-scale=1,maximum-scale=1">表明这个页面是不可缩放的,那双击缩放的功能就没有意义了,此时浏览器可以禁用默认的双击缩放行为并且去掉300ms的点击延迟。
这个方案有一个缺点,就是必须通过完全禁用缩放来达到去掉点击延迟的目的,然而完全禁用缩放并不是我们的初衷,我们只是想禁掉默认的双击缩放行为,这样就不用等待300ms来判断当前操作是否是双击。
方案二:更改默认的视口宽度
<meta name="viewport" content="width=device-width">方案三:指针事件
跟300ms点击延迟相关的,是touch-action这个CSS属性。这个属性指定了相应元素上能够触发的用户代理(也就是浏览器)的默认行为。如果将该属性值设置为touch-action: none,那么表示在该元素上的操作不会触发用户代理的任何默认行为,就无需进行300ms的延迟判断。
方案四:现成工具
FastClick,HandJS,Polymer
inline vs block vs inline-block
Inline elements:
- respect left & right margins and padding, but not top & bottom
- cannot have a width and height set
- allow other elements to sit to their left and right.
Block elements:
- respect all of those
- force a line break after the block element
Inline-block elements:
- allow other elements to sit to their left and right
- respect top & bottom margins and padding
- respect height and width
Doctype作用?严格模式与混杂模式如何区分?它们有何差异?
声明叫做文件类型定义(DTD),声明的作用为了告诉浏览器该文件的类型。让浏览器解析器知道应该用哪个规范来解析文档。声明必须在 HTML 文档的第一行,这并不是一个 HTML 标签。严格模式:又称标准模式,是指浏览器按照 W3C 标准解析代码。
混杂模式:又称怪异模式或兼容模式,是指浏览器用自己的方式解析代码。
