1.eval是做什么的?
它的功能是把对应的字符串解析成JS代码并运行;
应该避免使用eval,不安全,非常耗性能(2次,一次解析成js语句,一次执行)。
2. null,undefined 的区别?
目前,null和undefined基本是同义的,只有一些细微的差别。
null表示"没有对象",即该处不应该有值。典型用法是:
(1) 作为函数的参数,表示该函数的参数不是对象。
(2) 作为对象原型链的终点。
Object.getPrototypeOf(Object.prototype);
// null
undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。典型用法是:
(1)变量被声明了,但没有赋值时,就等于undefined。
(2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。
(3)对象没有赋值的属性,该属性的值为undefined。
(4)函数没有返回值时,默认返回undefined。
var i;
i // undefined
function f(x){console.log(x)}
f() // undefined
var o = new Object();
o.p // undefined
var x = f();
x // undefined
3. 写一个通用的事件侦听器函数
// event(事件)工具集,来源:github.com/markyun
markyun.Event = {
// 页面加载完成后
readyEvent : function(fn) {
if (fn==null) {
fn=document;
}
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = fn;
} else {
window.onload = function() {
oldonload();
fn();
};
}
},
// 视能力分别使用dom0||dom2||IE方式 来绑定事件
// 参数: 操作的元素,事件名称 ,事件处理程序
addEvent : function(element, type, handler) {
if (element.addEventListener) {
//事件类型、需要执行的函数、是否捕捉
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent('on' + type, function() {
handler.call(element);
});
} else {
element['on' + type] = handler;
}
},
// 移除事件
removeEvent : function(element, type, handler) {
if (element.removeEnentListener) {
element.removeEnentListener(type, handler, false);
} else if (element.datachEvent) {
element.detachEvent('on' + type, handler);
} else {
element['on' + type] = null;
}
},
// 阻止事件 (主要是事件冒泡,因为IE不支持事件捕获)
stopPropagation : function(ev) {
if (ev.stopPropagation) {
ev.stopPropagation();
} else {
ev.cancelBubble = true;
}
},
// 取消事件的默认行为
preventDefault : function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
// 获取事件目标
getTarget : function(event) {
return event.target || event.srcElement;
},
// 获取event对象的引用,取到事件的所有信息,确保随时能使用event;
getEvent : function(e) {
var ev = e || window.event;
if (!ev) {
var c = this.getEvent.caller;
while (c) {
ev = c.arguments[0];
if (ev && Event == ev.constructor) {
break;
}
c = c.caller;
}
}
return ev;
}
};
4.你用闭包来做什么?如果你有最喜欢的应用场景,举一些例子。
DOM操作——怎样添加、移除、移动、复制、创建和查找节点。
(
1)创建新节点
(
2
)添加、移除、替换、插入
appendChild()
removeChild()
replaceChild()
insertBefore() //
在已有的子节点前插入一个新的子节点
(3)查找
getElementsByTagName() //
通过标签名称
getElementsByTagName() //
通过标签名称
getElementsByName() //
通过元素的
Name
属性的值
(IE
容错能力较强,会得到一个数组,其中包括
id
等于
name
值的
)
getElementById() //
通过元素
Id
,唯一性
5.html5有哪些新特性、移除了那些元素?如何处理HTML5新标签的浏览器兼容问题?如何区分 HTML 和 HTML5?
* HTML5
现在已经不是
SGML
的子集,主要是关于图像,位置,存储,多任务等功能的增加。
*
拖拽释放
(Drag and drop) API
语义化更好的内容标签(
header,nav,footer,aside,article,section
)
音频、视频
API(audio,video)
画布
(Canvas) API
地理
(Geolocation) API
本地离线存储
localStorage
长期存储数据,浏览器关闭后数据不丢失;
sessionStorage
的数据在浏览器关闭后自动删除
表单控件,
calendar
、
date
、
time
、
email
、
url
、
search
新的技术
webworker, websocket, Geolocation
*
移除的元素
纯表现的元素:
basefont
,
big
,
center
,
font, s
,
strike
,
tt
,
u
;
对可用性产生负面影响的元素:
frame
,
frameset
,
noframes
;
支持
HTML5
新标签:
* IE8/IE7/IE6
支持通过
document.createElement
方法产生的标签,
可以利用这一特性让这些浏览器支持
HTML5
新标签,
浏览器支持新标签后,还需要添加标签默认的样式:
*
当然最好的方式是直接使用成熟的框架、使用最多的是
html5shim
框架
<!--[if lt IE 9]>
<script> src="http://html5shim.googlecode.com/svn/trunk/html5.js"</script>
<![endif]-->
如何区分:
DOCTYPE
声明
\
新增的结构元素
\
功能元素。
8.iframe的优缺点?
1.<iframe>
优点:
解决加载缓慢的第三方内容如图标和广告等的加载问题
Security sandbox,并行加载脚本
2.<iframe>
的缺点:
*iframe
会阻塞主页面的
Onload
事件;
*
即时内容为空,加载也需要时间
*
没有语意
9.如何实现浏览器内多个标签页之间的通信?
调用
localstorge
、
cookies
等本地存储方式
10.webSocket如何兼容低浏览器?
Adobe Flash Socket
、
ActiveX HTMLFile (IE)
、
基于
multipart
编码发送
XHR
、
基于长轮询的
XHR
11.线程与进程的区别
一个程序至少有一个进程
,
一个进程至少有一个线程
.
线程的划分尺度小于进程,使得多线程程序的并发性高。
另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
12.你如何对网站的文件和资源进行优化?
期待的解决方案包括:
文件合并
文件最小化
/
文件压缩
缓存的使用(多个域名来提供缓存)
其他
13.请说出三种减少页面加载时间的方法。
1.
优化图片
2.
图像格式的选择(
GIF
:提供的颜色较少,可用在一些对颜色要求不高的地方)
3.
优化
CSS
(压缩合并
css
,如
margin-top,margin-left...)
4.
网址后加斜杠(如
www.campr.com/
目录,会判断这个
“
目录是什么文件类型,或者是目录。)
5.标明高度和宽度(如果浏览器没有找到这两个参数,它需要一边下载图片一边计算大小,如果图片很多,浏览器需要不断地调整页面。这不但影响速度,也影响浏览体验。
当浏览器知道了高度和宽度参数后,即使图片暂时无法显示,页面上也会腾出图片的空位,然后继续加载后面的内容。从而加载时间快了,浏览体验也更好了。)
6.
减少
http
请求(合并文件,合并图片)。
14.你都使用哪些工具来测试代码的性能?
Profiler, JSPerf
(
http://jsperf.com/nexttick-vs-setzerotimeout-vs-settimeout
)
, Dromaeo
15.什么是 FOUC(无样式内容闪烁)?你如何来避免 FOUC?
FOUC - Flash Of Unstyled Content
文档样式闪烁
<style type="text/css" media="all">@import "../fouc.css";</style>
而引用
CSS
文件的
@import
就是造成这个问题的罪魁祸首。
IE
会先加载整个
HTML
文档的
DOM
,然后再去导入外部的
CSS
文件,因此,在页面
DOM
加载完成到
CSS
导入完成中间会有一段时间页面上的内容是没有样式的,这段时间的长短跟网速,电脑速度都有关系。
解决方法简单的出奇,只要在
<head>
之间加入一个
<link>
或者
<script>
元素就可以了。
16.null和undefined的区别?
null
是一个表示”无”的对象,转为数值时为0;undefined
是一个表示”无”的原始值,转为数值时为NaN
。
当声明的变量还未被初始化时,变量的默认值为undefined
。null
用来表示尚未存在的对象,常用来表示函数企图返回一个不存在的对象。
undefined
表示”缺少值”,就是此处应该有一个值,但是还没有定义。典型用法是:
(
1
)变量被声明了,但没有赋值时,就等于
undefined
。
(
2)
调用函数时,应该提供的参数没有提供,该参数等于
undefined
。
(
3
)对象没有赋值的属性,该属性的值为
undefined
。
(
4
)函数没有返回值时,默认返回
undefined
。
null
表示”没有对象”,即该处不应该有值。典型用法是:
(
1
)
作为函数的参数,表示该函数的参数不是对象。
(
2
)
作为对象原型链的终点。
17.new操作符具体干了什么呢?
1
、创建一个空对象,并且
this
变量引用该对象,同时还继承了该函数的原型。
2
、属性和方法被加入到
this
引用的对象中。
3
、新创建的对象由
this
所引用,并且最后隐式的返回
this
。
var obj = {};
obj.__proto__ = Base.prototype;
Base.call(obj);
18.JSON 的了解?
JSON(JavaScript Object Notation)
是一种轻量级的数据交换格式。
它是基于
JavaScript
的一个子集。数据格式简单
,
易于读写
,
占用带宽小.
{'age':'12', 'name':'back'}
19.js延迟加载的方式有哪些?
defer
和
async
、动态创建
DOM
方式(创建
script
,插入到
DOM
中,加载完毕后
callBack
)、按需异步载入
js
20.如何解决跨域问题?
jsonp
、
document.domain+iframe
、
window.name
、
window.postMessage
、服务器上设置代理页面
jsonp
的原理是动态插入
script
标签
21.documen.write和 innerHTML的区别
document.write
只能重绘整个页面
innerHTML
可以重绘页面的一部分
22. .call() 和 .apply() 的区别和作用?
作用:动态改变某个类的某个方法的运行环境。
23.哪些操作会造成内存泄漏?
内存泄漏指任何对象在您不再拥有或需要它之后仍然存在。
垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为
0
(没有其他对象引用过该对象),或对该对象的惟一引用是循环的,那么该对象的内存即可回收。
setTimeout
的第一个参数使用字符串而非函数的话,会引发内存泄漏。
闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)
24.JavaScript中的作用域与变量声明提升?
25.如何判断当前脚本运行在浏览器还是node环境中?
通过判断
Global
对象是否为
window
,如果不为
window
,当前脚本没有运行在浏览器中
26.其他问题?
99%的网站都需要被重构是那本书上写的?
*
网站重构:应用
web
标准进行设计(第
2
版)
27.javascript对象的几种创建方式
1
,工厂模式
2
,构造函数模式
3
,原型模式
4
,混合构造函数和原型模式
5
,动态原型模式
6,寄生构造函数模式
7
,稳妥构造函数模式
28.javascript继承的6种方法
1
,原型链继承
2
,借用构造函数继承
3
,组合继承
(
原型
+
借用构造
)
4
,原型式继承
5
,寄生式继承
6
,寄生组合式继承
29.ajax过程
(1)
创建
XMLHttpRequest
对象
,
也就是创建一个异步调用对象
.
(2)
创建一个新的
HTTP
请求
,
并指定该
HTTP
请求的方法、
URL
及验证信息
.
(3)
设置响应
HTTP
请求状态变化的函数
.
(4)
发送
HTTP
请求
.
(5)
获取异步调用返回的数据
.
(6)
使用
JavaScript
和
DOM
实现局部刷新
.
30.异步加载和延迟加载
1.
异步加载的方案:
动态插入
script
标签
2.
通过
ajax
去获取
js
代码,然后通过
eval
执行
3.script
标签上添加
defer
或者
async
属性
4.
创建并插入
iframe
,让它异步执行
js
5.
延迟加载:有些
js
代码并不是页面初始化的时候就立刻需要的,而稍后的某些情况才需要的。
31.javascript里面的继承怎么实现,如何避免原型链上面的对象共享
用构造函数和原型链的混合模式去实现继承,避免对象共享可以参考经典的
extend()
函数,很多前端框架都有封装的,就是用一个空函数当做中间变量
32.grunt, YUI compressor 和 google clojure用来进行代码压缩的用法。
YUI Compressor
是一个用来压缩
JS
和
CSS
文件的工具,采用
Java
开发。
使用方法:
//
压缩
JS
java -jar yuicompressor-2.4.2.jar --type js --charset utf-8 -v src.js > packed.js//
压缩
CSS
//
压缩
CSS
java -jar yuicompressor-2.4.2.jar --type css --charset utf-8 -v src.css > packed.css
33.Flash、Ajax各自的优缺点,在使用中如何取舍?
1
、
Flash ajax
对比
Flash
适合处理多媒体、矢量图形、访问机器;对
CSS
、处理文本上不足,不容易被搜索。
Ajax对CSS、文本支持很好,支持搜索;多媒体、矢量图形、机器访问不足。
共同点:与服务器的无刷新传递消息、用户离线和在线状态、操作
DOM
34.请解释一下 JavaScript 的同源策略。
概念:同源策略是客户端脚本(尤其是Javascript
)的重要的安全度量标准。它最早出自Netscape Navigator2.0
,其目的是防止某个文档或脚本从多个不同源装载。
这里的同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议。
指一段脚本只能读取来自同一来源的窗口和文档的属性。
35.为什么要有同源限制?
我们举例说明:比如一个黑客程序,他利用Iframe
把真正的银行登录页面嵌到他的页面上,当你使用真实的用户名,密码登录时,他的页面就可以通过Javascript
读取到你的表单中input
中的内容,这样用户名,密码就轻松到手了。
36.什么是 “use strict”; ? 使用它的好处和坏处分别是什么?
ECMAscript 5
添加了第二种运行模式:”严格模式”(strict mode)。顾名思义,这种模式使得Javascript
在更严格的条件下运行。
设立”严格模式”的目的,主要有以下几个:
-
消除
Javascript
语法的一些不合理、不严谨之处,减少一些怪异行为
;
-
消除代码运行的一些不安全之处,保证代码运行的安全;
-
提高编译器效率,增加运行速度;
-
为未来新版本的
Javascript
做好铺垫。
注:经过测试IE6,7,8,9
均不支持严格模式。
缺点:
现在网站的JS
都会进行压缩,一些文件用了严格模式,而另一些没有。这时这些本来是严格模式的文件,被 merge
后,这个串就到了文件的中间,不仅没有指示严格模式,反而在压缩后浪费了字节。
37.GET和POST的区别,何时使用POST?
GET
:一般用于信息获取,使用
URL
传递参数,对所发送信息的数量也有限制,一般在
2000
个字符
POST
:一般用于修改服务器上的资源,对所发送的信息没有限制。
GET
方式需要使用
Request.QueryString
来取得变量的值,而
POST
方式通过
Request.Form
来获取变量的值,
也就是说
Get
是通过地址栏来传值,而
Post
是通过提交表单来传值。
然而,在以下情况中,请使用
POST
请求:
无法使用缓存文件(更新服务器上的文件或数据库)
向服务器发送大量数据(
POST
没有数据量限制)
发送包含未知字符的用户输入时,
POST
比
GET
更稳定也更可靠
38.哪些地方会出现css阻塞,哪些地方会出现js阻塞?
js的阻塞特性:所有浏览器在下载JS
的时候,会阻止一切其他活动,比如其他资源的下载,内容的呈现等等。直到JS
下载、解析、执行完毕后才开始继续并行下载
其他资源并呈现内容。为了提高用户体验,新一代浏览器都支持并行下载JS
,但是JS
下载仍然会阻塞其它资源的下载(例如.图片,css文件等)。
由于浏览器为了防止出现JS
修改DOM
树,需要重新构建DOM
树的情况,所以就会阻塞其他的下载和呈现。
嵌入JS
会阻塞所有内容的呈现,而外部JS
只会阻塞其后内容的显示,2种方式都会阻塞其后资源的下载。也就是说外部样式不会阻塞外部脚本的加载,但会阻塞外部脚本的执行。
CSS
怎么会阻塞加载了?CSS
本来是可以并行下载的,在什么情况下会出现阻塞加载了(在测试观察中,IE6
下CSS
都是阻塞加载)
当CSS
后面跟着嵌入的JS
的时候,该CSS
就会出现阻塞后面资源下载的情况。而当把嵌入JS
放到CSS
前面,就不会出现阻塞的情况了。
根本原因:因为浏览器会维持html
中css
和js
的顺序,样式表必须在嵌入的JS执行前先加载、解析完。而嵌入的JS
会阻塞后面的资源加载,所以就会出现上面CSS
阻塞下载的情况。
39. 嵌入JS
应该放在什么位置?
1
、放在底部,虽然放在底部照样会阻塞所有呈现,但不会阻塞资源下载。
2
、如果嵌入
JS
放在
head
中,请把嵌入
JS
放在
CSS
头部。
3
、使用
defer
(只支持
IE
)
4
、不要在嵌入的
JS
中调用运行时间较长的函数,如果一定要用,可以用
`setTimeout`
来调用
40.Javascript无阻塞加载具体方式
- 将脚本放在底部。
<link>
还是放在head
中,用以保证在js
加载前,能加载出正常显示的页面。<script>
标签放在</body>
前。 - 成组脚本:由于每个
<script>
标签下载时阻塞页面解析过程,所以限制页面的<script>
总数也可以改善性能。适用于内联脚本和外部脚本。
- 非阻塞脚本:等页面完成加载后,再加载
js
代码。也就是,在window.onload
事件发出后开始下载代码。
(1)defer
属性:支持IE4和fierfox3.5
更高版本浏览器
(2)动态脚本元素:文档对象模型(DOM)允许你使用js动态创建HTML
的几乎全部文档内容。代码如下: -
<script> var script=document.createElement("script"); script.type="text/javascript"; script.src="file.js"; document.getElementsByTagName("head")[0].appendChild(script); </script>
此技术的重点在于:无论在何处启动下载,文件额下载和运行都不会阻塞其他页面处理过程。即使在head里(除了用于下载文件的http链接)。
41.闭包相关问题?
42.js事件处理程序问题?
43.eval是做什么的?
它的功能是把对应的字符串解析成
JS代码并运行;应该避免使用
eval
,不安全,非常耗性能(
2
次,一次解析成
js
语句,一次执行)。
44.Node.js的适用场景?
高并发、聊天、实时消息推送
45.JavaScript原型,原型链 ? 有什么特点?
*
原型对象也是普通的对象,是对象一个自带隐式的
__proto__
属性,原型也有可能有自己的原型,如果一个原型对象的原型不为
null
的话,我们就称之为原型链。
*
原型链是由一些用来继承和共享属性的对象组成的(有限的)对象链。
46.页面重构怎么操作?
编写
CSS
、让页面结构更合理化,提升用户体验,实现良好的页面效果和提升性能。
47.WEB应用从服务器主动推送Data到客户端有那些方式?
html5 websoket
WebSocket
通过
Flash
XHR
长时间连接
XHR Multipart Streaming
不可见的
Iframe
<script>
标签的长时间连接
(
可跨域
)
48.事件、IE与火狐的事件机制有什么区别? 如何阻止冒泡?
1.
我们在网页中的某个操作(有的操作对应多个事件)。例如:当我们点击一个按钮就会产生一个事件。是可以被
JavaScript
侦测到的行为。
2.
事件处理机制:
IE
是事件冒泡、
firefox
同时支持两种事件模型,也就是:捕获型事件和冒泡型事件。;
3. ev.stopPropagation();
注意旧
ie
的方法
ev.cancelBubble = true;
49.ajax 是什么?ajax 的交互模型?同步和异步的区别?如何解决跨域问题?
1.
通过异步模式,提升了用户体验
2.
优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占用
3. Ajax
在客户端运行,承担了一部分本来由服务器承担的工作,减少了大用户量下的服务器负载。
50
. Ajax
的最大的特点是什么。
Ajax
可以实现动态不刷新(局部刷新)
readyState
属性
状态
有
5
个可取值:
0=
未初始化
,
1=
启动
2=
发送,
3=
接收,
4=
完成
ajax
的缺点
1
、
ajax
不支持浏览器
back
按钮。
2
、安全问题
AJAX
暴露了与服务器交互的细节。
3
、对搜索引擎的支持比较弱。
4
、破坏了程序的异常机制。
5
、不容易调试。
51、跨域:
jsonp
、
iframe
、
window.name
、
window.postMessage
、服务器上设置代理页面
52.js对象的深度克隆
function clone(Obj) {
var buf;
if (Obj instanceof Array) {
buf = []; //
创建一个空的数组
var i = Obj.length;
while (i--) {
buf[i] = clone(Obj[i]);
}
return buf;
}else if (Obj instanceof Object){
buf = {}; //
创建一个空对象
for (var k in Obj) { //
为这个对象添加新的属性
buf[k] = clone(Obj[k]);
}
return buf;
}else{
return Obj;
}
}
53、AMD和CMD 规范的区别?
54、cache-control
网页的缓存是由HTTP消息头中的“Cache-control”
来控制的,常见的取值有private
、
no-cache
、
max-age
、
must-revalidate
等,默认为private
。
Expires
头部字段提供一个日期和时间,响应在该日期和时间后被认为失效。允许客户端在这个时间之前不去检查(发请求),等同max-age
的效果。但是如果同时存在,则被Cache-Control
的max-age
覆盖。
Expires = "Expires" ":" HTTP-date
例如
Expires: Thu, 01 Dec 1994 16:00:00 GMT
(必须是
GMT
格式)
如果把它设置为-1
,则表示立即过期
Expires
和max-age
都可以用来指定文档的过期时间,但是二者有一些细微差别
1.Expires
在
HTTP/1.0
中已经定义,
Cache-Control:max-age
在
HTTP/1.1
中才有定义,为了向下兼容,仅使用
max-age
不够;
2.Expires
指定一个绝对的过期时间
(GMT
格式
),
这么做会导致至少
2
个问题:
1)
客户端和服务器时间不同步导致
Expires
的配置出现问题。
2
)很容易在配置后忘记具体的过期时间,导致过期来临出现浪涌现象;
3.max-age
指定的是从文档被访问后的存活时间,这个时间是个相对值
(
比如
:3600s),
相对的是文档第一次被请求时服务器记录的
Request_time(
请求时间
)
4.Expires
指定的时间可以是相对文件的最后访问时间
(Atime)
或者修改时间
(MTime),
而
max-age
相对对的是文档的请求时间(Atime)。如果值为
no-cache,
那么每次都会访问服务器。如果值为
max-age,
则在过期之前不会重复访问服务器。
55.js操作获取和设置cookie
//
创建
cookie
function setCookie(name, value, expires, path, domain, secure) {
var cookieText = encodeURIComponent(name) + '=' + encodeURIComponent(value);
if (expires instanceof Date) {
cookieText += '; expires=' + expires;
}
if (path) {
cookieText += '; expires=' + expires;
}
if (domain) {
cookieText += '; domain=' + domain;
}
if (secure) {
cookieText += '; secure';
}
document.cookie = cookieText;
}
//
获取
cookie
function getCookie(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 = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd));
}
return cookieValue;
}
//
删除
cookie
function unsetCookie(name) {
document.cookie = name + "= ; expires=" + new Date(0);
}
56、javascript的typeof返回哪些数据类型
Object、number、 function、 boolean、 underfind、string
57.例举3种强制类型转换和2种隐式类型转换?
强制(parseInt,parseFloat,number)
隐式(== – ===)
58.split() join() 的区别
split()方法:用于把一个字符串分割成字符串数组.
join() 方法用于把数组中的所有元素放入一个字符串。
(总结:前者是切割成数组的形式,后者是将数组转换成字符串);
59.数组方法pop() push() unshift() shift()
Push()尾部添加; pop()尾部删除;
Unshift()头部添加; shift()头部删除;
60.事件绑定和普通事件有什么区别?
事件绑定就是针对dom元素的事件,绑定在dom元素上
普通事件即为非针对dom元素的事件;
例如:
普通事件
var btn = document.getElementById("hello");
btn.onclick = function(){
alert(1);
};
btn.onclick = function(){
alert(2);
};
//这个事件只会弹出2;
事件绑定
var btn = document.getElementById("hello");
btn.addEventListener("click",function(){
alert(1);
},false);
btn.addEventListener("click",function(){
alert(2);
},false); //这个事
件首先会弹出1,然后在弹出2;
61.IE和DOM事件流的区别?
1.执行顺序不一样;
2.参数不一样;
3.事件加不加on;
4.this指向问题;
62.IE和标准下有哪些兼容性的写法
var ev = ev || window.event
document.documentElement.clientWidth ||
document.body.clientWidth
Var target = ev.srcElement||ev.target
63.ajax请求的时候get 和post方式的区别?
1、get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和
表单内各个字段一一对应,在URL中可以看到;
post是通过HTTP post机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程;
2、Get请求有如下特性:它会将数据添加到URL中,通过这种方式传递到服务器,通常利用一个问号?代表URL地址的结尾与数据参数的开端,后面的参数每一个数据参数以“名称=值”的形式出现,参数与参数之间利用一个连接符&来区分。
Post请求有如下特性:数据是放在HTTP主体中的,其组织方式不只一种,有&连接方式,也有分割符方式,可隐藏参数,传递大批数据,比较方便。
3、get传送的数据量较小,不能大于2KB;post传送的数据量较大,一般被默认为不受限制。但理论上,因服务器的不同而异.
4、get安全性非常低,post安全性较高;(总结:一个在url后面 一个放在虚拟载体里面有大小限制安全问题应用不同 一个是论坛等只需要请求的,一个是类似修改密码的)
64.call和apply的区别?
相同点:两个方法产生的作用是完全一样的
不同点:方法传递的参数不同
Object.call(this,obj1,obj2,obj3)调用一个对象的一个方法,以另一
个对象替换当前对象
Object.apply(this,arguments)应用某一对象的一个方法,用另一个对
象替换当前对象。
65.ajax请求时,如何解释json数据?
使用eval parse 鉴于安全性考虑 使用parse更靠谱
66.b继承a的方法?
b.prototype=new a;
67.写一个获取非行间样式的函数
function getStyle(obj,attr,value){
if(!value){
if(obj.currentStyle){
return obj.currentStyle(attr)
}else{
obj.getComputedStyle(attr,false)
}
}else{
obj.style[attr]=value
}
}
68.事件委托是什么?
让利用事件冒泡的原理,让自己的所触发的事件,让他的父元素代替执
行!
事件委托就是事件目标自身不处理事件,而是把处理任务委托给其父元
素或者祖先元素,甚至根元素(document);
jQuery为绑定和委托事件提供了.bind()、.live()和.delegate()方法;
http://www.tuicool.com/articles/zQVvau 例子可见此链接
69.闭包是什么,有什么特性,对页面有什么影响?
闭包就是能够读取其他函数内部变量的函数。
http://blog.csdn.net/gaoshanwudi/article/details/7355794 此链
接可查看(问这个问题的不是一个公司)
70.如何阻止事件冒泡和默认事件?
canceBubble return false
查看 http://www.2cto.com/kf/201412/359961.html 案例
71.添加 删除 替换 插入到某个接点的方法?
obj.appendChidl()
obj.innersetBefore
obj.replaceChild
obj.removeChild
72.解释jsonp的原理,以及为什么不是真正的ajax?
动态创建script标签,回调函数
Ajax是页面无刷新请求数据操作
73.javascript的本地对象,内置对象和宿主对象?
本地对象为array obj regexp等可以new实例化
内置对象为gload Math 等不可以实例化的
宿主为浏览器自带的document,window 等
74.document load 和document ready的区别?
Document.onload 是在结构和样式加载完才执行js
Document.ready原生种没有这个方法,jquery中有 $().ready
(function)
75.”==”和“===”的不同?
前者会自动转换类型
后者不会
76.javascript的同源策略?
一段脚本只能读取来自于同一来源的窗口和文档的属性,这里的同一来
源指的是主机名、协议和端口号的组合
77.编写一个数组去重的方法。
function oSort(arr){
var result ={};
var newArr=[];
for(var i=0;i<arr.length;i++){
if(!result[arr]){
newArr.push(arr)
result[arr]=1
}
}
return newArr
}
78、:Scope作用范围
1: (function() {
2: var a = b = 5;
3: })();
4:
5: console.log(b);
什么会被打印在控制台上?
回答
上面的代码会打印 5。
这个问题的诀窍是,这里有两个变量声明,但 a 使用关键字var声明的。代表它是一个函数的局部变量。与此相反,b 变成了全局变量。
这个问题的另一个诀窍是,它没有使用严格模式 (‘use strict';)。如果启用了严格模式,代码就会引发ReferenceError的错误:B没有定义(b is not defined)。请记住,严格模式,则需要明确指定,才能实现全局变量声明。比如,你应该写:
2:创建“原生”(native)方法
给字符串对象定义一个repeatify功能。当传入一个整数n时,它会返回重复n次字符串的结果。例如:
1: console.log('hello'.repeatify(3));
应打印 hellohellohello。
回答
一个可能的实现如下所示:
1: String.prototype.repeatify = String.prototype.repeatify || function(times) {
2: var str = '';
3: for (var i = 0; i < times; i++) {
4: str += this;
5: }
6: return str;
7: };
现在的问题测试开发者有关JavaScript继承和prototype的知识点。这也验证了开发者是否知道该如果扩展内置对象(尽管这不应该做的)。
这里的另一个要点是,你要知道如何不覆盖可能已经定义的功能。通过测试一下该功能定义之前并不存在:
1: String.prototype.repeatify = String.prototype.repeatify || function(times) {/* code here */};
当你被要求做好JavaScript函数兼容时这种技术特别有用。
3:声明提升(Hoisting)
执行这段代码,输出什么结果。
1: function test() {
2: console.log(a);
3: console.log(foo());
4: var a = 1;
5: function foo() {
6: return 2;
7: }
8: }
9:
10: test();
回答
这段代码的结果是 undefined 和 2。
原因是,变量和函数的声明都被提前了(移到了函数的顶部),但变量不分配任何值。因此,在打印变量的时候,它在函数中存在(它被声明了),但它仍然是undefined 。表示换句话说,上面的代码等同于以下内容:
function test() {
var a;
function foo() {
return 2;
}
console.log(a);
console.log(foo());
a = 1;
}
test();
4:this在JavaScript中如何工作的
下面的代码会输出什么结果?给出你的答案。
1: var fullname = 'John Doe';
2: var obj = {
3: fullname: 'Colin Ihrig',
4: prop: {
5: fullname: 'Aurelio De Rosa',
6: getFullname: function() {
7: return this.fullname;
8: }
9: }
10: };
12: console.log(obj.prop.getFullname());
14: var test = obj.prop.getFullname;
16: console.log(test());
回答
答案是Aurelio De Rosa和John Doe。原因是,在一个函数中,this的行为,取决于JavaScript函数的调用方式和定义方式,而不仅仅是看它如何被定义的。
在第一个 console.log()调用中,getFullname()被调用作为obj.prop对象的函数。所以,上下文指的是后者,函数返回该对象的 fullname。与此相反,当getFullname()被分配到test变量时,上下文指的是全局对象(window)。这是因为test是被隐式设置为全局对象的属性。出于这个原因,该函数返回window的fullname,即定义在第一行的那个值。
5:call()和apply()
现在让你解决前一个问题,使最后的console.log() 打印 Aurelio De Rosa。
回答
该问题可以通过强制使用 call() 或者 apply()改变函数上下文。在下面我将使用call(),但在这种情况下,apply()会输出相同的结果:
1: console.log(test.call(obj.prop));
JavaScript
- 介绍JavaScript的基本数据类型。
- 说说写JavaScript的基本规范?
- JavaScript有几种类型的值?(堆:原始数据类型和 栈:引用数据类型),你能画一下他们的内存图吗?
- Javascript创建对象的几种方式?
- eval是做什么的?
- 什么是window对象? 什么是document对象?
- null,undefined的区别?
- 写一个通用的事件侦听器函数(机试题)。
- ["1", "2", "3"].map(parseInt) 答案是多少?
- 关于事件,IE与火狐的事件机制有什么区别? 如何阻止冒泡?
- 什么是闭包(closure),为什么要用它?
- javascript 代码中的"use strict";是什么意思 ? 使用它区别是什么?
- 如何判断一个对象是否属于某个类?
- 用原生JavaScript的实现过什么功能吗?
- Javascript中,有一个函数,执行时对象查找时,永远不会去查找原型,这个函数是?
- 对JSON的了解?
- [].forEach.call($$(""),function(a){ a.style.outline="1px solid #"+(~~(Math.random()(1<<24))).toString(16) }) - 能解释一下这段代码的意思吗?
- 页面编码和被请求的资源编码如果不一致如何处理?
- AMD(Modules/Asynchronous-Definition)、CMD(Common Module Definition)规范区别?
- requireJS的核心原理是什么?(如何动态加载的?如何避免多次加载的?如何 缓存的?)
- 让你自己设计实现一个requireJS,你会怎么做?
- 谈一谈你对ECMAScript6的了解?
- ECMAScript6 怎么写class么,为什么会出现class这种东西?
- 异步加载的方式有哪些?
- DOM操作——怎样添加、移除、移动、复制、创建和查找节点?
- .call() 和 .apply() 的含义和区别?
- 数组和对象有哪些原生方法,列举一下?
- JS 怎么实现一个类。怎么实例化这个类
- JavaScript中的作用域与变量声明提升?
- JQuery的源码看过吗?能不能简单概况一下它的实现原理?
- jQuery.fn的init方法返回的this指的是什么对象?为什么要返回this?
- jquery中如何将数组转化为json字符串,然后再转化回来?
- jQuery 的属性拷贝(extend)的实现原理是什么,如何实现深拷贝?
- jquery.extend 与 jquery.fn.extend的区别?
- jQuery 的队列是如何实现的?队列可以用在哪些地方?
- 谈一下Jquery中的bind(),live(),delegate(),on()的区别?
- 是否知道自定义事件。jQuery里的fire函数是什么意思,什么时候用?
- jQuery 是通过哪个方法和 Sizzle 选择器结合的?(jQuery.fn.find()进入Sizzle)
- 针对 jQuery性能的优化方法?
- jquery 中如何将数组转化为json字符串,然后再转化回来?
- jQuery和Zepto的区别?各自的使用场景?
- Zepto的点透问题如何解决?
- jQueryUI如何自定义组件?
- 需求:实现一个页面操作不会整页刷新的网站,并且能在浏览器前进、后退时正确响应。给出你的技术实现方案?
- 如何判断当前脚本运行在浏览器还是node环境中?(阿里)
- 移动端最小触控区域是多大?
- jQuery 的 slideUp动画 ,如果目标元素是被外部事件驱动, 当鼠标快速地连续触发外部元素事件, 动画会滞后的反复执行,该如何处理呢?
- 把 Script 标签 放在页面的最底部的body封闭之前 和封闭之后有什么区别?浏览器会如何解析它们?
- 移动端的点击事件的有延迟,时间是多久,为什么会有? 怎么解决这个延时?(click 有 300ms 延迟,为了实现safari的双击事件的设计,浏览器要知道你是不是要双击操作。)
- 知道各种JS框架(Angular, Backbone, Ember, React, Meteor, Knockout...)么? 能讲出他们各自的优点和缺点么?
- Underscore 对哪些 JS 原生对象进行了扩展以及提供了哪些好用的函数方法?
- (如果会用node)知道route, middleware, cluster, nodemon, pm2, server-side rendering么?
- 解释一下 Backbone 的 MVC 实现方式?
- 什么是“前端路由”?什么时候适合使用“前端路由”? “前端路由”有哪些优点和缺点?
- 知道什么是webkit么? 知道怎么用浏览器的各种工具来调试和debug代码么?
- 如何测试前端代码么? 知道BDD, TDD, Unit Test么? - 知道怎么测试你的前端工程么(mocha, sinon, jasmin, qUnit..)?
- 前端templating(Mustache, underscore, handlebars)是干嘛的, 怎么用?
- 简述一下 Handlebars 的基本用法?
- 简述一下 Handlerbars 的对模板的基本处理流程, 如何编译的?如何缓存的?
- 用js实现千位分隔符?(来源:前端农民工,提示:正则+replace)
- 我们给一个dom同时绑定两个点击事件,一个用捕获,一个用冒泡,你来说下会执行几次事件,然后会先执行冒泡还是捕获]
介绍js的基本数据类型
- Undefined、Null、Boolean、Number、String、 ECMAScript 2015 新增:Symbol(创建后独一无二且不可变的数据类型 )
JavaScript原型,原型链 ? 有什么特点?
- 每个对象都会在其内部初始化一个属性,就是prototype(原型),当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,于是就这样一直找下去,也就是我们平时所说的原型链的概念。
- 关系:instance.constructor.prototype = instance.proto
- 特点:JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变。
- 当我们需要一个属性的时,Javascript引擎会先看当前对象中是否有这个属性, 如果没有的话, 就会查找他的Prototype对象是否有这个属性,如此递推下去,一直检索到 Object 内建对象。
function Func(){}
Func.prototype.name = "Sean";
Func.prototype.getInfo = function() {
return this.name;
}
var person = new Func();//现在可以参考var person = Object.create(oldObject);
console.log(person.getInfo());//它拥有了Func的属性和方法
//"Sean"
console.log(Func.prototype);
// Func { name="Sean", getInfo=function()}
JavaScript有几种类型的值?,你能画一下他们的内存图吗?
栈:原始数据类型(Undefined,Null,Boolean,Number、String)
- 堆:引用数据类型(对象、数组和函数)
- 两种类型的区别是:存储位置不同;
- 原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;
- 引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体
如何将字符串转化为数字,例如'12.3b'?
- parseFloat('12.3b');
- 正则表达式,'12.3b'.match(/(\d)+(.)?(\d)+/g)[0] * 1, 但是这个不太靠谱,提供一种思路而已
如何将浮点数点左边的数每三位添加一个逗号,如12000000.11转化为『12,000,000.11』?
function commafy(num){
return num && num
.toString()
.replace(/(\d)(?=(\d{3})+\.)/g, function($1, $2){
return $2 + ',';
});
}
如何实现数组的随机排序?
- 方法一:
var arr = [1,2,3,4,5,6,7,8,9,10];
function randSort1(arr){
for(var i = 0,len = arr.length;i < len; i++ ){
var rand = parseInt(Math.random()*len);
var tem
p = arr[rand];
arr[rand] = arr[i];
arr[i] = temp;
}
return arr;
}
console.log(randSort1(arr));
- 方法二:
var arr = [1,2,3,4,5,6,7,8,9,10];
function randSort2(arr){
var mixedArray = [];
while(arr.length > 0){
var randomIndex = parseInt(Math.random()*arr.length);
mixedArray.push(arr[randomIndex]);
arr.splice(randomIndex, 1);
}
return mixedArray;
}
console.log(randSort2(arr));
- 方法三:
var arr = [1,2,3,4,5,6,7,8,9,10];
arr.sort(function(){
return Math.random() - 0.5;
})
console.log(arr);
Javascript如何实现继承?
- 构造继承
- 原型继承
- 实例继承
- 拷贝继承
- 原型prototype机制或apply和call方法去实现较简单,建议使用构造函数与原型混合方式
function Parent(){
this.name = 'wang';
}
function Child(){
this.age = 28;
}
Child.prototype = new Parent();//继承了Parent,通过原型
var demo = new Child();
alert(demo.age);
alert(demo.name);//得到被继承的属性
javascript创建对象的几种方式?
- javascript创建对象简单的说,无非就是使用内置对象或各种自定义对象,当然还可以用JSON;但写法有很多种,也能混合使用
- 1、对象字面量的方式
- person={firstname:"Mark",lastname:"Yun",age:25,eyecolor:"black"};
- 2、用function来模拟无参的构造函数
function Person(){}
//定义一个function,如果使用new"实例化",该function可以看作是一个Class
person.name="Mark";
var person=new Person();
person.age="25";
person.work=function(){
alert(person.name+" hello...");
}
person.work();
- 3、用function来模拟参构造函数来实现(用this关键字定义构造的上下文属性)
function Pet(name,age,hobby){
this.name=name;//this作用域:当前对象
this.age=age;
this.hobby=hobby;
this.eat=function(){
alert("我叫"+this.name+",我喜欢"+this.hobby+",是个程序员");
}
}
var maidou =new Pet("麦兜",25,"coding");//实例化、创建对象
maidou.eat();//调用eat方法
- 4、用工厂方式来创建(内置对象)
var wcDog =new Object();
wcDog.name="旺财";
wcDog.age=3;
wcDog.work=function(){
alert("我是"+wcDog.name+",汪汪汪......");
}
wcDog.work();
- 5、用原型方式来创建
function Dog(){
}
Dog.prototype.name="旺财";
Dog.prototype.eat=function(){
alert(this.name+"是个吃货");
}
var wangcai =new Dog();
wangcai.eat();
- 6、用混合方式来创建
function Car(name,price){
this.name=name;
this.price=price;
}
Car.prototype.sell=function(){
alert("我是"+this.name+",我现在卖"+this.price+"万元");
}
var camry =new Car("凯美瑞",27);
camry.sell();
eval是做什么的?
- 它的功能是把对应的字符串解析成JS代码并运行;
- 应该避免使用eval,不安全,非常耗性能(2次,一次解析成js语句,一次执行)
- 由JSON字符串转换为JSON对象的时候可以用eval,var obj =eval('('+ str +')');
什么是window对象? 什么是document对象?
- window对象是指浏览器打开的窗口。
- document对象是Documentd对象(HTML 文档对象)的一个只读引用,window对象的一个属性
null,undefined 的区别?
- null 表示一个对象是“没有值”的值,也就是值为“空”;
- undefined 表示一个变量声明了没有初始化(赋值);
- undefined不是一个有效的JSON,而null是;
- undefined的类型(typeof)是undefined;
- null的类型(typeof)是object;
- Javascript将未赋值的变量默认值设为undefined;
- Javascript从来不会将变量设为null。它是用来让程序员表明某个用var声明的变量时没有值的
- typeof undefined
- undefined :
- 是一个表示"无"的原始值或者说表示"缺少值",就是此处应该有一个值,但是还没有定义。当尝试读取时会返回 undefined;
- 例如变量被声明了,但没有赋值时,就等于undefined
- undefined :
- typeof null //"object"
- null : 是一个对象(空对象, 没有任何属性和方法);
- 例如作为函数的参数,表示该函数的参数不是对象;
- 注意:
- 在验证null时,一定要使用 === ,因为 == 无法分别 null 和 undefined
- null == undefined // true
- null === undefined // false
["1", "2", "3"].map(parseInt) 答案是多少?
- parseInt() 函数能解析一个字符串,并返回一个整数,需要两个参数 (val, radix),其中 radix 表示要解析的数字的基数
function parseInt(str, radix) {
return str+'-'+radix;
};
var a=["1", "2", "3"];
a.map(parseInt); // ["1-0", "2-1", "3-2"] 不能大于radix
- 因为二进制里面,没有数字3,导致出现超范围的radix赋值和不合法的进制解析,才会返回NaN所以["1", "2", "3"].map(parseInt) 答案也就是:[1, NaN, NaN]
事件是?IE与火狐的事件机制有什么区别? 如何阻止冒泡?
- 我们在网页中的某个操作(有的操作对应多个事件)。例如:当我们点击一个按钮就会产生一个事件。是可以被 JavaScript 侦测到的行为
- 事件处理机制:IE是事件冒泡、Firefox同时支持两种事件模型,也就是:捕获型事件和冒泡型事件
- ev.stopPropagation();(旧ie的方法 ev.cancelBubble = true;)
什么是闭包(closure),为什么要用它?
- 闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部
- 闭包的特性:
- 函数内再嵌套函数
- 内部函数可以引用外层的参数和变量
- 参数和变量不会被垃圾回收机制回收
//li节点的onclick事件都能正确的弹出当前被点击的li索引
<ul id="testUL">
<li> index = 0</li>
<li> index = 1</li>
<li> index = 2</li>
<li> index = 3</li>
</ul>
<script type="text/javascript">
var nodes = document.getElementsByTagName("li");
for(i = 0;i<nodes.length;i+= 1){
nodes[i].onclick = (function(i){
return function() {
console.log(i);
} //不用闭包的话,值每次都是4
})(i);
}
</script>
- 执行say667()后,say667()闭包内部变量会存在,而闭包内部函数的内部变量不会存在
- 使得Javascript的垃圾回收机制GC不会收回say667()所占用的资源
- 因为say667()的内部函数的执行需要依赖say667()中的变量
- 这是对闭包作用的非常直白的描述
function say667() {
// Local variable that ends up within closure
var num = 666;
var sayAlert = function() {
alert(num);
}
num++;
return sayAlert;
}
var sayAlert = say667();
sayAlert()//执行结果应该弹出的667
javascript 代码中的"use strict";是什么意思 ? 使用它区别是什么?
- use strict是一种ECMAscript 5 添加的(严格)运行模式,这种模式使得 Javascript 在更严格的条件下运行,
- 使JS编码更加规范化的模式,消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为。
- 默认支持的糟糕特性都会被禁用,比如不能用with,也不能在意外的情况下给全局变量赋值;
- 全局变量的显示声明,函数必须声明在顶层,不允许在非函数代码块内声明函数,arguments.callee也不允许使用;
- 消除代码运行的一些不安全之处,保证代码运行的安全,限制函数中的arguments修改,严格模式下的eval函数的行为和非严格模式的也不相同;
- 提高编译器效率,增加运行速度;为未来新版本的Javascript标准化做铺垫。
如何判断一个对象是否属于某个类?
if(a instanceof Person){
alert('yes');
}
Javascript中,有一个函数,执行时对象查找时,永远不会去查找原型,这个函数是?
- javaScript中hasOwnProperty函数方法是返回一个布尔值,指出一个对象是否具有指定名称的属性。此方法无法检查该对象的原型链中是否具有该属性;该属性必须是对象本身的一个成员
- 使用方法: object.hasOwnProperty(proName)
- 其中参数object是必选项。一个对象的实例。
- proName是必选项。一个属性名称的字符串值。
- 如果 object 具有指定名称的属性,那么JavaScript中hasOwnProperty函数方法返回 true,反之则返回 false。
JSON 的了解?
- JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。
- 它是基于JavaScript的一个子集。数据格式简单, 易于读写, 占用带宽小
- 如:{"age":"12", "name":"back"}
- JSON字符串转换为JSON对象:
var obj =eval('('+ str +')');
var obj = str.parseJSON();
var obj = JSON.parse(str);
JSON对象转换为JSON字符串:
var last=obj.toJSONString();
var last=JSON.stringify(obj);
Ajax 解决浏览器缓存问题?
- 1、在ajax发送请求前加上 anyAjaxObj.setRequestHeader("If-Modified-Since","0")。
- 2、在ajax发送请求前加上 anyAjaxObj.setRequestHeader("Cache-Control","no-cache")。
- 3、在URL后面加上一个随机数: "fresh=" + Math.random();。
- 4、在URL后面加上时间搓:"nowtime=" + new Date().getTime();。
- 5、如果是使用jQuery,直接这样就可以了 $.ajaxSetup({cache:false})。这样页面的所有ajax都会执行这条语句就是不需要保存缓存记录
同步和异步的区别?
- 同步的概念应该是来自于OS中关于同步的概念:不同进程为协同完成某项工作而在先后次序上调整(通过阻塞,唤醒等方式).同步强调的是顺序性.谁先谁后.异步则不存在这种顺序性.
- 同步:浏览器访问服务器请求,用户看得到页面刷新,重新发请求,等请求完,页面刷新,新内容出现,用户看到新内容,进行下一步操作
- 异步:浏览器访问服务器请求,用户正常操作,浏览器后端进行请求。等请求完,页面不刷新,新内容也会出现,用户看到新内容
模块化开发怎么做?
- 不暴露私有成员
var module1 = (function(){
var _count = 0;
var m1 = function(){
//...
};
var m2 = function(){
//...
};
return {
m1 : m1,
m2 : m2
};
})();
AMD(Modules/Asynchronous-Definition)、CMD(Common Module Definition)规范区别?
- Asynchronous Module Definition,异步模块定义,所有的模块将被异步加载,模块加载不影响后面语句运行。所有依赖某些模块的语句均放置在回调函数中
- 区别:
- 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible
- CMD 推崇依赖就近,AMD 推崇依赖前置。看代码:
// CMD
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
// 此处略去 100 行
var b = require('./b') // 依赖可以就近书写
b.doSomething()
// ...
})
// AMD 默认推荐
define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好
a.doSomething()
// 此处略去 100 行
b.doSomething()
// ...
})
异步加载JS的方式有哪些?
- (1) defer,只支持IE
- (2) async:
- (3) 创建script,插入到DOM中,加载完毕后callBack
.call() 和 .apply() 的区别?
- 例子中用 add 来替换 sub,add.call(sub,3,1) == add(3,1) ,所以运行结果为:alert(4);
- 注意:js 中的函数其实是对象,函数名是对 Function 对象的引用。
function add(a,b)
{
alert(a+b);
}
function sub(a,b)
{
alert(a-b);
}
add.call(sub,3,1);
jquery.extend 与 jquery.fn.extend的区别?
- jquery.extend 为jquery类添加类方法,可以理解为添加静态方法
- jquery.fn.extend:源码中jquery.fn = jquery.prototype,所以对jquery.fn的扩展,就是为jquery类添加成员函数 使用:
- jquery.extend扩展,需要通过jquery类来调用,而jquery.fn.extend扩展,所有jquery实例都可以直接调用
Jquery与jQuery UI 有啥区别?
- jQuery是一个js库,主要提供的功能是选择器,属性修改和事件绑定等等
- jQuery UI则是在jQuery的基础上,利用jQuery的扩展性,设计的插件
- 提供了一些常用的界面元素,诸如对话框、拖动行为、改变大小行为等等
jquery 中如何将数组转化为json字符串,然后再转化回来?
- jQuery中没有提供这个功能,所以你需要先编写两个jQuery的扩展:
$.fn.stringifyArray = function(array) {
return JSON.stringify(array)
}
$.fn.parseArray = function(array) {
return JSON.parse(array)
}
然后调用:
$("").stringifyArray(array)
针对 jQuery 的优化方法?
- 基于Class的选择性的性能相对于Id选择器开销很大,因为需遍历所有DOM元素。
- 频繁操作的DOM,先缓存起来再操作。用Jquery的链式调用更好
- 比如:var str=$("a").attr("href");
- for (var i = size; i < arr.length; i++) {}
- for 循环每一次循环都查找了数组 (arr) 的.length 属性,在开始循环的时候设置一个变量来存储这个数字,可以让循环跑得更快:
- for (var i = size, length = arr.length; i < length; i++) {}
如何判断当前脚本运行在浏览器还是node环境中?(阿里)
- this === window ? 'browser' : 'node';
- 通过判断Global对象是否为window,如果不为window,当前脚本没有运行在浏览器中
jQuery 的 slideUp动画 ,如果目标元素是被外部事件驱动, 当鼠标快速地连续触发外部元素事件, 动画会滞后的反复执行,该如何处理呢?
- jquery stop(): 如:$("#div").stop().animate({width:"100px"},100);
JQuery一个对象可以同时绑定多个事件,这是如何实现的?
- 多个事件同一个函数:$("div").on("click mouseover", function(){});
- 多个事件不同函数
$("div").on({
click: function(){},
mouseover: function(){}
});
知道什么是webkit么? 知道怎么用浏览器的各种工具来调试和debug代码么?
- Chrome,Safari浏览器内核
检测浏览器版本版本有哪些方式?
- 功能检测、userAgent特征检测
- 比如:navigator.userAgent
//"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36"
What is a Polyfill?
- polyfill 是“在旧版浏览器上复制标准 API 的 JavaScript 补充”,可以动态地加载 JavaScript 代码或库,在不支持这些标准 API 的浏览器中模拟它们
- 例如,geolocation(地理位置)polyfill 可以在 navigator 对象上添加全局的 geolocation 对象,还能添加 getCurrentPosition 函数以及“坐标”回调对象
- 所有这些都是 W3C 地理位置 API 定义的对象和函数。因为 polyfill 模拟标准 API,所以能够以一种面向所有浏览器未来的方式针对这些 API 进行开发
- 一旦对这些 API 的支持变成绝对大多数,则可以方便地去掉 polyfill,无需做任何额外工作。
做的项目中,有没有用过或自己实现一些 polyfill 方案(兼容性处理方案)?
- 比如: html5shiv、Geolocation、Placeholder
使用JS实现获取文件扩展名?
function getFileExtension(filename) {
return filename.slice((filename.lastIndexOf(".") - 1 >>> 0) + 2);
}
- String.lastIndexOf()
- 方法返回指定值(本例中的'.')在调用该方法的字符串中最后出现的位置,如果没找到则返回 -1。对于'filename'和'.hiddenfile',lastIndexOf的返回值分别为0和-1无符号右移操作符(»>)
- 将-1转换为4294967295,将-2转换为4294967294,这个方法可以保证边缘情况时文件名不变
- String.prototype.slice()
- 从上面计算的索引处提取文件的扩展名。如果索引比文件名的长度大,结果为""
ECMAScript6 相关
Object.is() 与原来的比较操作符“ ===”、“ ==”的区别?
- 两等号判等,会在比较时进行类型转换;
- 三等号判等(判断严格),比较时不进行隐式类型转换,(类型不同则会返回false);
- Object.is 在三等号判等的基础上特别处理了 NaN 、-0 和 +0 ,保证 -0 和 +0 不再相同,但 Object.is(NaN, NaN) 会返回 true
- Object.is 应被认为有其特殊的用途,而不能用它认为它比其它的相等对比更宽松或严格。
- (1)JavaScript的数据类型
- 基本数据类型:Number,String,Boolean,Undefined,Null
- 复杂数据类型:Object,Array,Function,RegExp,Date,Error
- 全局数据类型:Math
- (2)JavaScript的闭包
- 闭包简单的说就是一个函数能访问外部函数的变量,这就是闭包,比如说:
- function a(x){
- var tem=3;
- function b(y){
- console.log(x+y+(++tem));
- }
- }
- a函数中的b函数就是闭包了,b函数可以使用a函数的局部变量,参数,最典型的闭包应该是下面这样,将定义在函数中的函数作为返回值
- function a(x){
- var tem=3;
- function b(y){
- console.log(x+y+(++tem));
- }
- return b;
- }
- 闭包的另一种作用是隔离作用域,请看下面这段代码
- for(var i=0;i<2;i++){
- setTimeout(function(){
- console.log(i);
- },0);
- }
- 上面这段代码的执行结果是2,2而不是0,1,因为等for循环出来后,执行setTimeout中的函数时,i的值已经变成了2,这就是没有隔离作用域所造成的,请看下面代码
- for(var i=0;i<2;i++){
- (function(i){
- setTimeout(function(){
- console.log(i);
- },0)
- })(i);
- }
- 这样就会输出0,1,我们的立即执行函数创建了一个作用域,隔离了外界的作用域,闭包的缺点是,因为内部闭包函数可以访问外部函数的变量,所以外部函数的变量不能被释放,如果闭包嵌套过多,会导致内存占用大,要合理使用闭包。
- (3)new 操作符到底做了什么
- 首先,new操作符为我们创建一个新的空对象,然后this变量指向该对象,
- 其次,空对象的原型执行函数的原型,
- 最后,改变构造函数内部的this的指向
- 代码如下:
- var obj={};
- obj.__proto__=fn.prototype;
- fn.call(obj);
- (4)改变函数内部this指针的指向函数
- call和apply,假设要改变fn函数内部的this的指向,指向obj,那么可以fn.call(obj);或者fn.apply(obj);那么问题来了,call和apply的区别是什么,其是call和apply的区别在于参数,他们两个的第一个参数都是一样的,表示调用该函数的对象,apply的第二个参数是数组,是[arg1,arg2,arg3]这种形式,而call是arg1,arg2,arg3这样的形式。还有一个bind函数,
- var bar=fn.bind(obj);那么fn中的this就指向obj对象了,bind函数返回新的函数,这个函数内的this指针指向obj对象。
- (5)JavaScript的作用域和作用域链
- JavaScript的作用域指的是变量的作用范围,内部作用域由函数的形参,实参,局部变量,函数构成,内部作用域和外部的作用域一层层的链接起来形成作用域链,当在在函数内部要访问一个变量的时候,首先查找自己的内部作用域有没有这个变量,如果没有就到这个对象的原型对象中去查找,还是没有的话,就到该作用域所在的作用域中找,直到到window所在的作用域,每个函数在声明的时候就默认有一个外部作用域的存在了,比如:
- var t=4;
- function foo(){
- var tem=12;
- funciton bar(){
- var temo=34;
- console.log(t+" "+tem+" "+temo);
- }
- }
- bar找t变量的过程就是,先到自己的内部作用域中找,发现没有找到,然后到bar所在的最近的外部变量中找,也就是foo的内部作用域,还是没有找到,再到window的作用域中找,结果找到了
- (6)JavaScript的继承
- function A(name){ this.name=name; }
- A.prototype.sayName=function(){ console.log(this.name); }
- function B(age){ this.age=age; }
原型继承
- B.prototype=new A("mbj"); //被B的实例共享
- var foo=new B(18);
- foo.age; //18,age是本身携带的属性
- foo.name; //mbj,等价于foo.__proto__.name
- foo.sayName(); //mbj,等价于foo.__proto__.proto__.sayName()
- foo.toString(); //"[object Object]",等价于foo.__proto__.__proto__.__proto__.toString();
这样B通过原型继承了A,在new B的时候,foo中有个隐藏的属性__proto__指向构造函数的prototype对象,在这里是A对象实例,A对象里面也有一个隐藏的属性__proto__,指向A构造函数的prototype对象,这个对象里面又有一个__proto__指向Object的prototype
这种方式的缺第一个缺点是所有子类共享父类实例,如果某一个子类修改了父类,其他的子类在继承的时候,会造成意想不到的后果。第二个缺点是在构造子类实例的时候,不能给父类传递参数。
- 构造函数继承
- function B(age,name){ this.age=age;A.call(this,name); }
- var foo=new B(18,"wmy");
- foo.name; //wmy
- foo.age; //18
- foo.sayName(); //undefined
- 采用这种方式继承是把A中的属性加到this上面,这样name相当于就是B的属性,sayName不在A的构造函数中,所以访问不到sayName。这种方法的缺点是父类的prototype中的函数不能复用。
- 原型继承+构造函数继承
- function B(age,name){ this.age=age;A.call(this,name); }
- B.prototype=new A("mbj");
- var foo=new B(18,"wmy");
- foo.name; //wmy
- foo.age; //18
- foo.sayName(); //wmy
- 这样就可以成功访问sayName函数了,结合了上述两种方式的优点,但是这种方式也有缺点,那就是占用的空间更大了。
- (7)JavaScript变量提升
- 请看下面代码
- var bar=1;
- function test(){
- console.log(bar); //undeifned
- var bar=2;
- console.log(bar); //2
- }
- test();
- 为什么在test函数中会出现上述结果呢,这就是JavaScript的变量提升了,虽然变量bar的定义在后面,不过浏览器在解析的时候,会把变量的定义放到最前面,上面的test函数相当于
- function test(){
- var bar;
- console.log(bar); //undefined
- bar=2;
- console.log(bar); //2
- }
- 再看
- var foo=function(){ console.log(1); }
- function foo(){ console.log(2); }
- foo(); //结果为1
- 同样的,函数的定义也会到提升到最前面,上面的代码相当于
- function foo(){ console.log(2); }
- var foo;
- foo=funciton(){ console.log(1); }
- foo(); //1
- (8)JavaScript事件模型
- 原始事件模型,捕获型事件模型,冒泡事件模型,
- 原始事件模型就是ele.οnclick=function(){}这种类型的事件模型
- 冒泡事件模型是指事件从事件的发生地(目标元素),一直向上传递,直到document,
- 捕获型则恰好相反,事件是从document向下传递,直到事件的发生地(目标元素)
- IE是只支持冒泡事件模型的,下面是兼容各个浏览器的事件监听代码
- EventUtil={
- addListener:function(target,type,handler){
- if(target.addEventListener){
- target.addEventListener(type,handler);
- }else if(target.attachEvent){
- target.attach("on"+type,function(){
- handler.call(target); //让handler中的this指向目标元素
- });
- }else{
- target["on"+type]=handler;
- }
- },
- removeListener:function(target,type,handler){
- if(target.removeEventListener){
- target.removeEventListener(type,handler);
- }else if(target.detachEvent){
- target.detachEvent("on"+type,handler);
- }else{
- target["on"+type]=null;
- }
- },
- getEvent:function(e){ //获取事件对象
- var evt=window.event||e;
- return evt;
- },
- getTarget:function(e){ //获得目标对象
- var evt=EventUtil.getEvent(e);
- var target;
- if(evt.target){ target=evt.target;}
- else {target=evt.srcElement;}
- return target;
- },
- stopPropagation:function(e){ //停止冒泡
- var evt=EventUtil.getEvent(e);
- if(evt.stopPropagation) {evt.stopPropagation();}
- else {evt.cancelBubble=true;}
- },
- preventDefault:function(e){ //阻值默认行为的发生
- var evt=EventUtil.getEvent(e);
- if(evt.preventDefault){ evt.preventDefault(); }
- else {e.returnValue=false;}
- }
- }
- (9)内存泄漏
- 内存泄漏指的是浏览器不能正常的回收内存的现象
- (10)浏览器的垃圾回收机制
- 垃圾收集器必须跟踪哪个变量有用哪个变量没用,对于不再有用的变量打上标记,以备将来收回其占用的内存,内存泄露和浏览器实现的垃圾回收机制息息相关, 而浏览器实现标识无用变量的策略主要有下两个方法:
- 第一,引用计数法
- 跟踪记录每个值被引用的次数。当声明一个变量并将引用类型的值赋给该变量时,则这个值的引用次数就是1。如果同一个值又被赋给另一个变量,则该值的引用次 数加1.相反,如果包含对这个值引用的变量又取得另外一个值,则这个值的引用次数减1.当这个值的引用次数变成0时,则说明没有办法访问这个值了,因此就 可以将其占用的内存空间回收回来。
- 如: var a = {}; //对象{}的引用计数为1
- b = a; //对象{}的引用计数为 1+1
- a = null; //对象{}的引用计数为2-1
- 所以这时对象{}不会被回收;
- IE 6, 7 对DOM对象进行引用计数回收, 这样简单的垃圾回收机制,非常容易出现循环引用问题导致内存不能被回收, 进行导致内存泄露等问题,一般不用引用计数法。
- 第二,标记清除法
- 到2008年为止,IE,Firefox,Opera,Chrome和Safari的javascript实现使用的都是标记清除式的垃圾收集策略(或类似的策略),只不过垃圾收集的时间间隔互有不同。
- 标记清除的算法分为两个阶段,标记(mark)和清除(sweep). 第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除。
- (11)同源策略
- 同源策略是浏览器有一个很重要的概念。所谓同源是指,域名,协议,端口相同。不同源的客户端脚本(javascript、ActionScript)在没明确授权的情况下,不能读写对方的资源。简单的来说,浏览器允许包含在页面A的脚本访问第二个页面B的数据资源,这一切是建立在A和B页面是同源的基础上。
- (12)跨域的几种方式
- jsonp(利用script标签的跨域能力)跨域、websocket(html5的新特性,是一种新协议)跨域、设置代理服务器(由服务器替我们向不同源的服务器请求数据)、CORS(跨源资源共享,cross origin resource sharing)、iframe跨域、postMessage(包含iframe的页面向iframe传递消息)
- (13)异步和同步
- 同步指下一个程序的执行需要等到上一个程序执行完毕,也就是得出结果后下一个才能执行,
- 异步指的是上一个程序指向后,下一个程序不用等到上一个程序出结果就能执行,等上一个出结果了调用回调函数处理结果就好。
- (14)JavaScript的值类型和引用类型
- JavaScript有两种类型的数据,值类型和引用类型,一般的数字,字符串,布尔值都是值类型,存放在栈中,而对象,函数,数组等是引用类型,存放在堆中,对引用类型的复制其实是引用复制,相当于复制着地址,对象并没有真正的复制。
- var a=5;var b=a;a=null; //那么b是5
- var a={},var b=a;b.name="mbj";
- console.log(a.name); //mbj,因为a,b指向同一个对象
- a=null;console.log(typeof b); //object,a=null,只是a不再指向该对象,但是这个对象还是在堆中确确实实的存在,b依然指向它。
- (15)优化下面代码
- var str="我喜欢我可爱的女朋友,";
- str=str+"她叫喵喵,";
- str=str+"她时而可爱,时而认真,";
- str=str+"她那天真的笑声可以让人忘掉一切烦恼。";
- console.log(str);
- 这里的优化主要是对加号操作符的优化,因为加号在JavaScript中非常耗时和耗内存,需要经过以下六步:
- 1、首先开辟一块临时空间,存储字符串,
- 2、然后在开辟一块空间
- 3、把str中的字符串复制到刚刚开辟的空间
- 4、在把需要连接的字符串复制到str后面
- 5、str指向这块空间
- 6、回收str原来的空间和临时空间
- 优化的方法是使用数组的push方法,数组是连续的存储空间,可以省下很多步
- var res=[];
- var str="我喜欢我可爱的女朋友,";
- res.push(str);
- res.push("她叫喵喵,");
- res.push("她时而可爱,时而认真,");
- res.push("她那天真的笑声可以让人忘掉一切烦恼。");
- console.log(res.join(""));
- (16)封装cookie的添加,删除,查询方法
- cookie是存储在浏览器端的,可以用于存储sessionID,也可以用于自动登陆,记住密码等,但是在浏览器端并没有官方的操作cookie的方法,下面我们来封装一下:
- CookieUtil={
- addCookie:function(key,value,options){
- var str=key+"="+escape(value);
- if(options.expires){
- var curr=new Date(); //options.expires的单位是小时
- curr.setTime(curr.getTime()+options.expires*3600*1000);
- options.expires=curr.toGMTString();
- }
- for(var k in options){ //有可能指定了cookie的path,cookie的domain
- str+=";"+k+"="+options[k];
- }
- document.cookie=str;
- },
- queryCookie:function(key){
- var cookies=document.cookie;
- //获得浏览器端存储的cookie,格式是key=value;key=value;key=value
- cookies+=";";
- var start=cookies.indexOf(key);
- if(start<=-1){ return null; } //说明不存在该cookie
- var end=cookies.indexOf(";",start);
- var value=cookies.slice(start+key.length+1,end);
- return unescape(value);
- },
- deleteCookie:function(key){
- var value=CookieUtil.queryCookie(key);
- if(value===null){return false;}
- CookieUtil.addCookie(key,value,{expires:0});//把过期时间设置为0,浏览器会马上自动帮我们删除cookie
- }
- }
- (17)事件委托机制
- 事件委托指的是,不再事件的发生地设立监听函数,而是在事件发生地的父元素或者祖先元素设置监听器函数,这样可以大大提高性能,因为可以减少绑定事件的元素,比如:
- <ul>
- <li></li>
- <li></li>
- <li></li>
- </ul>
- 要给li元素绑定click事件,使用事件委托机制的话,就只需要给ul绑定click事件就行了,这样就不需要给每个li'绑定click事件,减小内存占用,提高效率,有兴趣的童鞋可以去看看jQuery的live,bind,on,delegate函数的区别,这几个函数就采用了事件委托机制。
校招:
- 事件模型
- 闭包
- 原型链
- 事件模型
- DOM2级事件模型
- 闭包
- 原型链
- JavaScript有几种类型的值?(堆:原始数据类型和 栈:引用数据类型),你能画一下他们的内存图吗?
- Javascript创建对象的几种方式?
- 什么是window对象? 什么是document对象?
- 关于事件,IE与火狐的事件机制有什么区别? 如何阻止冒泡?
- 什么是闭包(closure),为什么要用它?
- javascript 代码中的”use strict”;是什么意思 ? 使用它区别是什么?
- 用原生JavaScript的实现过什么功能吗?
- Javascript中,有一个函数,执行时对象查找时,永远不会去查找原型,这个函数是?
- 对JSON的了解?
- [].forEach.call($$("*"),function(a){ a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).toString(16) }) 能解释一下这段代码的意思吗?
- 页面编码和被请求的资源编码如果不一致如何处理?
- AMD(Modules/Asynchronous-Definition)、CMD(Common Module Definition)规范区别?
- requireJS的核心原理是什么?(如何动态加载的?如何避免多次加载的?如何 缓存的?)
- 让你自己设计实现一个requireJS,你会怎么做?
- 谈一谈你对ECMAScript6的了解?
- .call() 和 .apply() 的含义和区别?
- 数组和对象有哪些原生方法,列举一下?
- JS 怎么实现一个类。怎么实例化这个类
- JavaScript中的作用域与变量声明提升?
- 如何编写高性能的Javascript?
- 3、JavaScript中有哪几种数据类型
- 答:
- JavaScript中有5种简单数据类型(也称为基本数据类型):Undefined、Null、Boolean、Number和String。还有1种复杂数据类型——Object,Object本质上是由一组无序的名值对组成的
- 4、回答以下输出的类型
- 答:
- ?
1 2 3 4 5 | alert(typeof(null));//object alert(typeof(NaN));//number alert(typeof(undefined));//undefined alert(typeof(“undefined”));//string alert(NaN == undefined);//false alert(NaN == NaN);//false |
- 5、用jquery和原生js获取元素中的内容
- 答:
- ?
1 2 | JS:document.getElementById(“div1”).innerHTML; document.querySelector(“#div1”).innerText; JQ:$(“#div1”).html() |
- 6、用原生js封装一个添加监听事件的兼容写法
- 答:
1 2 3 4 5 6 7 | function addEvent(obj,event,fn){ //现代:addEventLister 不用加on //ie:touchEvent 需要加on if (window.addEventListener){ obj.addEventListener(event,fn); }else{ obj.attachEvent("on"+event, fn); } } |
- 7、对跨域的理解和解决办法
- 答:
- 跨域简单的理解即为当前服务器目录下的前端需求要请求非本服务器(本域名)下的后台服务就称为跨域请求。跨域请求我们使用普通的ajax请求是无法进行的同源策略,一般来说位于 server1.example.com 的网页无法与不是 server2.example.com的服务器沟通,或者说如果在server1.example.com下想获取server2.example.com的话就得用跨域请求。
- 跨域的解决方法及解决:通过script标签请求,或者通过jQuery跨域
- 8、Ajax的原理
- 答:
- Ajax的原理简单来说通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面。
- XMLHttpRequest是ajax的核心机制,它是在IE5中首先引入的,是一种支持异步请求的技术。简单的说,也就是javascript可以及时向服务器提出请求和处理响应,而不阻塞用户。达到无刷新的效果。
- 9、jQuery库中的$()是什么
- 答:
- $()函数用于将任何对象包裹成jQuery对象,接着你就被允许调用定义在 jQuery对象上的多个不同方法。你甚至可以将一个选择器字符串传入$()函数,它会返回一个包含所有匹配的DOM元素数组的jQuery对象。
- 10、JavaScript的window.onload事件和jQuery的ready函数有何不同
- 答:
- JavaScript的window.onload事件和jQuery的ready函数之间的主要区别是,前者除了要等待DOM被创建还要等到包括大型图片、音频、视频在内的所有外部资源都完全加载。如果加载图片和媒体内容花费了大量时间,用户就会感受到定义在window.onload 事件上的代码在执行时有明显的延迟。
- 另一方面,jQuery的ready()函数只需对DOM树的等待,而无需对图像或外部资源加载的等待,从而执行起来更快。使用jQuery $(document).ready()的另一个优势是你可以在网页里多次使用它,浏览器会按它们在HTML页面里出现的顺序执行它们,相反对于onload技术而言,只能在单一函数里使用。鉴于这个好处,用jQuery的ready()函数比用JavaScript的window.onload 事件要更好些。
- 11、用原生js封装一个能获取元素到页面最上方和最左侧的函数,再用JQ封装一个同样的函数
- 答:
- 原生:
1 2 3 4 5 6 7 | function offset(obj){ var l = 0; var t = 0; while(obj){ l+=obj.offsetLeft; t+=obj.offsetTop; obj = obj.offsetParent; } return {left:l,top:t}; } |
- jQuery:
- $().offset().left;$().offset().top
- 12、如何实现一个EventEmitter
- 答:
- 主要分三步:定义一个子类,调用构造函数,继承EventEmitter
| var util = require('util'); var EventEmitter = require('events'); function MyEmitter() { EventEmitter.call(this); } // 构造函数 util.inherits(MyEmitter, EventEmitter); // 继承 var em = new MyEmitter(); em.on('hello', function(data) { console.log('收到事件hello的数据:', data); }); // 接收事件,并打印到控制台 em.emit('hello', 'EventEmitter传递消息真方便!'); |
- 13、如何通过stream实现一个文件的复制
- 答:
1 2 3 4 | var fs = require("fs"); var rs = fs.createReadStream(“1.jpg"); var ws = fs.createWriteStream("2.jpg"); rs.pipe(ws); |
22、事件委托是什么?
答:
利用事件冒泡的原理,使自己的所触发的事件,让它的父元素代替执行!
23、什么叫优雅降级和渐进增强?
答:
优雅降级:Web站点在所有新式浏览器中都能正常工作,如果用户使用的是老式浏览器,则代码会检查以确认它们是否能正常工作。由于IE独特的盒模型布局问题,针对不同版本的IE的hack实践过优雅降级了,为那些无法支持功能的浏览器增加候选方案,使之在旧式浏览器上以某种形式降级体验却不至于完全失效。
渐进增强:从被所有浏览器支持的基本功能开始,逐步地添加那些只有新式浏览器才支持的功能,向页面增加无害于基础浏览器的额外样式和功能的。当浏览器支持时,它们会自动地呈现出来并发挥作用。
24、JavaScript原型,原型链都是什么? 有什么特点?
答:
原型对象也是普通的对象,是对象一个自带隐式的 proto属性,原型也有可能有自己的原型,如果一个原型对象的原型不为null的话,我们就称之为原型链。
原型链是由一些用来继承和共享属性的对象组成的(有限的)对象链。
25、如何阻止事件冒泡和默认事件
答:
阻止冒泡:
现代浏览器:e.stopPropagation
低版本浏览器:e.cancelBubble=true
阻止默认事件:
现代浏览器:e.preventDefult()
低版本浏览器:return false
27、解释GET/POST的区别
答:
GET请求,请求的数据会附加在URL之后,以?分割URL和传输数据,多个参数用&连接。URL的编码格式采用的是ASCII编码,而不是uniclde,即是说所有的非ASCII字符都要编码之后再传输。
POST请求:POST请求会把请求的数据放置在HTTP请求包的包体中。
因此,GET请求的数据会暴露在地址栏中,而POST请求则不会。
关于传输数据的大小
在HTTP规范中,没有对URL的长度和传输的数据大小进行限制。但是在实际开发过程中,对于GET,特定的浏览器和服务器对URL的长度有限制。因此,在使用GET请求时,传输数据会受到URL长度的限制。
对于POST,由于不是URL传值,理论上是不会受限制的,但是实际上各个服务器会规定对POST提交数据大小进行限制,Apache、IIS都有各自的配置。
关于安全性
Get是Form的默认方法,安全性相对比较低
28、描述一下cookies,sessionStorage和localStorage的区别
答:
sessionStorage和localStorage是HTML5 Web Storage API 提供的,可以方便的在web请求之间保存数据。有了本地数据,就可以避免数据在浏览器和服务器间不必要地来回传递。
sessionStorage、localStorage、cookie都是在浏览器端存储的数据,其中 sessionStorage的概念很特别,引入了一个“浏览器窗口”的概念。sessionStorage 是在同源的同窗口(或tab)中,始终存在的数据。也就是说只要这个浏览器窗口没有关闭,即使刷新页面或进入同源另一页面,数据仍然存在。关闭窗口后,sessionStorage即被销毁。同时“独立”打开的不同窗口,即使是同一页面, sessionStorage对象也是不同的。cookies会发送到服务器端。其余两个不会。
Microsoft指出Internet Explorer 8增加cookie限制为每个域名50个,但IE7似乎也允许每个域名50个cookie。Firefox每个域名cookie限制为50个。Opera每个域名cookie限制为30个。Firefox和Safari允许cookie多达4097个字节,包括名name)、值(value)和等号。Opera许cookie多达4096个字节,包括:名(name)、值(value)和等号。Internet Explorer允许cookie多达4095 个字节,包括:名(name)、值(value)和等号。
区别:
Cookie:
- 每个域名存储量比较小(各浏览器不同,大致 4K )
- 所有域名的存储量有限制(各浏览器不同,大致 4K )
- 有个数限制(各浏览器不同)
- 会随请求发送到服务器
LocalStorage:
- 永久存储
- 单个域名存储量比较大(推荐 5MB ,各浏览器不同)
- 总体数量无限制
SessionStorage:
- 只在Session内有效
- 存储量更大(推荐没有限制,但是实际上各浏览器也不同)
1、谈谈你对Ajax的理解?(概念、特点、作用)
AJAX全称为“Asynchronous JavaScript And XML”(异步JavaScript和XML) 是指一种创建交互式网页应用的开发技术、改善用户体验,实现无刷新效果。
优点
a、不需要插件支持
b、优秀的用户体验
c、提高Web程序的性能
d、减轻服务器和带宽的负担
缺点
a、浏览器对XMLHttpRequest对象的支持度不足,几乎所有浏览器现在都支持
b、破坏浏览器“前进”、“后退”按钮的正常功能,可以通过简单的插件弥补
c、对搜索引擎的支持不足
2、说说你对延迟对象deferred的理解?
deferred对象是从jQuery 1.5.0版本开始引入的一个新功能。
a、什么是deferred对象
开发网站的过程中,我们经常遇到某些耗时很长的javascript操作。其中,既有异步的操作(比如ajax读取服务器数据),也有同步的操作(比如遍历一个大型数组),它们都不是立即能得到结果的。
通常的做法是,为它们指定回调函数(callback)。即事先规定,一旦它们运行结束,应该调用哪些函数。
但是,在回调函数方面,jQuery的功能非常弱。为了改变这一点,jQuery开发团队就设计了deferred对象。
简单说,deferred对象就是jQuery的回调函数解决方案。在英语中,defer的意思是"延迟",所以deferred对象的含义就是"延迟"到未来某个点再执行。
它解决了如何处理耗时操作的问题,对那些操作提供了更好的控制,以及统一的编程接口。
b、它的主要功能,可以归结为四点:
(1)、实现链式操作
(2)、指定同一操作的多个回调函数
(3)、为多个操作指定回调函数
(4)、普通操作的回调函数接口
3、什么是跨域,如何实现跨域访问?
跨域是指不同域名之间相互访问。
JavaScript同源策略的限制,A域名下的JavaScript无法操作B或是C域名下的对象
(1)、JSONP跨域:利用script脚本允许引用不同域下的js实现的,将回调方法带入服务器,返回结果时回调。
(2)、跨域资源共享(CORS)
跨域资源共享(CORS)是一种网络浏览器的技术规范,它为Web服务器定义了一种方式,允许网页从不同的域访问其资源。
CORS与JSONP相比:
a、 JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。
b、 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。
c、 JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS。
4、为什么要使用模板引擎?
a、模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。
b、在一些示例中javascript有大量的html字符串,html中有一些像onclick样的javascript,这样javascript中有html,html中有javascript,代码的偶合度很高,不便于修改与维护,使用模板引擎可以解决问题。
5、JavaScript是一门什么样的语言,它有哪些特点?
JavaScript 是一种脚本语言,官方名称为 ECMAScript(因定义语言的标准为 ECMA-262)。
JS 的主要特点:
a、语法类似于常见的高级语言,如 C 和 Java;
b、脚本语言,不需要编译就可以由解释器直接运行;
c、 变量松散定义,属于弱类型语言;
d、面向对象的。
JS 最初是为网页设计而开发的,现在也是Web 开发的重要语言。它支持对浏览器(浏览器对象模型,BOM)和HTML 文档(文档对象模型,DOM)进行操作而使网页呈现动态的交互特性。
严格的说,JS只是ECMAScript 的一种实现,是ECMAScript和BOM、DOM组成的一种Web 开发技术。
6、JavaScript的数据类型有哪些?
基本数据类型:字符串 String、数字 Number、布尔Boolean
复合数据类型:数组 Array、对象 Object
特殊数据类型:Null 空对象、Undefined 未定义
7、已知ID的Input输入框,如何获取这个输入框的输入值?(不使用第三方框架)
document.getElementById("ID").value
8、根据你的理解,请简述JavaScript脚本的执行原理?
JavaScript是一种动态、弱类型、基于原型的语言,通过浏览器可以直接执行。
当浏览器遇到<script> 标记的时候,浏览器会执行之间的javascript代码。嵌入的js代码是顺序执行的,每个脚本定义的全局变量和函数,都可以被后面执行的脚本所调用。 变量的调用,必须是前面已经声明,否则获取的变量值是undefined。
9、DOM操作怎样添加、移除、移动、复制、创建和查找节点?
(1)创建新节点
1 2 3 | createDocumentFragment() //创建一个DOM片段 createElement() //创建一个具体的元素 createTextNode() //创建一个文本节点 |
(2)添加、移除、替换、插入
1 2 3 4 | appendChild() removeChild() replaceChild() insertBefore() //在已有的子节点前插入一个新的子节点 |
(3)查找
1 2 3 | getElementsByTagName() //通过标签名称 getElementsByName() //通过元素的Name属性的值(IE容错能力较强,会得到一个数组,其中包括id等于name值的) getElementById() //通过元素Id,唯一性 |
10、说说你对json的理解?
回答一:
a、JSON对象:以“{”开始,以“}”结束,里面则是一系列的键(key)值(value)对,键和值用“:”分开,每对键值对之间用“,”分开。参考以下语法结构:{key1:value1,key2:value2,key3:value3…}其中键(key)是字符串,而值(value)可以是字符串,数值,true,false,null,对象或数组,也就是说某个键(key)的值(value)可以是一个数组,数组里面又是一些JSON对象,这种表示稍微复杂一些,但是参照这些理解可以很容易分辨出来。
b、JSON数组:以”[”开始,”]”结束,如同程序语言一样,例如C#,Button[] btnArray,则BtnArray是一个Button类型的数组,里面就存放Button类型的对象,那么JSON数组也一样,里面存放的也是JSON对象.
回答二:
a、JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
b、JSON 是轻量级的文本数据交换格式,并不是编程语言
c、JSON 独立于语言存在
d、JSON 具有自我描述性,更易理解
e、JSON 可以将 JavaScript 对象中表示的一组数据转换为字符串,然后就可以在函数之间轻松地传递这个字符串,或者在异步应用程序中将字符串从 Web 客户机传递给服务器端程序。这个字符串看起来有点儿古怪,但是JavaScript很容易解释它,而且 JSON 可以表示比"名称 / 值对"更复杂的结构。例如,可以表示数组和复杂的对象,而不仅仅是键和值的简单列表
回答三:
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。
它是基于JavaScript的一个子集。数据格式简单, 易于读写, 占用带宽小.
json简单说就是javascript中的对象和数组,所以这两种结构就是对象和数组两种结构,通过这两种结构可以表示各种复杂的结构。
(1)、对象:对象在js中表示为“{}”括起来的内容,数据结构为 {key:value,key:value,...}的键值对的结构,在面向对象的语言中,key为对象的属性,value为对应的属性值,所以很容易理解,取值方法为 对象.key 获取属性值,这个属性值的类型可以是 数字、字符串、数组、对象几种。
(1)、数组:数组在js中是中括号“[]”括起来的内容,数据结构为 ["java","javascript","vb",...],取值方式和所有语言中一样,使用索引获取,字段值的类型可以是数字、字符串、数组、对象几种。
经过对象、数组2种结构就可以组合成复杂的数据结构了。
11、ionic和angularjs的区别?
a、ionic是一个用来开发混合手机应用的,开源的,免费的代码库。可以优化html、css和js的性能,构建高效的应用程序,而且还可以用于构建Sass和AngularJS的优化。
b、AngularJS通过新的属性和表达式扩展了HTML。AngularJS可以构建一个单一页面应用程序(SPAs:Single Page Applications)。
c、Ionic是一个混合APP开发工具,它以AngularJS为中间脚本工具(称为库,似乎又不恰当),所以,你如果要使用Ionic开发APP,就必须了解AngularJS。
12、谈谈你对闭包的理解?
(1)、使用闭包主要是为了设计私有的方法和变量。闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。
(2)、闭包有三个特性:
a、函数嵌套函数
b、函数内部可以引用外部的参数和变量
c、参数和变量不会被垃圾回收机制回收
13、谈谈你This对象的理解?
回答一:
(1)、js的this指向是不确定的,也就是说是可以动态改变的。call/apply 就是用于改变this指向的函数,这样设计可以让代码更加灵活,复用性更高
(2)、this 一般情况下,都是指向函数的拥有者。
(3)、在函数自执行里,this 指向的是 window 对象。
扩展:关于this,还有一个地方比较让人模糊的是在dom事件里,通常有如下3种情况:
a、使用标签属性注册事件,此时this指向的是window对象。
b、对与a,要让this指向input,可以将this作为参数传递。
c、使用addEventListener等注册事件。此时this也是指向 input。
回答二:
(1)、处于全局作用域下的this:
1 2 3 | this;/*window*/ var a = {name: this}/*window*/ var b = [this];/*window*/ |
在全局作用域下,this默认指向window对象。
(2)、处在函数中的this,又分为以下几种情况:
a、一般定义的函数,然后一般的执行:
1 2 3 4 | var a = function(){ console.log(this); } a();/*window*/ |
this还是默认指向window。
b、一般定义,用new调用执行:
1 2 3 4 | var a = function(){ console.log(this); } new a();/*新建的空对象*/ |
这时候让this指向新建的空对象,我们才可以给空对象初始化自有变量
c、作为对象属性的函数,调用时:
1 2 3 4 5 6 | var a = { f:function(){ console.log(this) } } a.f();/*a对象*/ |
这时候this指向调用f函数的a对象。
(3)、通过call()和apply()来改变this的默认引用:
1 2 3 4 5 6 7 | var b = {id: 'b'}; var a = { f:function(){ console.log(this) } } a.f.call(b);/*window*/ |
所有函数对象都有的call方法和apply方法,它们的用法大体相似,f.call(b);的意思 是,执行f函数,并将f函数执行期活动对象里的this指向b对象,这样标示符解析时,this就会是b对象了。不过调用函数是要传参的。所以,f.call(b, x, y); f.apply(b, [x, y]);好吧,以上就是用call方法执行f函数,与用apply方法执行f函数时传参方式,它们之间的差异,大家一目了然:apply通过数组的方式传递参数,call通过一个个的形参传递参数。
(4)、一些函数特殊执行情况this的指向问题:
a、setTimeout()和setInverval():
1 2 3 4 | var a = function(){ console.log(this); } setTimeout(a,0);/*window*/ |
setInterval()类似。
b、dom模型中触发事件的回调方法执行中活动对象里的this指向该dom对象。
14、JavaScript对象的几种创建方式?
(1) var obj = new Object();
(1) 工厂模式
1 2 3 4 5 6 7 | function Parent(){ var Child = new Object(); Child.name="欲泪成雪"; Child.age="20"; return Child; }; var x = Parent(); |
引用该对象的时候,这里使用的是 var x = Parent()而不是 var x = new Parent();因为后者会可能出现很多问题(前者也成为工厂经典方式,后者称之为混合工厂方式),不推荐使用new的方式使用该对象
(2)构造函数方式
1 2 3 4 5 | function Parent(){ this.name="欲泪成雪"; this.age="20"; }; var x =new Parent(); |
(3) 原型模式
1 2 3 4 5 | function Parent(){ }; Parent.prototype.name="欲泪成雪"; Parent.prototype.age="20"; var x =new Parent(); |
(4)混合的构造函数,原型方式(推荐)
1 2 3 4 5 6 7 8 | function Parent(){ this.name="欲泪成雪"; this.age=22; }; Parent.prototype.lev=function(){ return this.name; }; var x =new Parent(); |
(5)动态原型方式
1 2 3 4 5 6 7 8 9 | function Parent(){ this.name="欲泪成雪"; this.age=22; ; if(typeof Parent._lev=="undefined"){ Parent.prototype.lev=function(){ return this.name; } Parent._lev=true; } }; var x =new Parent(); |
15、get和post的区别,何时使用post?
(1)、get 是从服务器上获取数据,post 是向服务器传送数据。 get 请求返回 request - URI 所指出的任意信息。
Post 请求用来发送电子邮件、新闻或发送能由交互用户填写的表格。这是唯一需要在请求中发送body的请求。使用Post请求时需要在报文首部 Content - Length 字段中指出body的长度。
(2)、get 是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到。post是通过HTTP post机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址,用户看不到这个过程。
(3)、对于 get 方式,服务器端用Request.QueryString获取变量的值,对于 post 方式,服务器端用Request.Form获取提交的数据。
(4)、get 传送的数据量较小,不能大于2KB。post 传送的数据量较大,一般被默认为不受限制。但理论上,IIS4中最大量为80KB,IIS5中为100KB。 用IIS过滤器的只接受get参数,所以一般大型搜索引擎都是用get方式。
(5)get安全性非常低,post 安全性相对较高。如果这些数据是中文数据而且是
非敏感数据,那么使用get;如果用户输入的数据不是中文字符而且包含敏感数据,那么还是使用 post 为好。
16、null和undefined的区别?
(1)、null是一个表示"无"的对象,转为数值时为0;undefined是一个表示"无"的原始值,转为数值时为NaN。当声明的变量还未被初始化时,变量的默认值为undefined。
(2)、null用来表示尚未存在的对象,常用来表示函数企图返回一个不存在的对象。
(3)、undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。典型用法是:
a、变量被声明了,但没有赋值时,就等于undefined。
b、调用函数时,应该提供的参数没有提供,该参数等于undefined。
c、对象没有赋值的属性,该属性的值为undefined。
d、函数没有返回值时,默认返回undefined。
(4)、null表示"没有对象",即该处不应该有值。典型用法是:
a、作为函数的参数,表示该函数的参数不是对象。
b、作为对象原型链的终点。
17、请写出js内存泄漏的问题?
回答一:
(1)、IE7/8 DOM对象或者ActiveX对象循环引用导致内存泄漏
a、多个对象循环引用
b、循环引用自己
(2)、基础的DOM泄漏
当原有的DOM被移除时,子结点引用没有被移除则无法回收。
(3)、timer定时器泄漏
这个时候你无法回收buggyObject,解决办法,先停止timer然后再回收
回答二:
内存泄漏指任何对象在您不再拥有或需要它之后仍然存在。
垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为 0(没有其他对象引用过该对象),或对该对象的惟一引用是循环的,那么该对象的内存即可回收。
setTimeout 的第一个参数使用字符串而非函数的话,会引发内存泄漏。
闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)也会引发内存泄漏问题。
18、哪些地方会出现css阻塞,哪些地方会出现js阻塞?
js的阻塞特性:所有浏览器在下载JS的时候,会阻止一切其他活动,比如其他资源的下载,内容的呈现等等。直到JS下载、解析、执行完毕后才开始继续并行下载其他资源并呈现内容。为了提高用户体验,新一代浏览器都支持并行下载JS,但是JS下载仍然会阻塞其它资源的下载(例如.图片,css文件等)。
由于浏览器为了防止出现JS修改DOM树,需要重新构建DOM树的情况,所以就会阻塞其他的下载和呈现。
嵌入JS会阻塞所有内容的呈现,而外部JS只会阻塞其后内容的显示,2种方式都会阻塞其后资源的下载。也就是说外部样式不会阻塞外部脚本的加载,但会阻塞外部脚本的执行。
CSS怎么会阻塞加载?CSS本来是可以并行下载的,在什么情况下会出现阻塞加载了(在测试观察中,IE6下CSS都是阻塞加载)
当CSS后面跟着嵌入的JS的时候,该CSS就会出现阻塞后面资源下载的情况。而当把嵌入JS放到CSS前面,就不会出现阻塞的情况了。
根本原因:因为浏览器会维持html中css和js的顺序,样式表必须在嵌入的JS执行前先加载、解析完。而嵌入的JS会阻塞后面的资源加载,所以就会出现上面CSS阻塞下载的情况。
JS应该放在什么位置?
(1)、放在底部,虽然放在底部照样会阻塞所有呈现,但不会阻塞资源下载。
(2)、如果嵌入JS放在head中,请把嵌入JS放在CSS头部。
(3)、使用defer(只支持IE)
(4)、不要在嵌入的JS中调用运行时间较长的函数,如果一定要用,可以用`setTimeout`来调用
Javascript无阻塞加载具体方式
将脚本放在底部。<link>还是放在head中,用以保证在js加载前,能加载出正常显示的页面。<script>标签放在</body>前。
成组脚本:由于每个<script>标签下载时阻塞页面解析过程,所以限制页面的<script>总数也可以改善性能。适用于内联脚本和外部脚本。
非阻塞脚本:等页面完成加载后,再加载js代码。也就是,在window.onload事件发出后开始下载代码。
(1)defer属性:支持IE4和fierfox3.5更高版本浏览器
(2)动态脚本元素:文档对象模型(DOM)允许你使用js动态创建HTML的几乎全部文档内容。代码如下:
1 2 3 4 5 | <script> var script=document.createElement("script"); script.type="text/javascript"; script.src="file.js"; document.getElementsByTagName("head")[0].appendChild(script); </script> |
此技术的重点在于:无论在何处启动下载,文件额下载和运行都不会阻塞其他页面处理过程。即使在head里(除了用于下载文件的http链接)。
19、对比Flash与ajax哪个好,在使用中如何取舍?
Ajax的优势:
(1)、可搜索性
普通的文本网页会更有利于SEO。文本内容是搜索引擎容易检索的,而繁琐的swf字节码却是搜索引擎不愿触及的。虽然Google等一些大型的搜索引擎可以检索SWF内部的内容,但是仍然有很多麻烦存在。
(2)、开放性
Flash常年以来被Macromedia看的很死。包括Flex、FMS等辅佐技术一直都需要昂贵的安装、维护费用。而JS则没有这样的麻烦。没有人愿意承担法律和版权的风险。
费用
Flash开发是很昂贵的,因为FlashIDE等环境都是要收费的.而Ajax则不同.虽然有一些便宜的生成swf的工具,但是他们的工能实在无法满足复杂需求。
(3)、易用性
Ajax程序有更好的易用性。由于中间有一层Flashplayer代理层,因此许多辅助功能无法被Flash灵活利用。而且Flash在一些方面有着不好的口碑。比如弹出广告、比如恶意代码。
(awflasher.com个人认为这八成是乱上xx网站造成的)
(4)、易于开发
人们开发复杂的Ajax和Flash应用程序时,都会借助一些高级的开发工具。普遍来说,Ajax的开发包比Flash简便、容易。
Flash的优势:
(1)、多媒体处理
Flash在音频、视频等多媒体领域相比HTML有绝对的优势。现在几乎所有的网站都包含有Flash内容。
(2)、兼容性
兼容性好:由于通过了唯一的FlashPlayer“代理”。人们不必像调试JS那样,在不同的浏览器中调试程序。
(3)、矢量图型
这是Flash最大的优势,同样处在这一领域的SVG、Canvas element以及Direct完全不能与Flash相比。
(4)、客户端资源调度
Flash能够更容易的调用浏览器以外的外部资源。比如摄像头、麦克风等。然而这是普通的HTML无法完成的。但是这也许是一个缺点(为什么呢?)
Ajax的劣势:
(1)、它可能破坏浏览器的后退功能
(2)、使用动态页面更新使得用户难于将某个特定的状态保存到收藏夹中 ,不过这些都有相关方法解决。
Flash的劣势:
(1)、二进制格式
(2)、格式私有
(3)、flash 文件经常会很大,用户第一次使用的时候需要忍耐较长的等待时间
(4)/性能问题
ajax与flash各有利弊,到底哪个好,这取决于你的需求
20、请你解释一下事件冒泡机制?
a、在一个对象上触发某类事件(比如单击onclick事件),如果此对象定义了此事件的处理程序,那么此事件就会调用这个处理程序,如果没有定义此事件处理程序或者事件返回true,那么这个事件会向这个对象的父级对象传播,从里到外,直至它被处理(父级对象所有同类事件都将被激活),或者它到达了对象层次的最顶层,即document对象(有些浏览器是window)。
b、冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发
c、js冒泡机制是指如果某元素定义了事件A,如click事件,如果触发了事件之后,没有阻止冒泡事件,那么事件将向父级元素传播,触发父类的click函数。
1 2 3 4 | //阻止冒泡时间方法,兼容ie(e.cancleBubble)和ff(e.stopProgation) function stopBubble(e){ var evt = e||window.event; evt.stopPropagation?evt.stopPropagation():(evt.cancelBubble=true);//阻止冒泡 evt.preventDefault |
21、请你说说split()与join() 函数的区别?
前者是切割成数组的形式,后者是将数组转换成字符串
Join 函数获取一批字符串,然后用分隔符字符串将它们联接起来,从而返回一个字符串。Split 函数获取一个字符串,然后在分隔符处将其断开,从而返回一批字符串。但是,这两个函数之间的主要区别在于 Join 可以使用任何分隔符字符串将多个字符串连接起来,而 Split 只能使用一个字符分隔符将字符串断开。
简单地说,如果你用split,是把一串字符(根据某个分隔符)分成若干个元素存放在一个数组里。而Join是把数组中的字符串连成一个长串,可以大体上认为是split的逆操作。
22、说说你对Promise的理解?
ES6 原生提供了 Promise 对象。
所谓 Promise,就是一个对象,用来传递异步操作的消息。它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的 API,可供进一步处理。
Promise 对象有以下两个特点。
(1)、对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和 Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就是「承诺」,表示其他手段无法改变。
(2)、一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。
Promise 也有一些缺点。首先,无法取消 Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
23、谈谈你对Javascript垃圾回收机制的理解?
(1)、标记清除(mark and sweep)
这是`JavaScript`最常见的垃圾回收方式,当变量进入执行环境的时候,比如函数中声明一个变量,垃圾回收器将其标记为“进入环境”,当变量离开环境的时候(函数执行结束)将其标记为“离开环境”。
垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了
(2)、引用计数(reference counting)
在低版本`IE`中经常会出现内存泄露,很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数,当声明了一个 变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加1,如果该变量的值变成了另外一个,则这个值得引用次数减1,当这个值的引用次数变为0的时 候,说明没有变量在使用,这个值没法被访问了,因此可以将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为0的值占用的空间。
在IE中虽然`JavaScript`对象通过标记清除的方式进行垃圾回收,但BOM与DOM对象却是通过引用计数回收垃圾的,也就是说只要涉及BOM及DOM就会出现循环引用问题。
24、说说你对原型(prototype)理解?
JavaScript是一种通过原型实现继承的语言与别的高级语言是有区别的,像java,C#是通过类型决定继承关系的,JavaScript是的动态的弱类型语言,总之可以认为JavaScript中所有都是对象,在JavaScript中,原型也是一个对象,通过原型可以实现对象的属性继承,JavaScript的对象中都包含了一个" prototype"内部属性,这个属性所对应的就是该对象的原型。
"prototype"作为对象的内部属性,是不能被直接访问的。所以为了方便查看一个对象的原型,Firefox和Chrome内核的JavaScript引擎中提供了"__proto__"这个非标准的访问器(ECMA新标准中引入了标准对象原型访问器"Object.getPrototype(object)")。
原型的主要作用就是为了实现继承与扩展对象。
25、typeof与instanceof的区别是什么?
在 JavaScript 中,判断一个变量的类型可以用typeof
(1)、数字类型, typeof 返回的值是 number。比如说:typeof(1),返回值是number
(2)、字符串类型, typeof 返回的值是 string。比如typeof("123")返回值是string。
(3)、布尔类型, typeof 返回的值是 boolean 。比如typeof(true)返回值是boolean。
(4)、对象、数组、null 返回的值是 object 。比如typeof(window),typeof(document),typeof(null)返回的值都是object。
(5)、函数类型,返回的值是 function。比如:typeof(eval),typeof(Date)返回的值都是function。
(6)、不存在的变量、函数或者undefined,将返回undefined。比如:typeof(abc)、typeof(undefined)都返回undefined。
在 JavaScript 中,instanceof用于判断某个对象是否被另一个函数构造。
使用 typeof 运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回 "object"。ECMAScript 引入了另一个 Java 运算符 instanceof 来解决这个问题。instanceof 运算符与 typeof 运算符相似,用于识别正在处理的对象的类型。与 typeof 方法不同的是,instanceof 方法要求开发者明确地确认对象为某特定类型。
26、说说你对node.js的理解?
a、Node.js 是一个基于Google Chrome V8 引擎的 JavaScript 运行环境。Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。Node.js 的包管理器 npm,是全球最大的开源库生态系统。
b、能方便地搭建响应速度快、易于扩展的网络应用,Node.js 使用事件驱动, 非阻塞I/O 模型而得以轻量和高效,非常适合在分布式设备上运行的数据密集型的实时应用。
c、简单说Node.js就是运行在服务器端的JavaScript,是现在流行的语言中能同时运行在前端与后台的程序语言
27、NPM(包管理器)作用是什么?
NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,常见的使用场景有以下几种:
a、允许用户从NPM服务器下载别人编写的第三方包到本地使用。
b、允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
c、允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。
28、请简要说说你对Javascript面向对象的理解?
为了说明 JavaScript 是一门彻底的面向对象的语言,首先有必要从面向对象的概念着手 , 探讨一下面向对象中的几个概念:
a、一切事物皆对象
b、对象具有封装和继承特性
c、对象与对象之间使用消息通信,各自存在信息隐藏
以这三点做为依据,C++ 是半面向对象半面向过程语言,因为,虽然他实现了类的封装、继承和多态,但存在非对象性质的全局函数和变量。Java、C# 是完全的面向对象语言,它们通过类的形式组织函数和变量,使之不能脱离对象存在。但这里函数本身是一个过程,只是依附在某个类上。
然而,面向对象仅仅是一个概念或者编程思想而已,它不应该依赖于某个语言存在。比如 Java 采用面向对象思想构造其语言,它实现了类、继承、派生、多态、接口等机制。但是这些机制,只是实现面向对象编程的一种手段,而非必须。换言之,一门语言可以根据其自身特性选择合适的方式来实现面向对象。所以,由于大多数程序员首先学习或者使用的是类似 Java、C++ 等高级编译型语言(Java 虽然是半编译半解释,但一般做为编译型来讲解),因而先入为主地接受了“类”这个面向对象实现方式,从而在学习脚本语言的时候,习惯性地用类式面向对象语言中的概念来判断该语言是否是面向对象语言,或者是否具备面向对象特性。这也是阻碍程序员深入学习并掌握 JavaScript 的重要原因之一。
实际上,JavaScript 语言是通过一种叫做 原型(prototype)的方式来实现面向对象编程的。下面就来讨论 基于类的(class-based)面向对象和 基于原型的 (prototype-based) 面向对象这两种方式在构造客观世界的方式上的差别。
基于类的面向对象和基于原型的面向对象方式比较在基于类的面向对象方式中,对象(object)依靠类(class)来产生。而在基于原型的面向对象方式中,对象(object)则是依靠 构造器(constructor)利用 原型(prototype)构造出来的。举个客观世界的例子来说明二种方式认知的差异。例如工厂造一辆车,一方面,工人必须参照一张工程图纸,设计规定这辆车应该如何制造。这里的工程图纸就好比是语言中的 类 (class),而车就是按照这个 类(class)制造出来的;另一方面,工人和机器 ( 相当于 constructor) 利用各种零部件如发动机,轮胎,方向盘 ( 相当于 prototype 的各个属性 ) 将汽车构造出来。
事实上关于这两种方式谁更为彻底地表达了面向对象的思想,目前尚有争论。但笔者认为原型式面向对象是一种更为彻底的面向对象方式,理由如下:
(1)、首先,客观世界中的对象的产生都是其它实物对象构造的结果,而抽象的“图纸”是不能产生“汽车”的,也就是说,类是一个抽象概念而并非实体,而对象的产生是一个实体的产生;
(2)、其次,按照一切事物皆对象这个最基本的面向对象的法则来看,类 (class) 本身并不是一个对象,然而原型方式中的构造器 (constructor) 和原型 (prototype) 本身也是其他对象通过原型方式构造出来的对象。
(3)、再次,在类式面向对象语言中,对象的状态 (state) 由对象实例 (instance) 所持有,对象的行为方法 (method) 则由声明该对象的类所持有,并且只有对象的结构和方法能够被继承;而在原型式面向对象语言中,对象的行为、状态都属于对象本身,并且能够一起被继承(参考资源),这也更贴近客观实际。
(4)、最后,类式面向对象语言比如 Java,为了弥补无法使用面向过程语言中全局函数和变量的不便,允许在类中声明静态 (static) 属性和静态方法。而实际上,客观世界不存在所谓静态概念,因为一切事物皆对象!而在原型式面向对象语言中,除内建对象 (build-in object) 外,不允许全局对象、方法或者属性的存在,也没有静态概念。
所有语言元素 (primitive) 必须依赖对象存在。但由于函数式语言的特点,语言元素所依赖的对象是随着运行时 (runtime) 上下文 context变化而变化的,具体体现在this指针的变化。正是这种特点更贴近“万物皆有所属,宇宙乃万物生存之根本”的自然观点。在程序清单 1中 window 便类似与宇宙的概念。
29、你对JavaScript函数的理解是?
javascript中的函数就是对象,对象就是“键/值”对的集合并拥有一个连接到原型对隐藏连接。消
(1)、参数对象 (arguments)
第一个函数中有一个默认对象叫arguments,类似数组,但不是数组,该对象是传递给函数的参数。
(2)、构造函数
在javascript中对象构造函数可以创建一个对象。
(3)、函数调用
a、call:调用一个对象的一个方法,以另一个对象替换当前对象
b、apply:应用某一对象的一个方法,用另一个对象替换当前对象,与call类似。
c、caller:在一个函数调用另一个函数时,被调用函数会自动生成一个caller属性,指向调用它的函数对象。如果该函数当前未被调用,或并非被其他函数调用,则caller为null。
d、Callee:当函数被调用时,它的arguments.callee对象就会指向自身,也就是一个
对自己的引用。
30、简要说说什么是IIFE?它有什么作用?
IIFE即Immediately-Invoked Function Expression,立即执行函数表达式, 立即执行的函数表达式的执行括号应该写在外包括号内。虽然写在内还是写在外都是有效的,但写在内使得整个表达式看起来更像一个整体,因此推荐这么做。
| //最常用的两种写法 (function(){ /* code */ }()); // 老师推荐写法 (function(){ /* code */ })(); // 当然这种也可以
// 括号和JS的一些操作符(如 = && || ,等)可以在函数表达式和函数声明上消除歧义 // 如下代码中,解析器已经知道一个是表达式了,于是也会把另一个默认为表达式 // 但是两者交换则会报错 var i = function(){ return 10; }(); true && function(){ /* code */ }(); 0, function(){ /* code */ }();
// 如果你不怕代码晦涩难读,也可以选择一元运算符 !function(){ /* code */ }(); ~function(){ /* code */ }(); -function(){ /* code */ }(); +function(){ /* code */ }();
// 你也可以这样 new function(){ /* code */ } new function(){ /* code */ }() // 带参 |
IIFE的作用
(1)、提高性能:减少作用域查找时间。使用IIFE的一个微小的性能优势是通过匿名函数的参数传递常用全局对象window、document、jQuery,在作用域内引用这些全局对象。JavaScript解释器首先在作用域内查找属性,然后一直沿着链向上查找,直到全局范围。将全局对象放在IIFE作用域内提升js解释器的查找速度和性能。
(2)、压缩空间:通过参数传递全局对象,压缩时可以将这些全局对象匿名为一个更加精简的变量名
(3)、避免冲突:匿名函数内部可以形成一个块级的私有作用域。
(4)、依赖加载:可以灵活的加载第三方插件,当然使用模块化加载更好(AMD,CMD)
31、谈谈你对Function与Object的理解?
Function
函数就是对象,代表函数的对象就是函数对象。所有的函数对象是被Function这个函数对象构造出来的。Function是最顶层的构造器。它构造了系统中所有的对象,包括用户自定义对象,系统内置对象,甚至包括它自已。这也表明Function具有自举性(自已构造自己的能力)。这也间接决定了Function的call和constructor逻辑相同。每个对象都有一个 constructor 属性,用于指向创建其的函数对象。
a、函数与对象具有相同的语言地位
b、没有类,只有对象
c、函数也是一种对象,所谓的函数对象
d、对象是按引用来传递的
Object
对于Object它是最顶层的对象,所有的对象都将继承Object的原型,但是你也要明确的知道Object也是一个函数对象,所以说Object是被Function构造出来的。
32、$.extend与$.fn.extend区别是什么?
$.extend
在jQuery根命名空间下直接调用的方法可以认为是jQuery的静态方法或属性,常常使用方法名来调用,使用.方法名来调用,使用.extend这个静态方法可以完成两个功能:
a、扩展属性或方法给jQuery
b、扩展对象
$.fn.extend
.fn就是jQuery的原型,.fn等于jQuery.prototype,是jQuery的别名。.fn.extend方法的作用是用于扩展jQuery实例对象,也就是我们从页面中获得的jQuery对象。
.fn扩展了jQuery的原型,让所有的jQuery实例对象都得到的扩展的方法,其它也可以直接修改jQuery.prototype来实现,.fn是jQuery.prototype的简写
33、什么是链式编程?
几乎在所有基于“类型”的语言中如果调用一个方法后将对象作为方法参数返回则就会形成链式编程
链式编程是将多个操作(多行代码)通过点号"."链接在一起成为一句代码。 链式代码通常要求操作有返回值, 但对于很多操作大都是void型,什么也不返回,这样就很难链起来了, 当然也有解决办法,可能不太优雅。 链式编程的新思想在jQuery中已流行使用
示例:
1 2 3 4 5 | return $.each(this, function(index, obj) { $("<span/>").html("+").css("cursor", "pointer").click(function() { $(obj).width($(obj).width() + length); }).insertAfter(obj); }); |
上面的示例中当$.each循环完成后返回this对象,返回的仍然是一个jQuery对象,所以可以继续jQuery编程。
$("button").SuperPlus(10).height(26).width(100).css("color","blue");
34、请指出 JavaScript中的本地对象、内置对象、宿主对象的区别?
(1)、本地对象
ECMA-262 把本地对象(native object)定义为“独立于宿主环境的 ECMAScript 实现提供的对象”。
再来看一下,“本地对象”包含哪些内容:
Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError
由此可以看出,简单来说,本地对象就是 ECMA-262 定义的类(引用类型)。
(2)、内置对象
ECMA-262 把内置对象(built-in object)定义为“由 ECMAScript 实现提供的、独立于宿主环境的所有对象,在 ECMAScript 程序开始执行时出现”。这意味着开发者不必明确实例化内置对象,它已被实例化了。
同样是“独立于宿主环境”。根据定义我们似乎很难分清“内置对象”与“本地对象”的区别。而ECMA-262 只定义了两个内置对象,即 Global 和 Math (它们也是本地对象,根据定义,每个内置对象都是本地对象)。
如此就可以理解了。内置对象是本地对象的一种。而其包含的两种对象中,Math对象我们经常用到,可这个Global对象是啥东西呢?
Global对象是ECMAScript中最特别的对象,因为实际上它根本不存在,但大家要清楚,在ECMAScript中,不存在独立的函数,所有函数都必须是某个对象的方法。类似于isNaN()、parseInt()和parseFloat()方法等,看起来都是函数,而实际上,它们都是Global对象的方法。
(3)、宿主对象
由ECMAScript实现的宿主环境提供的对象,即我们网页的运行环境(操作系统和浏览器),所有的BOM和DOM都是宿主对象。
宿主环境提供的全局方法:
alert、confirm、prompt、write、writeln(后面的两种是document的方法)
内置对象是本地对象的一种,本地对象时由官方定义的,而宿主对象相当于由自己定义的对象、DOM对象和BOM对象组成的
35、请解释一下变量声明提升?
a、变量定义
可以使用var定义变量,变量如果没有赋值,那变量的初始值为undefined。
b、变量作用域
变量作用域指变量起作用的范围。变量分为全局变量和局部变量。全局变量在全局都拥有定义;而局部变量只能在函数内有效。
在函数体内,同名的局部变量或者参数的优先级会高于全局变量。也就是说,如果函数内存在和全局变量同名的局部变量或者参数,那么全局变量将会被局部变量覆盖。
所有不使用var定义的变量都视为全局变量。
44 个 JavaScript 变态题解析
第1题
["1", "2", "3"].map(parseInt)
知识点:
首先, map接受两个参数, 一个回调函数 callback, 一个回调函数的this值
其中回调函数接受三个参数 currentValue, index, arrary;
而题目中, map只传入了回调函数--parseInt.
其次, parseInt 只接受两个两个参数 string, radix(基数).
可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间。
如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果它以 “0x” 或 “0X” 开头,将以 16 为基数。
如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN。
所以本题即问
parseInt('1', 0);
parseInt('2', 1);
parseInt('3', 2);
首先后两者参数不合法.
所以答案是 [1, NaN, NaN]
第2题
[typeof null, null instanceof Object]
两个知识点:
typeof 返回一个表示类型的字符串.
instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上.
这个题可以直接看链接... 因为 typeof null === 'object' 自语言之初就是这样....
typeof 的结果请看下表:
type result
Undefined "undefined"
Null "object"
Boolean "boolean"
Number "number"
String "string"
Symbol "symbol"
Host object Implementation-dependent
Function "function"
Object "object"
所以答案 [object, false]
第3题
[ [3,2,1].reduce(Math.pow), [].reduce(Math.pow) ]
知识点:
arr.reduce(callback[, initialValue])
reduce接受两个参数, 一个回调, 一个初始值.
回调函数接受四个参数 previousValue, currentValue, currentIndex, array
需要注意的是 If the array is empty and no initialValue was provided, TypeError would be thrown.
所以第二个表达式会报异常. 第一个表达式等价于 Math.pow(3, 2) => 9; Math.pow(9, 1) =>9
答案 an error
第4题
var val = 'smtg';
console.log('Value is ' + (val === 'smtg') ? 'Something' : 'Nothing');
两个知识点:
Operators/Conditional_Operator
简而言之 + 的优先级 大于 ?
所以原题等价于 'Value is true' ? 'Somthing' : 'Nonthing' 而不是 'Value is' + (true ? 'Something' : 'Nonthing')
答案 'Something'
第5题
var name = 'World!';
(function () {
if (typeof name === 'undefined') {
var name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
})();
这个相对简单, 一个知识点:
在 JavaScript中, functions 和 variables 会被提升。变量提升是JavaScript将声明移至作用域 scope (全局域或者当前函数作用域) 顶部的行为。
这个题目相当于
var name = 'World!';
(function () {
var name;
if (typeof name === 'undefined') {
name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
})();
所以答案是 'Goodbye Jack'
第6题
var END = Math.pow(2, 53);
var START = END - 100;
var count = 0;
for (var i = START; i <= END; i++) {
count++;
}
console.log(count);
一个知识点:
在 JS 里, Math.pow(2, 53) == 9007199254740992 是可以表示的最大值. 最大值加一还是最大值. 所以循环不会停.
第7题
var ary = [0,1,2];
ary[10] = 10;
ary.filter(function(x) { return x === undefined;});
答案是 []
看一篇文章理解稀疏数组
我们来看一下 Array.prototype.filter 的 polyfill:
if (!Array.prototype.filter) {
Array.prototype.filter = function(fun/*, thisArg*/) {
'use strict';
if (this === void 0 || this === null) {
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun !== 'function') {
throw new TypeError();
}
var res = [];
var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
for (var i = 0; i < len; i++) {
if (i in t) { // 注意这里!!!
var val = t[i];
if (fun.call(thisArg, val, i, t)) {
res.push(val);
}
}
}
return res;
};
}
我们看到在迭代这个数组的时候, 首先检查了这个索引值是不是数组的一个属性, 那么我们测试一下.
0 in ary; => true
3 in ary; => false
10 in ary; => true
也就是说 从 3 - 9 都是没有初始化的'坑'!, 这些索引并不存在与数组中. 在 array 的函数调用的时候是会跳过这些'坑'的.
第8题
var two = 0.2
var one = 0.1
var eight = 0.8
var six = 0.6
[two - one == one, eight - six == two]
JavaScript的设计缺陷?浮点运算:0.1 + 0.2 != 0.3
IEEE 754标准中的浮点数并不能精确地表达小数
那什么时候精准, 什么时候不经准呢? 笔者也不知道...
答案 [true, false]
第9题
function showCase(value) {
switch(value) {
case 'A':
console.log('Case A');
break;
case 'B':
console.log('Case B');
break;
case undefined:
console.log('undefined');
break;
default:
console.log('Do not know!');
}
}
showCase(new String('A'));
两个知识点:
switch 是严格比较, String 实例和 字符串不一样.
var s_prim = 'foo';
var s_obj = new String(s_prim);
console.log(typeof s_prim); // "string"
console.log(typeof s_obj); // "object"
console.log(s_prim === s_obj); // false
答案是 'Do not know!'
第10题
function showCase2(value) {
switch(value) {
case 'A':
console.log('Case A');
break;
case 'B':
console.log('Case B');
break;
case undefined:
console.log('undefined');
break;
default:
console.log('Do not know!');
}
}
showCase2(String('A'));
解释:
String(x) does not create an object but does return a string, i.e. typeof String(1) === "string"
还是刚才的知识点, 只不过 String 不仅是个构造函数 直接调用返回一个字符串哦.
答案 'Case A'
第11题
function isOdd(num) {
return num % 2 == 1;
}
function isEven(num) {
return num % 2 == 0;
}
function isSane(num) {
return isEven(num) || isOdd(num);
}
var values = [7, 4, '13', -9, Infinity];
values.map(isSane);
一个知识点
Arithmetic_Operators#Remainder
此题等价于
7 % 2 => 1
4 % 2 => 0
'13' % 2 => 1
-9 % % 2 => -1
Infinity % 2 => NaN
需要注意的是 余数的正负号随第一个操作数.
答案 [true, true, true, false, false]
第12题
parseInt(3, 8)
parseInt(3, 2)
parseInt(3, 0)
第一个题讲过了, 答案 3, NaN, 3
第13题
Array.isArray( Array.prototype )
一个知识点:
一个鲜为人知的实事: Array.prototype => [];
答案: true
第14题
var a = [0];
if ([0]) {
console.log(a == true);
} else {
console.log("wut");
}
答案: false
第15题
[]==[]
== 是万恶之源, 看上图
答案是 false
第16题
'5' + 3
'5' - 3
两个知识点:
Arithmetic_Operators#Subtraction
+ 用来表示两个数的和或者字符串拼接, -表示两数之差.
请看例子, 体会区别:
> '5' + 3
'53'
> 5 + '3'
'53'
> 5 - '3'
2
> '5' - 3
2
> '5' - '3'
2
也就是说 - 会尽可能的将两个操作数变成数字, 而 + 如果两边不都是数字, 那么就是字符串拼接.
答案是 '53', 2
第17题
1 + - + + + - + 1
这里应该是(倒着看)
1 + (a) => 2
a = - (b) => 1
b = + (c) => -1
c = + (d) => -1
d = + (e) => -1
e = + (f) => -1
f = - (g) => -1
g = + 1 => 1
所以答案 2
第18题
var ary = Array(3);
ary[0]=2
ary.map(function(elem) { return '1'; });
稀疏数组. 同第7题.
题目中的数组其实是一个长度为3, 但是没有内容的数组, array 上的操作会跳过这些未初始化的'坑'.
所以答案是 ["1", undefined × 2]
这里贴上 Array.prototype.map 的 polyfill.
Array.prototype.map = function(callback, thisArg) {
var T, A, k;
if (this == null) {
throw new TypeError(' this is null or not defined');
}
var O = Object(this);
var len = O.length >>> 0;
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
if (arguments.length > 1) {
T = thisArg;
}
A = new Array(len);
k = 0;
while (k < len) {
var kValue, mappedValue;
if (k in O) {
kValue = O[k];
mappedValue = callback.call(T, kValue, k, O);
A[k] = mappedValue;
}
k++;
}
return A;
};
第19题
function sidEffecting(ary) {
ary[0] = ary[2];
}
function bar(a,b,c) {
c = 10
sidEffecting(arguments);
return a + b + c;
}
bar(1,1,1)
这是一个大坑, 尤其是涉及到 ES6语法的时候
知识点:
首先 The arguments object is an Array-like object corresponding to the arguments passed to a function.
也就是说 arguments 是一个 object, c 就是 arguments[2], 所以对于 c 的修改就是对 arguments[2] 的修改.
所以答案是 21.
然而!!!!!!
当函数参数涉及到 any rest parameters, any default parameters or any destructured parameters 的时候, 这个 arguments 就不在是一个 mapped arguments object 了.....
请看:
function sidEffecting(ary) {
ary[0] = ary[2];
}
function bar(a,b,c=3) {
c = 10
sidEffecting(arguments);
return a + b + c;
}
bar(1,1,1)
答案是 12 !!!!
请读者细细体会!!
第20题
var a = 111111111111111110000,
b = 1111;
a + b;
答案还是 111111111111111110000. 解释是 Lack of precision for numbers in JavaScript affects both small and big numbers. 但是笔者不是很明白................ 请读者赐教!
第21题
var x = [].reverse;
x();
这个题有意思!
知识点:
The reverse method transposes the elements of the calling array object in place, mutating the array, and returning a reference to the array.
也就是说 最后会返回这个调用者(this), 可是 x 执行的时候是上下文是全局. 那么最后返回的是 window.
答案是 window
第22题
Number.MIN_VALUE > 0
true
第23题
[1 < 2 < 3, 3 < 2 < 1]
这个题也还可以.
这个题会让人误以为是 2 > 1 && 2 < 3 其实不是的.
这个题等价于
1 < 2 => true;
true < 3 => 1 < 3 => true;
3 < 2 => false;
false < 1 => 0 < 1 => true;
答案是 [true, true]
第24题
// the most classic wtf
2 == [[[2]]]
这个题我是猜的. 我猜的 true, 至于为什么.....
both objects get converted to strings and in both cases the resulting string is "2" 我不能信服...
第25题
3.toString()
3..toString()
3...toString()
这个题也挺逗, 我做对了 :) 答案是 error, '3', error
你如果换一个写法就更费解了
var a = 3;
a.toString()
这个答案就是 '3';
为啥呢?
因为在 js 中 1.1, 1., .1 都是合法的数字. 那么在解析 3.toString 的时候这个 . 到底是属于这个数字还是函数调用呢? 只能是数字, 因为3.合法啊!
第26题
(function(){
var x = y = 1;
})();
console.log(y);
console.log(x);
答案是 1, error
y 被赋值到全局. x 是局部变量. 所以打印 x 的时候会报 ReferenceError
第27题
var a = /123/,
b = /123/;
a == b
a === b
即使正则的字面量一致, 他们也不相等.
答案 false, false
第28题
var a = [1, 2, 3],
b = [1, 2, 3],
c = [1, 2, 4]
a == b
a === b
a > c
a < c
字面量相等的数组也不相等.
数组在比较大小的时候按照字典序比较
答案 false, false, false, true
第29题
var a = {}, b = Object.prototype;
[a.prototype === b, Object.getPrototypeOf(a) === b]
知识点:
只有 Function 拥有一个 prototype 的属性. 所以 a.prototype 为 undefined.
而 Object.getPrototypeOf(obj) 返回一个具体对象的原型(该对象的内部[[prototype]]值)
答案 false, true
第30题
function f() {}
var a = f.prototype, b = Object.getPrototypeOf(f);
a === b
f.prototype is the object that will become the parent of any objects created with new f while Object.getPrototypeOf returns the parent in the inheritance hierarchy.
f.prototype 是使用使用 new 创建的 f 实例的原型. 而 Object.getPrototypeOf 是 f 函数的原型.
请看:
a === Object.getPrototypeOf(new f()) // true
b === Function.prototype // true
答案 false
31
function foo() { }
var oldName = foo.name;
foo.name = "bar";
[oldName, foo.name]
答案 ['foo', 'foo']
知识点:
因为函数的名字不可变.
第32题
"1 2 3".replace(/\d/g, parseInt)
知识点:
str.replace(regexp|substr, newSubStr|function)
如果replace函数传入的第二个参数是函数, 那么这个函数将接受如下参数
- match 首先是匹配的字符串
- p1, p2 .... 然后是正则的分组
- offset match 匹配的index
- string 整个字符串
由于题目中的正则没有分组, 所以等价于问
parseInt('1', 0)
parseInt('2', 2)
parseInt('3', 4)
答案: 1, NaN, 3
第33题
function f() {}
var parent = Object.getPrototypeOf(f);
f.name // ?
parent.name // ?
typeof eval(f.name) // ?
typeof eval(parent.name) // ?
先说以下答案 'f', 'Empty', 'function', error 这个答案并不重要.....
这里第一小问和第三小问很简单不解释了.
第二小问笔者在自己的浏览器测试的时候是 '', 第四问是 'undefined'
所以应该是平台相关的. 这里明白 parent === Function.prototype 就好了.
第34题
var lowerCaseOnly = /^[a-z]+$/;
[lowerCaseOnly.test(null), lowerCaseOnly.test()]
知识点:
这里 test 函数会将参数转为字符串. 'nul', 'undefined' 自然都是全小写了
答案: true, true
第35题
[,,,].join(", ")
[,,,] => [undefined × 3]
因为javascript 在定义数组的时候允许最后一个元素后跟一个,, 所以这是个长度为三的稀疏数组(这是长度为三, 并没有 0, 1, 2三个属性哦)
答案: ", , "
第36题
var a = {class: "Animal", name: 'Fido'};
a.class
这个题比较流氓.. 因为是浏览器相关, class是个保留字(现在是个关键字了)
所以答案不重要, 重要的是自己在取属性名称的时候尽量避免保留字. 如果使用的话请加引号 a['class']
第37题
var a = new Date("epoch")
知识点:
简单来说, 如果调用 Date 的构造函数传入一个字符串的话需要符合规范, 即满足 Date.parse 的条件.
另外需要注意的是 如果格式错误 构造函数返回的仍是一个Date 的实例 Invalid Date.
答案 Invalid Date
第38题
var a = Function.length,
b = new Function().length
a === b
我们知道一个function(Function 的实例)的 length 属性就是函数签名的参数个数, 所以 b.length == 0.
另外 Function.length 定义为1......
所以不相等.......答案 false
第39题
var a = Date(0);
var b = new Date(0);
var c = new Date();
[a === b, b === c, a === c]
还是关于Date 的题, 需要注意的是
- 如果不传参数等价于当前时间.
- 如果是函数调用 返回一个字符串.
答案 false, false, false
第40题
var min = Math.min(), max = Math.max()
min < max
知识点:
有趣的是, Math.min 不传参数返回 Infinity, Math.max 不传参数返回 -Infinity
-
for(var i=0;i<10;i+=2){
-
if(i<=5){
-
i++;
-
continue;
-
}else{
-
i--;
-
break;
-
}
-
console.log(i);}
-
console.log(i); //=>5