题目总结

求工作Orz

1.
函数声明:

1
2
3
function count(a,b){
return a+b;
}

函数表达式:

1
var count = function(a,b){ return a+b;};

在后续的调用中,效果是没有差别的;但是他们的区别在于解析器对这两种定义读取的顺序不同;
解析器会事先读取函数声明,并在执行后续的代码之前使之可以使用,即使你把函数声明放在代码的末端;
而对于函数表达式,解析器只有在读到函数表达式所在那行的时候才执行

2.
absolute 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。
fixed 生成绝对定位的元素,相对于浏览器窗口进行定位。
relative 生成相对定位的元素,相对于其正常位置进行定位。
static 默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)

3.
BFC(block formatting context)中相邻的两个block-level的盒,上一个box的下边距会跟下一个box的上边距发生叠加,即两者取最大的,而不是相加;
当把元素的display属性设为inline-block,它们都位于IFC当中,所以不论水平还是竖直方向,都不会发生叠加;
当把元素的float属性设为left,它们都不在正常流中,更不在BFC中了,同样不论水平还是竖直方向,都不会发生叠加;
当一个容器既没有border又没有padding时,它的第一个子box的的margin也能跟它的上一个容器的margin发生叠加;
有padding(内边距)的时候,上一节的情况不发生;

4.
background-color:blue; /firefox/
background-color:red\9; /all ie/
background-color:yellow\0; /ie8/
+background-color:pink; /ie7/
_background-color:orange; /ie6/

5.
浏览器内核:

  • Trident(IE内核)
  • Gecko(Firefox内核)
  • Presto(Opera前内核) (已废弃)
  • Webkit(Safari内核,Chrome内核原型,开源)

6.
null只和undefined相等,接下来依次有number都转number,有boolean也都转number,有string都转string,对象互相不等,NaN互相不等就可以了

7.
当遮罩被点击时要自动关闭

1
2
3
4
$('.overlay').click(function(e){
if (e.target == e.currentTarget)
closeOverlay();
});

8.一个简单的图片轮播

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<div id="scrollbox">
<ul>
<li><img src="1.jpg" alt=""></li>
<li><img src="2.jpg" alt=""></li>
<li><img src="3.jpg" alt=""></li>
<li><img src="4.jpg" alt=""></li>
</ul>
</div>
#scrollbox{width:500px;height:240px;position:relative;overflow:hidden;margin:0 auto;border:1px solid #000;}
#scrollbox ul {width:900px;height:280px;position:absolute;padding:10px 0;}
#scrollbox li {float:left;position:relative;margin:0 10px;border:1px solid #000;}
function scrollBox(){
var first = $('#scrollbox ul li:first');
var width = -(first.outerWidth(true)) + 'px';
$('#scrollbox ul').animate({left:width},{
duration:200,
complete:function(){
$('#scrollbox ul').append(first).css("left","0");
}
});
};
$(document).ready(function(){
myScroll = setInterval(scrollBox,1500);
$('#scrollbox').hover(function(){
clearInterval(myScroll);
},function(){
myScroll = setInterval(scrollBox,1500);
}
);
})

9.
JavaScript是一门什么样的语言,它有哪些特点?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
+动态性:在javascript对象中,要为一个属性赋值,不必事先创建一个字段,只需要在使用的时候做赋值操作即可。
var obj=new Object();//定义一个对象
obj.name='blue';//动态创造属性
obj.sayHi=function(){ alert("hi")}; obj.sayHi();//动态创造方法
delete obj.name //动态删除属性
+弱类型:数据类型无需在声明时指定,解释器会根据上下文进行实例化。
+面向对象:在javascript中一切都是对象。同时体会map,filter的使用。
var array=[1,2,3,4,5];
var array2=array.map(function(item){
return item*2;
}); //运行结果:[2,4,6,8,10]
alert(array2)
var staff=[
{name:'abruzzi',age:24},
{name:'blue',age:26},
{name:'chris',age:25}
];
var att3=staff.map(function(item){
return item.name.toUpperCase();
})
alert(att3);['ABRUZZI','BLUE','CHRIS'];
var att3=staff.filter(function(item){
return item.age>24;
})
返回结果:
[
{name:'blue',age:26},
{name:'chris',age:25}
]
+解释与编译:javascript是解释性语言,可以随时的修改代码,无需编译,刷新页面即可重新解释,可以实时的看到程序的结果,但是每一次的解释,程序开销大。编译语言只是编译一次,但是丧失动态性。

10.
JavaScript的数据类型都有什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
基本数据类型:String,boolean,Number,Undefined, Null
引用数据类型:Object(Array,Date,RegExp,Function)
那么问题来了,如何判断某变量是否为数组数据类型?
方法一.判断其是否具有“数组性质”,如slice()方法。可自己给该变量定义slice方法,故有时会失效
方法二.obj instanceof Array 在某些IE版本中不正确
方法三.方法一二皆有漏洞,在ECMA Script5中定义了新方法Array.isArray(), 保证其兼容性,最好的方法如下:
if(typeof Array.isArray==="undefined")
{
Array.isArray = function(arg){
return Object.prototype.toString.call(arg)==="[object Array]"
};
}

11.
已知ID的Input输入框,希望获取这个输入框的输入值,怎么做?(不使用第三方框架)

1
document.getElementById(“ID”).value;

12.
希望获取到页面中所有的checkbox怎么做?(不使用第三方框架)

1
2
3
4
5
6
7
8
var domList = document.getElementsByTagName(‘input’)
var checkBoxList = [];//等价于var a = new Array();
var len = domList.length;  //缓存到局部变量
while (len--) {  //使用while的效率会比for循环更高
  if (domList[len].type == ‘checkbox’) {
  checkBoxList.push(domList[len]);
  }
}

13.
设置一个已知ID的DIV的html内容为xxxx,字体颜色设置为黑色(不使用第三方框架)

1
2
3
var dom = document.getElementById(“ID”);
dom.innerHTML = “xxxx”
dom.style.color = “#000”

14.
当一个DOM节点被点击时候,我们希望能够执行一个函数,应该怎么做?

1
2
3
4
5
6
7
8
+直接在DOM里绑定事件:<div onclick=”test()”></div>
+在JS里通过onclick绑定:xxx.onclick = test
+通过事件添加进行绑定:addEventListener(xxx, ‘click’, test)
那么问题来了,Javascript的事件流模型都有什么?
+“事件冒泡”:事件开始由最具体的元素接受,然后逐级向上传播
+“事件捕捉”:事件由最不具体的节点先接收,然后逐级向下,一直到最具体的
“DOM事件流”:三个阶段:事件捕捉,目标阶段,事件冒泡

如何阻止事件冒泡?
+什么是事件冒泡?
在一个对象上触发某类事件(比如单击onclick事件),如果此对象定义此事件的处理程序,那么此事件就会调用这个处理程序,如果没有定义此事件处理程序或者事件返回true,那么这个事件会向这个对象的父级对象传播,从里到外,直至它被处理(父级对象所有同类事件都将被激活),或者它到达了对象层次的最顶层,即document(有些浏览器是window).
+如何阻止?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Porschev---Jquery事件冒泡</title>
<script src="jquery-1.3.2-vsdoc.js"type="text/javascript"></script>
</head>
<body>
<form id="form1"runat="server">
<div id="divOne"onclick="alert('我是最外层');">
<div id="divTwo"onclick="alert('我是中间层!')">
<a id="hr_three"href="http://www.baidu.com"mce_href="http://www.baidu.com"onclick="alert('我是最里层!')">点击我</a>
</div>
</div>
</form>
</body>
</html>

比如这个页面,分为三层,divone是最外层,divtwo是中间层,hr_three是最里层,他们都有各自的click事件,最里层a标签还有href属性。
运行页面,点击”点击我”会依次弹出:我是最里层->我是中间层->我是最外层->然后再链接到百度,这就是事件冒泡,本来我只点击id为hr_three的标签,但是却执行了三个alert操作。
事件冒泡过程:hr_three->divtwo->divone,从最里层冒泡到最外层。
如何来阻止?
+event.stopPropagetion()

1
2
3
4
5
6
7
<script type="text/javascript">
$(function(){
$("#hr_three").click(function(event){
event.stopPropagetion();
});
});
</script>

再点击”点击我”,会弹出:我是最里层,然后链接到百度
+returnfalse;
如果头部加入的是以下代码

1
2
3
4
5
6
7
<script type="text/javascript">
$(function(){
$("#hr_three").click(function(event){
returnfalse;
});
});
</script>

再点击”点击我”,会弹出:我是最里层,但不会执行链接到百度页面

由此可以看出:
+event.stopPropagetion();
事件处理过程中,阻止了事件冒泡,但不会阻止默认行为(它就执行了超链接的跳转)
+returnfalse;
事件处理过程中,阻止了事件冒泡,也阻止了默认行为(比如刚才它就没有执行超链接的跳转)
+event.preventDefault();
如果把它放在头部A标签的click事件中,点击”点击我”
会发现它依次弹出:我是最里层->我是中间层->我是最外层,但最后没有跳到百度
它的作用是:事件处理过程中,不阻止事件冒泡,但阻止默认行为(它只执行所有弹框,却没有执行超链接跳转)

15.
什么是Ajax和JSON,它们的优缺点

1
2
3
4
5
6
7
8
9
10
11
Ajax是异步JavaScript和XML,用于在Web页面中实现异步数据交互。
+ 优点:
 可以使得页面不重载全部内容的情况下加载局部内容,降低数据传输量
 避免用户不断刷新或者跳转页面,提高用户体验
+ 缺点:
 对搜索引擎不友好(
 要实现ajax下的前后退功能成本较大
 可能造成请求数的增加
 跨域问题限制
JSON是一种轻量级的数据交换格式,ECMA的一个子集
+ 优点:轻量级、易于人的阅读和编写,便于机器(JavaScript)解析,支持复合数据类型(数组、对象、字符串、数字)

16.
看下列代码输出为何?解释原因。

1
2
3
var a;
alert(typeof a); // undefined
alert(b); // 报错

Undefined是一个只有一个值的数据类型,这个值就是“undefined”,在使用var声明变量但并未对其赋值进行初始化时,这个变量的值就是undefined。而b由于未声明将报错。注意未申明的变量和声明了未赋值的是不一样的。

1
2
var a = null;
alert(typeof a); //object

解释:null是一个只有一个值的数据类型,这个值就是null。表示一个空指针对象,所以用typeof检测会返回”object”。

17.
看下列代码,输出什么?解释原因
var undefined;
undefined == null; // true
1 == true; // true
2 == true; // false
0 == false; // true
0 == ‘’; // true
NaN == NaN; // false
[] == false; // true
[] == ![]; // true
undefined与null相等,但不恒等(===)
一个是number一个是string时,会尝试将string转换为number
尝试将boolean转换为number,0或1
尝试将Object转换成number或string,取决于另外一个对比量的类型
所以,对于0、空字符串的判断,建议使用 “===” 。“===”会先判断两边的值类型,类型不匹配时为false。
那么问题来了,看下面的代码,输出什么,foo的值为什么?
var foo = “11”+2-“1”;
console.log(foo);
console.log(typeof foo);
执行完后foo的值为111,foo的类型为number。

18.
var a = new Object();
a.value = 1;
b = a;
b.value = 2;
alert(a.value);//2

19.
已知数组var stringArray = [“This”, “is”, “Baidu”, “Campus”],Alert出”This is Baidu Campus”。

1
alert(stringArray.join(" "));

20.
已知有字符串foo=”get-element-by-id”,写一个function将其转化成驼峰表示法”getElementById”。

1
2
3
4
5
6
7
8
function combo(msg){
var arr=msg.split("-");
for(var i=1;i<arr.length;i++){
arr=arr.charAt(0).toUpperCase()+arr.substr(1,arr.length-1);
}
msg=arr.join("");
return msg;
}

21.
已知var numberArray = [3,6,2,4,1,5]; (考察基础API)

1) 实现对该数组的倒排,输出[5,1,4,2,6,3]

2) 实现对该数组的降序排列,输出[6,5,4,3,2,1]

1
2
3
4
5
var numberArray = [3,6,2,4,1,5];
numberArray.reverse(); // 5,1,4,2,6,3
numberArray.sort(function(a,b){ //6,5,4,3,2,1
return b-a;
})

22.
输出今天的日期,以YYYY-MM-DD的方式,比如今天是2014年9月26日,则输出2014-09-26

1
2
3
4
5
6
7
8
9
10
11
var d = new Date();
// 获取年,getFullYear()返回4位的数字
var year = d.getFullYear();
// 获取月,月份比较特殊,0是1月,11是12月
var month = d.getMonth() + 1;
// 变成两位
month = month < 10 ? '0' + month : month;
// 获取日
var day = d.getDate();
day = day < 10 ? '0' + day : day;
alert(year + '-' + month + '-' + day);

23.
将字符串”{$id}{$name}”中的{$id}替换成10,{$name}替换成Tony (使用正则表达式)

1
"<tr><td>{$id}</td><td>{$id}_{$name}</td></tr>".replace(/{\$id}/g, '10').replace(/{\$name}/g, ‘Tony');

24.
为了保证页面输出安全,我们经常需要对一些特殊的字符进行转义,请写一个函数escapeHtml,将<, >, &, “进行转义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function escapeHtml(str) {
return str.replace(/[<>”&]/g, function(match) {
switch (match) {
case "<”:
return "<”;
case ">”:
return ">”;
case "&”:
return "&”;
case "\””:
return ""”;
}
});
}

25.
foo = foo||bar ,这行代码是什么意思?为什么要这样写?

1
if(!foo) foo = bar; //如果foo存在,值不变,否则把bar的值赋给foo。

短路表达式:作为”&&”和”||”操作符的操作数表达式,这些表达式在进行求值时,只要最终的结果已经可以确定是真或假,求值过程便告终止,这称之为短路求值。

26.

1
2
3
4
5
6
var foo = 1;
function(){
console.log(foo);//undefined
var foo = 2;
console.log(foo);//2
}

等价于

1
2
3
4
5
6
7
var foo = 1;
function(){
var foo;
console.log(foo); //undefined
foo = 2;
console.log(foo); // 2;
}

函数声明与变量声明会被JavaScript引擎隐式地提升到当前作用域的顶部,但是只提升名称不会提升赋值部分。

27.
用js实现随机选取10–100之间的10个数字,存入一个数组,并排序。

1
2
3
4
5
6
7
8
9
var iArray = [];
funtion getRandom(istart, iend){
var iChoice = istart - iend +1;
return Math.floor(Math.random() * iChoice + istart;
}
for(var i=0; i<10; i++){
iArray.push(getRandom(10,100));
}
iArray.sort();

28.
把两个数组合并,并删除第二个元素。

1
2
3
4
var array1 = ['a','b','c'];
var bArray = ['d','e','f'];
var cArray = array1.concat(bArray);
cArray.splice(1,1);

arrayObject.splice(index,howmany,item1,…..,itemX)
//index 必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。
howmany 必需。要删除的项目数量。如果设置为 0,则不会删除项目。
item1, …, itemX 可选。向数组添加的新项目

29.
1)创建新节点
createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点
  2)添加、移除、替换、插入
appendChild() //添加
removeChild() //移除
replaceChild() //替换
insertBefore() //插入
  3)查找
getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的Name属性的值
getElementById() //通过元素Id,唯一性

30.
有这样一个URL:http://item.taobao.com/item.htm?a=1&b=2&c=&d=xxx&e,请写一段JS程序提取URL中的各个GET参数(参数名和参数个数不确定),将其按key-value形式返回到一个json结构中,如{a:'1‘, b:’2’, c:’’, d:’xxx’, e:undefined}。

1
2
3
4
5
6
7
8
9
function serilizeUrl(url) {
var result = {};
url = url.split("?")[1];
var map = url.split("&");
for(var i = 0, len = map.length; i < len; i++) {
result[map[i].split("=")[0]] = map[i].split("=")[1];
}
return result;
}

31.
正则表达式构造函数var reg=new RegExp(“xxx”)与正则表达字面量var reg=//有什么不同?匹配邮箱的正则表达式?

1
2
当使用RegExp()构造函数的时候,不仅需要转义引号(即\"表示"),并且还需要双反斜杠(即\\表示一个\)。使用正则表达字面量的效率更高。
  邮箱的正则匹配:var regMail = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/;

32.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for(var i=1;i<=3;i++){
setTimeout(function(){
console.log(i);
},0);
};
//4 4 4
for(var i=1;i<=3;i++){
setTimeout((function(a){ //改成立即执行函数
console.log(a);
})(i),0);
};
1 //输出
2
3

33.
写一个function,清除字符串前后的空格。(兼容所有浏览器)使用自带接口trim(),考虑兼容性:

1
2
3
4
5
6
7
8
9
if (!String.prototype.trim) {
String.prototype.trim = function() {
return this.replace(/^\s+/, "").replace(/\s+$/,"");
}
}
// test the function
var str = " \t\n test string ".trim();
alert(str == "test string"); // alerts "true"

34.
Javascrpt语言的特殊之处,就在于函数内部可以直接读取全局变量。

1
2
3
4
5
var n=999;
function f1(){
alert(n);
}
f1();//999

另一方面,在函数外部自然无法读取函数内的局部变量。

1
2
3
4
function f1(){
var n=999;
}
alert(n);//error

这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!

1
2
3
4
5
function f1(){
n=999;
}
f1();
alert(n);//999

其他内容请戳这里
还有这里

附:雅虎网站性能优化的34条黄金准则
1、尽量减少HTTP请求次数

+合并文件:如可以简单地把所有的CSS文件都放入一个样式表中。当脚本或者样式表在不同页面中使用时需要做不同的修改,这可能会相对麻烦点,但即便如此也要把这个方法作为改善页面性能的重要一步。
+CSS Sprites:是减少图像请求的有效方法。把所有的背景图像都放到一个图片文件中,然后通过CSS的background-image和 background-position属性来显示图片的不同部分;

2、减少DNS查找次数
域名系统(DNS)提供了域名和IP的对应关系,就像电话本中人名和他们的电话号码的关系一样。当你在浏览器地址栏中输入www.dudo.org 时,DNS解析服务器就会返回这个域名对应的IP地址。一般情况下返回给定域名对应的IP地址会花费20到120毫秒的时间。而且在这个过程中浏览器什么都不会做直到DNS查找完毕。

+缓存DNS查找

3、避免跳转
跳转是使用301和302代码实现的。下面是一个响应代码为301的HTTP头:
HTTP/1.1 301 Moved Permanently
Location: http://example.com/newuri
Content-Type: text/html
元素的刷新标签和JavaScript也可以实现URL的跳转,但是如果你必须要跳转的时候,最好的方法就是使用标准的3XXHTTP状态代 码,这主要是为了确保“后退”按钮可以正确地使用。
但是要记住跳转会降低用户体验。

4、可缓存的AJAX

5、推迟加载内容
把整个过程按照onload事件分隔成两部分,JavaScript是一个理想的选择。例如,如果你有用于实现拖放和动画的JavaScript,那么它 就以等待稍后加载,因为页面上的拖放元素是在初始化呈现之后才发生的。其它的例如隐藏部分的内容(用户操作之后才显现的内容)和处于折叠部分的图像也可以 推迟加载
工具可以节省你的工作量

6、预加载
预加载是在浏览器空闲时请求将来可能会用到的页面内容(如图像、样式表和脚本)。
使用这种方法,当用户要访问下一个页面时,页面中的内容大部分已经加载到缓存中了,因此可以大大改善访问速度。
下面提供了几种预加载方法:
+无条件加载:触发onload事件时,直接加载额外的页面内容。以Google.com为例,你可以看一下它的spirit image图像是怎样在onload中加载的。这个spirit image图像在google.com主页中是不需要的,但是却可以在搜索结果页面中用到它。
+有条件加载:根据用户的操作来有根据地判断用户下面可能去往的页面并相应的预加载页面内容。在search.yahoo.com中你可以看到如何在你输入内容时加载额外的页面内容。
+有预期的加载:载入重新设计过的页面时使用预加载。这种情况经常出现在页面经过重新设计后用户抱怨“新的页面看起来很酷,但是却比以前慢”。问题可能出在 用户对于你的旧站点建立了完整的缓存,而对于新站点却没有任何缓存内容。因此你可以在访问新站之前就加载一部内容来避免这种结果的出现。在你的旧站中利用 浏览器的空余时间加载新站中用到的图像的和脚本来提高访问速度。

7、减少DOM元素数量

8、根据域名划分页面内容
把页面内容划分成若干部分可以使你最大限度地实现平行下载。由于DNS查找带来的影响你首先要确保你使用的域名数量在2个到4个之间。例如,你可以把用到的HTML内容和动态内容放在www.example.org上,而把页面各种组件(图片、脚本、CSS)分别存放在 statics1.example.org和statics.example.org上。

9、使iframe的数量最小
ifrmae元素可以在父文档中插入一个新的HTML文档。了解iframe的工作理然后才能更加有效地使用它,这一点很重要。
+iframe优点:
解决加载缓慢的第三方内容如图标和广告等的加载问题
Security sandbox
并行加载脚本
+iframe的缺点:
即使内容为空,加载也需要时间
会阻止页面加载
没有语意

10、不要出现404错误

11、使用内容分发网络

内容分发网络(Content Delivery Network,CDN)是由一系列分散到各个不同地理位置上的Web服务器组成的,它提高了网站内容的传输速度。用于向用户传输内容的服务器主要是根据 和用户在网络上的靠近程度来指定的。例如,拥有最少网络跳数(network hops)和响应速度最快的服务器会被选定。

12、为文件头指定Expires或Cache-Control
这条守则包括两方面的内容:
对于静态内容:设置文件头过期时间Expires的值为“Never expire”(永不过期)
对于动态内容:使用恰当的Cache-Control文件头来帮助浏览器进行有条件的请求

13、Gzip压缩文件内容
Gzip是目前最流行也是最有效的压缩方式。这是由GNU项目开发并通过RFC 1952来标准化的。另外仅有的一个压缩格式是deflate,但是它的使用范围有限效果也稍稍逊色。
Gzip大概可以减少70%的响应规模。

14、配置ETag
Entity tags(ETags)(实体标签)是web服务器和浏览器用于判断浏览器缓存中的内容和服务器中的原始内容是否匹配的一种机制(“实体”就是所说的“内 容”,包括图片、脚本、样式表等)。

15、尽早刷新输出缓冲

16、使用GET来完成AJAX请求
使用GET最为恰当,因为它只需发送一个TCP包(除非你有很多cookie)。IE中URL的最大长度为2K,因此如果你要发送一个超过2K的 数据时就不能使用GET了。
一个有趣的不同就是POST并不像GET那样实际发送数据。根据HTTP规范,GET意味着“获取”数据,因此当你仅仅获取数据时使用GET更加有意义(从语意上讲也是如此),相反,发送并在服务端保存数据时使用POST。

17、把样式表置于顶部
因为把样式表放到内会使页面有步骤的加载显示。
注重性能的前端服务器往往希望页面有秩序地加载。

18、避免使用CSS表达式(Expression)

19、使用外部JavaScript和CSS

20、削减JavaScript和CSS

21、用代替@import

22、避免使用滤镜

23、把脚本置于页面底部

24、剔除重复脚本

25、减少DOM访问

27、减小Cookie体积

28、对于页面内容使用无coockie域名

29、优化图像

30、优化CSS Spirite

31、不要在HTML中缩放图像

32、favicon.ico要小而且可缓存

33、保持单个内容小于25K
这条限制主要是因为iPhone不能缓存大于25K的文件。

34、打包组件成复合文本
把页面内容打包成复合文本就如同带有多附件的Email,它能够使你在一个HTTP请求中取得多个组件(切记:HTTP请求是很奢侈的)。当你使用这条规则时,首先要确定用户代理是否支持(iPhone就不支持)