题库-js 高级

1、JQuery一个对象可以同时绑定多个事件,实现原理

jQuery可以给一个对象同时绑定多个事件,低层实现方式是使用 addEventListner 或 attachEvent 兼容不同的浏览器实现事件的绑定,这样可以给同一个对象注册

2、webkit、用浏览器的各种工具来调试和debug代码

Webkit是浏览器引擎,包括 html 渲染和 js 解析功能,手机浏览器的主流内核,与之相对应的引擎有 Gecko(Mozilla Firefox 等使用)和 Trident(也称MSHTML,IE 使用)。
对于浏览器的调试工具要熟练使用,主要是页面结构分析,后台请求信息查看,js 调试工具使用,熟练使用这些工具可以快速提高解决问题的效率

3、如何测试前端代码? 知道 BDD, TDD, Unit Test 么?

怎么测试你的前端工程 (mocha, sinon, jasmin, qUnit..)

了解BDD行为驱动开发与 TDD 测试驱动开发已经单元测试相关概念

TDD:测试驱动开发(Test-Driven Development)

测试驱动开发是敏捷开发中的一项核心实践和技术,也是一种设计方法论。TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。TDD的基本思路就是通过测试来推动整个开发的进行,但测试驱动开发并不只是单纯的测试工作,而是把需求分析,设计,质量控制量化的过程。TDD首先考虑使用需求(对象、功能、过程、接口等),主要是编写测试用例框架对功能的过程和接口进行设计,而测试框架可以持续进行验证。

BDD:行为驱动开发(Behavior Driven Development)

行为驱动开发是一种敏捷软件开发的技术,它鼓励软件项目中的开发者、QA和非技术人员或商业参与者之间的协作。主要是从用户的需求出发,强调系统行为。BDD最初是由Dan North在2003年命名,它包括验收测试和客户测试驱动等的极限编程的实践,作为对测试驱动开发的回应。

ATDD:验收测试驱动开发(Acceptance Test Driven Development)

TDD 只是开发人员的职责,通过单元测试用例来驱动功能代码的实现。在准备实施一个功能或特性之前,首先团队需要定义出期望的质量标准和验收细则,以明确而且达成共识的验收测试计划(包含一系列测试场景)来驱动开发人员的TDD实践和测试人员的测试脚本开发。面向开发人员,强调如何实现系统以及如何检验。

4、前端 templating(Mustache, underscore, handlebars) 是干嘛的, 怎么用?

Web 模板引擎是为了使用户界面与业务数据(内容)分离而产生的,
Mustache 是一个 logic-less (轻逻辑)模板解析引擎,它的优势在于可以应用在 Javascript、PHP、Python、Perl 等多种编程语言中。
Underscore封装了常用的JavaScript对象操作方法,用于提高开发效率。
Handlebars 是 JavaScript 一个语义模板库,通过对view和data的分离来快速构建Web模板。

5、Handlebars 的基本用法

没有用过的话说出它是干什么的即可

6、Handlerbars 的对模板的基本处理流程, 如何编译的?如何缓存的?

学习技术不仅要会用,还有熟悉它的实现机制,这样在开发中遇到问题时才能更好的解决

7、用js实现千位分隔符

原生js的熟练度,实践经验,实现思路

8、检测浏览器版本版本有哪些方式?

IE与标准浏览器判断,IE不同版本的判断,userAgent var ie = /*@cc_on !@*/false;

9、实现一个函数 clone

要求:对JavaScript中的5种主要的数据类型(包括Number、String、Object、Array、Boolean)进行值复制

考察点1:对于基本数据类型和引用数据类型在内存中存放的是值还是指针这一区别是否清楚
考察点2:是否知道如何判断一个变量是什么类型的
考察点3:递归算法的设计

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
32
33
// 方法一:
Object.prototype.clone = function(){
var o = this.constructor === Array ? [] : {};
for(var e in this){
o[e] = typeof this[e] === "object" ? this[e].clone() : this[e];
}
return o;
}
//方法二:
/**
* 克隆一个对象
* @param Obj
* @returns
*/
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;
}
}

10、小贤是一条可爱的小狗(Dog),它的叫声很好听(wow),每次看到主人的时候就会乖乖叫一声(yelp)。从这段描述可以得到以下对象:

1
2
3
4
5
6
7
8
function Dog() {
this.wow = function() {
alert('Wow');
}
this.yelp = function() {
this.wow();
}
}

11、小芒和小贤一样,原来也是一条可爱的小狗,可是突然有一天疯了(MadDog),一看到人就会每隔半秒叫一声(wow)地不停叫唤(yelp)。请根据描述,按示例的形式用代码来实。(继承,原型,setInterval)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function MadDog() {
this.yelp = function() {
var self = this;
setInterval(function() {
self.wow();
}, 500);
}
}
MadDog.prototype = new Dog();
//for test
var dog = new Dog();
dog.yelp();
var madDog = new MadDog();
madDog.yelp();

12、下面这个ul,如何点击每一列的时候alert其index?(闭包)

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
<ul id=”test”>
<li>这是第一条</li>
<li>这是第二条</li>
<li>这是第三条</li>
</ul>
<script>
// 方法一:
var lis=document.getElementById('2223').getElementsByTagName('li');
for(var i=0;i<3;i++)
{
lis[i].index=i;
lis[i].onclick=function(){
alert(this.index);
};
}
//方法二:
var lis=document.getElementById('2223').getElementsByTagName('li');
for(var i=0;i<3;i++){
lis[i].index=i;
lis[i].onclick=(function(a){
return function() {
alert(a);
}
})(i);
}
</script>

13、编写一个JavaScript函数,输入指定类型的选择器

仅需支持id,class,tagName三种简单CSS选择器,无需兼容组合选择器)可以返回匹配的DOM节点,需考虑浏览器兼容性和性能。

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/**
* @param selector {String} 传入的CSS选择器。
* @return {Array}
* @param {[type]} selector [description]
* @return {[type]} [description]
*/
var query = function(selector) {
var reg = /^(#)?(\.)?(\w+)$/img;
var regResult = reg.exec(selector);
var result = [];
//如果是id选择器
if (regResult[1]) {
if (regResult[3]) {
if (typeof document.querySelector === "function") {
result.push(document.querySelector(regResult[3]));
} else {
result.push(document.getElementById(regResult[3]));
}
}
} else if (regResult[2]) {//如果是class选择器
if (regResult[3]) {
if (typeof document.getElementsByClassName === 'function') {
var doms = document.getElementsByClassName(regResult[3]);
if(doms) {
result = converToArray(doms);
}
} else { //如果不支持getElementsByClassName函数
var allDoms = document.getElementsByTagName("*") ;
for (var i = 0, len = allDoms.length; i < len; i++) {
if(allDoms[i].className.search(new RegExp(regResult[2])) > -1) {
result.push(allDoms[i]);
}
}
}
}
} else if (regResult[3]) { //如果是标签选择器
var doms = document.getElementsByTagName(regResult[3].toLowerCase());
if(doms) {
result = converToArray(doms);
}
}
return result;
}
function converToArray(nodes){
var array = null;
try{
array = Array.prototype.slice.call(nodes,0);//针对非IE浏览器
} catch(ex) {
array = new Array();
for( var i = 0 ,len = nodes.length; i < len ; i++ ) {
array.push(nodes[i])
}
}
return array;
}

14、请评价以下代码并给出改进意见

1
2
3
4
5
6
7
8
9
10
11
12
if(window.addEventListener){
var addListener = function (el, type, listener, useCapture) {
el.addEventListener(type, listener, useCapture);
};
}
else if(document.all){
addListener = function(el, type, listener) {
el.attachEvent("on" + type, function() {
listener.apply(el);
});
}
}

不应该在 if 和 else 语句中声明 addListener 函数,应该先声明;
不需要使用 window.addEventListener 或 document.all 来进行检测浏览器,应该使用能力检测;
由于 attachEvent 在 IE 中有 this 指向问题,所以调用它时需要处理一下

改进如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
function addEvent (elem, type, handler) {
if(elem.addEventListener) {
elem.addEventListener(type, handler, false);
} else if (elem.attachEvent) {
elem['temp' + type + handler] = handler;
elem[type + handler] = function() {
elem['temp' + type + handler].apply(elem);
};
elem.attachEvent('on' + type, elem[type + handler]); 
} else {
elem['on' + type] = handler;
}
}

15、定义一个log方法,让它可以代理 console.log 的方法。

1
2
3
4
5
6
7
8
9
// 可行的方法一:
function log(msg) {
console.log(msg);
}
log("hello world!") // hello world!
// 如果要传入多个参数呢?显然上面的方法不能满足要求,所以更好的方法是:
function log(){
console.log.apply(console, arguments);
};

apply和call方法的异同。

对于apply和call两者在作用上是相同

即是调用一个对象的一个方法,以另一个对象替换当前对象。
将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。

但两者在参数上有区别

对于第一个参数意义都一样,但对第二个参数: apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,
而call则作为call的参数传入(从第二个参数开始)。
如 func.call(func1,var1,var2,var3)对应的apply写法为:func.apply(func1,[var1,var2,var3]) 。

16、对作用域上下文和this的理解,看下列代码:

1
2
3
4
5
6
7
8
9
var User = {
count: 1,
getCount: function() {
return this.count;
}
};
console.log(User.getCount()); // what?
var func = User.getCount;
console.log(func()); // what?

问两处console输出什么?为什么?

答案是 1 和 undefined。

func是在winodw的上下文中被执行的,所以会访问不到count属性。

那么如何确保Uesr总是能访问到func的上下文,即正确返回1。
正确的方法是使用Function.prototype.bind。兼容各个浏览器完整代码如下:

1
2
3
4
5
6
7
8
Function.prototype.bind = Function.prototype.bind || function(context){
var self = this;
return function(){
return self.apply(context, arguments);
};
}
var func = User.getCount.bind(User);
console.log(func());

17、原生JS的window.onload与Jquery的$(document).ready(function(){})有什么不同?

如何用原生JS实现Jq的ready方法?

window.onload()方法是必须等到页面内包括图片的所有元素加载完毕后才能执行。
$(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕。

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/*
* 传递函数给whenReady()
* 当文档解析完毕且为操作准备就绪时,函数作为document的方法调用
*/
var whenReady = (function() { //这个函数返回whenReady()函数
var funcs = []; //当获得事件时,要运行的函数
var ready = false; //当触发事件处理程序时,切换为true
//当文档就绪时,调用事件处理程序
function handler(e) {
if (ready) return; //确保事件处理程序只完整运行一次
//如果发生onreadystatechange事件,但其状态不是complete的话,那么文档尚未准备好
if (e.type === 'onreadystatechange' && document.readyState !== 'complete') {
return;
}
//运行所有注册函数
//注意每次都要计算funcs.length
//以防这些函数的调用可能会导致注册更多的函数
for(var i = 0; i < funcs.length; i++) {
funcs[i].call(document);
}
//事件处理函数完整执行,切换ready状态, 并移除所有函数
ready = true;
funcs = null;
}
//为接收到的任何事件注册处理程序
if(document.addEventListener) {
document.addEventListener('DOMContentLoaded', handler, false);
document.addEventListener('readystatechange', handler, false); //IE9+
window.addEventListener('load', handler, false);
}else if(document.attachEvent) {
document.attachEvent('onreadystatechange', handler);
window.attachEvent('onload', handler);
}
//返回whenReady()函数
return function whenReady(fn) {
if(ready) { fn.call(document); }
else { funcs.push(fn); }
}
})();
// 如果上述代码十分难懂,下面这个简化版:
function ready(fn){
if(document.addEventListener) {//标准浏览器
document.addEventListener('DOMContentLoaded', function() {
//注销事件, 避免反复触发
document.removeEventListener('DOMContentLoaded',arguments.callee, false);
fn();//执行函数
}, false);
} else if (document.attachEvent) {//IE
document.attachEvent('onreadystatechange', function() {
if(document.readyState == 'complete') {
document.detachEvent('onreadystatechange', arguments.callee);
fn();//函数执行
}
});
}
};

18、(设计题)想实现一个对页面某个节点的拖曳?如何做?(使用原生JS)

给需要拖拽的节点绑定mousedown, mousemove, mouseup事件
mousedown事件触发后,开始拖拽
mousemove时,需要通过event.clientX和clientY获取拖拽位置,并实时更新位置
mouseup时,拖拽结束
需要注意浏览器边界的情况

19、请实现如下功能

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
function setcookie(name,value,days){ //给cookie增加一个时间变量
var exp = new Date();
exp.setTime(exp.getTime() + days*24*60*60*1000); //设置过期时间为days天
document.cookie = name + " = "+ escape (value) + "; expires = " + exp.toGMTString();
}
function getCookie(name){
var result = "";
var myCookie = "" + document.cookie + ";";
var searchName = "+ name + "= "";
var startOfCookie = myCookie.indexOf(searchName);
var endOfCookie;
if(satrtOfCookie != -1){
startOfcookie += searchName.length;
endOfCookie = myCookie.indexOf(";",startOfCookie);
result = (myCookie.substring(startOfCookie,endOfCookie));
}
return result;
}
(function(){
var oTips = document.getElementById('tips');//假设tips的id为tips
var page = {
check: function() {//检查tips的cookie是否存在并且允许显示
var tips = getCookie('tips');
if(!tips || tips == 'show') return true;//tips的cookie不存在
if(tips == "never_show_again") return false;
},
hideTip: function(bNever) {
if(bNever) setcookie('tips', 'never_show_again', 365);
oTips.style.display = "none";//隐藏
  },
showTip: function() {
oTips.style.display = "inline";//显示,假设tips为行级元素
},
init: function() {
var _this = this;
if(this.check()) {
_this.showTip();
setcookie('tips', 'show', 1);
}
oTips.onclick = function() {
_this.hideTip(true);
};
}
};
page.init();
})();

20、说出以下函数的作用是?空白区域应该填写什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//define
(function(window){
function fn(str){
this.str=str;
}
fn.prototype.format = function(){
var arg = ______;
return this.str.replace(_____,function(a,b){
return arg[b]||"";
});
}
window.fn = fn;
})(window);
//use
(function(){
var t = new fn('<p><a href="{0}">{1}</a><span>{2}</span></p>');
console.log(t.format('http://www.alibaba.com','Alibaba','Welcome'));
})();

访函数的作用是使用format函数将函数的参数替换掉{0}这样的内容,返回一个格式化后的结果:

第一个空是:arguments
第二个空是:/\{(\d+)\}/ig

21、Javascript作用链域

理解变量和函数的访问范围和生命周期,全局作用域与局部作用域的区别,JavaScript中没有块作用域,函数的嵌套形成不同层次的作用域,嵌套的层次形成链式形式,通过作用域链查找属性的规则需要深入理解。

22、This对象

理解不同形式的函数调用方式下的this指向,理解事件函数、定时函数中的this指向,函数的调用形式决定了this的指向。

在JavaScript中,this通常指向的是我们正在执行的函数本身,或者是,指向该函数所属的对象。
全局的this → 指向的是Window
函数中的this → 指向的是函数所在的对象
对象中的this → 指向其本身

23、 eval

它的功能是把对应的字符串解析成JS代码并运行;应该避免使用eval,不安全,非常耗性能

2个步骤:

一次解析成js语句
一次执行

24、关于事件,IE与火狐的事件机制有什么区别? 如何阻止冒泡?

[1].在IE中,事件对象是作为一个全局变量来保存和维护的.所有的浏览器事件,不管是用户触发的,还是其他事件,都会更新window.event对象.所以在代码中,只要调用window.event就可以获取事件对象, 再event.srcElement就可以取得触发事件的元素进行进一步处理.
[2].在FireFox中,事件对象却不是全局对象,一般情况下,是现场发生,现场使用,FireFox把事件对象自动传给事件处理程序.

25、什么是闭包(closure),为什么要用它?

简单的理解是函数的嵌套形成闭包,闭包包括函数本身已经它的外部作用域
使用闭包可以形成独立的空间,延长变量的生命周期,报存中间状态值

执行say667()后,say667()闭包内部变量会存在, 而闭包内部函数的内部变量不会存在.使得Javascript的垃圾回收机制GC不会收回say667()所占用的资源,因为say667()的内部函数的执行需要依赖say667()中的变量。这是对闭包作用的非常直白的描述.

1
2
3
4
5
6
7
8
9
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

26、javascript 代码中的”use strict”; 是什么意思 ? 使用它区别是什么?

意思是使用严格模式,使用严格模式,一些不规范的语法将不再支持

27、如何判断一个对象是否属于某个类?

Instanceof constructor

28、new操作符具体干了什么呢?

创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。
属性和方法被加入到 this 引用的对象中。
新创建的对象由 this 所引用,并且最后隐式的返回 this 。

1
2
3
var obj = {};
obj.__proto__ = Base.prototype;
Base.call(obj);

29、Javascript中,有一个函数,执行时对象查找时,永远不会去查找原型,这个函数是?

HasOwnProperty

30、对JSON的了解

轻量级数据交互格式,可以形成复杂的嵌套格式,解析非常方便

31、js延迟加载的方式有哪些

方案一:<script>标签的async="async"属性
方案二:<script>标签的defer="defer"属性
方案三:动态创建<script>标签
方案四:AJAX eval(使用AJAX得到脚本内容,然后通过eval_r(xmlhttp.responseText)来运行脚本)
方案五:iframe方式

32、模块化开发怎么做?

浏览器端 requirejs,seajs;
服务器端 nodejs;ES6模块化;
fis、webpack 等前端整体模块化解决方案;
grunt、gulp等前端工作流的使用

33、AMD(Modules/Asynchronous-Definition)、CMD(Common Module Definition)规范区别

理解这两种规范的差异,主要通过requirejs与seajs的对比,
理解模块的定义与引用方式的差异以及这两种规范的设计原则

34、requireJS的核心原理是什么?(如何动态加载的?如何避免多次加载的?如何缓存的?)

核心是js的加载模块,通过正则匹配模块以及模块的依赖关系,保证文件加载的先后顺序
根据文件的路径对加载过的文件做了缓存

35、自己设计实现一个 requireJS,你会怎么做?

核心是实现js的加载模块,维护js的依赖关系,控制好文件加载的先后顺序

36、对ECMAScript6的了解

ES6新的语法糖,类,模块化等新特性

37、ECMAScript6 怎么写class么,为什么会出现class这种东西?

1
2
3
4
5
6
7
8
9
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '('+this.x+', '+this.y+')';
}
}

39、数组和对象有哪些原生方法

Array.concat( ) 连接数组
Array.join( ) 将数组元素连接起来以构建一个字符串
Array.length 数组的大小
Array.pop( ) 删除并返回数组的最后一个元素
Array.push( ) 给数组添加元素
Array.reverse( ) 颠倒数组中元素的顺序
Array.shift( ) 将元素移出数组
Array.slice( ) 返回数组的一部分
Array.sort( ) 对数组元素进行排序
Array.splice( ) 插入、删除或替换数组的元素
Array.toLocaleString( ) 把数组转换成局部字符串
Array.toString( ) 将数组转换成一个字符串
Array.unshift( ) 在数组头部插入一个元素
Object.hasOwnProperty( ) 检查属性是否被继承
Object.isPrototypeOf( ) 一个对象是否是另一个对象的原型
Object.propertyIsEnumerable( ) 是否可以通过for/in循环看到属性
Object.toLocaleString( ) 返回对象的本地字符串表示
Object.toString( ) 定义一个对象的字符串表示
Object.valueOf( ) 指定对象的原始值

40、JS 怎么实现一个类。怎么实例化这个类

严格来讲js中并没有类的概念
不过js中的函数可以作为构造函数来使用
通过new来实例化,其实函数本身也是一个对象。

41、JavaScript中的作用域与变量声明提升?

理解JavaScript的预解析机制
js的运行主要分两个阶段
js的预解析和运行
预解析阶段所有的变量声明和函数定义都会提前,但是变量的赋值不会提前

42、如何编写高性能的Javascript

使用 DocumentFragment 优化多次 append
通过模板元素 clone ,替代 createElement
使用一次 innerHTML 赋值代替构建 dom 元素
使用 firstChild 和 nextSibling 代替 childNodes 遍历 dom 元素
使用 Array 做为 StringBuffer ,代替字符串拼接的操作
将循环控制量保存到局部变量
顺序无关的遍历时,用 while 替代 for
将条件分支,按可能性顺序从高到低排列
在同一条件子的多( >2 )条件分支时,使用 switch 优于 if
使用三目运算符替代条件分支
需要不断执行的时候,优先考虑使用 setInterval

43、那些操作会造成内存泄漏

闭包,循环

44、javascript对象的几种创建方式

工厂模式
构造函数模式
原型模式
混合构造函数和原型模式
动态原型模式
寄生构造函数模式
稳妥构造函数模式

45、javascript 继承的 6 种方法?

原型链继承
借用构造函数继承
组合继承(原型+借用构造)
原型式继承
寄生式继承
寄生组合式继承

46、eval

它的功能是把对应的字符串解析成JS代码并运行
应该避免使用eval,不安全,非常耗性能(2次,一次解析成js语句,一次执行)

47、JavaScript 原型,原型链 ? 有什么特点?

原型对象也是普通的对象,是对象一个自带隐式的 __proto__ 属性,原型也有可能有自己的原型,如果一个原型对象的原型不为 null 的话,我们就称之为原型链
原型链是由一些用来继承和共享属性的对象组成的(有限的)对象链

JavaScript的数据对象有那些属性值

writable:这个属性的值是否可以改。
configurable:这个属性的配置是否可以删除,修改。
enumerable:这个属性是否能在for…in循环中遍历出来或在Object.keys中列举出来。
value:属性值。

当我们需要一个属性的时,Javascript引擎会先看当前对象中是否有这个属性, 如果没有的话,就会查找他的Prototype对象是否有这个属性。

1
2
3
4
5
6
7
8
9
10
11
12
function clone(proto) {
function Dummy() { }
Dummy.prototype = proto;
Dummy.prototype.constructor = Dummy;
return new Dummy(); //等价于Object.create(Person);
}
function object(old) {
function F() {};
F.prototype = old;
return new F();
}
var newObj = object(oldObject);

48、事件、IE与火狐的事件机制有什么区别? 如何阻止冒泡?

我们在网页中的某个操作(有的操作对应多个事件)。
例如:当我们点击一个按钮就会产生一个事件。是可以被 JavaScript 侦测到的行为
事件处理机制:IE是事件冒泡、firefox同时支持两种事件模型,也就是:捕获型事件和冒泡型事件
ev.stopPropagation(); 注意旧ie的方法:ev.cancelBubble = true;

49、简述一下Sass、Less,且说明区别

他们是动态的样式语言,是 CSS 预处理器, CSS 上的一种抽象层。他们是一种特殊的语法/语言而编译成CSS。

变量符不一样,less 是 @,而 Sass 是 $;

Sass支持条件语句,可以使用 if{}else{}, for{} 循环等等。而 Less 不支持;
Sass是基于 Ruby 的,是在服务端处理的,而 Less 是需要引入 less.js 来处理 Less 代码输出 Css 到浏览器

50、关于javascript中apply()和call()方法的区别?

相同点:两个方法产生的作用是完全一样的
不同点:方法传递的参数不同
Object.call(this,obj1,obj2,obj3)
Object.apply(this,arguments)
apply()接收两个参数,一个是函数运行的作用域(this),另一个是参数数组。
call()方法第一个参数与apply()方法相同,但传递给函数的参数必须列举出来。

1
2
3
4
5
6
7
function add(a,b){
alert(a+b);
}
function sub(a,b){
alert(a-b);
}
add.call(sub,3,1);

例子中用 add 来替换 sub,add.call(sub,3,1) == add(3,1) ,所以运行结果为:alert(4);

注意:js 中的函数其实是对象,函数名是对 Function 对象的引用。

51、分别阐述split(),slice(),splice(),join()

join()用于把数组中的所有元素拼接起来放入一个字符串。所带的参数为分割字符串的分隔符,默认是以逗号分开。归属于Array
split()即把字符串分离开,以数组方式存储。归属于Stringstring
slice() 方法可从已有的数组中返回选定的元素。该方法并不会修改数组,而是返回一个子数组。如果想删除数组中的一段元素,应该使用方法 Array.splice()
splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目。返回的是含有被删除的元素的数组。

52、事件委托

让利用事件冒泡的原理,让自己的所触发的事件,让他的父元素代替执行!

53、如何阻止事件冒泡和默认事件

阻止浏览器的默认行为

window.event?window.event.returnValue = false: e.preventDefault();

停止事件冒泡

window.event?window.event.cancelBubble = true:e.stopPropagation();

原生的和 jQuery 的

原生JavaScript中,return false;只阻止默认行为,不阻止冒泡,
jQuery中的return false;既阻止默认行为,又阻止冒泡

54、require.js 有什么特性

实现js文件的异步加载,避免网页失去响应;
管理模块之间的依赖性,便于代码的编写和维护。

55、谈一下JS中的递归函数,并且用递归简单实现阶乘?

递归即是程序在执行过程中不断调用自身的编程技巧,当然也必须要有一个明确的结束条件,不然就会陷入死循环。

56、请用正则表达式写一个简单的邮箱验证

/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;

57、简述一下你对web性能优化的方案

尽量减少 HTTP 请求
使用浏览器缓存
使用压缩组件
图片、JS的预载入
将脚本放在底部
将样式文件放在页面顶部
使用外部的JS和CSS
精简代码

58、在JS中有哪些会被隐式转换为false

Undefined、null、关键字false、NaN、零、空字符串

59、定时器 setInterval 有一个有名函数 fn1,setInterval(fn1,500)与 setInterval(fn1(),500)有什么区别

第一个是重复执行每 500 毫秒执行一次,后面一个只执行一次。

60、外部 JS 文件出现中文字符,会出现什么问题,怎么解决

会出现乱码,加 charset="GB2312";

61、谈谈浏览器的内核,并且说一下什么是内核

Trident ([‘traɪd(ə)nt])–IE
Gecko ([‘gekəʊ])–Firefox
Presto ([‘prestəʊ])–opera
webkit—谷歌和Safari

浏览器内核又可以分成两部分:渲染引擎和 JS 引擎。它负责取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入 CSS 等),以及计算网页的显示方式,然后会输出至显示器或打印机。JS 引擎则是解析 Javascript 语言,执行 javascript 语言来实现网页的动态效果。

62、写一个通用的事件侦听器函数

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// event(事件)工具集
mhq.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;
}
};

63、如何判断一个对象是否属于某个类

使用instanceof (待完善)

1
2
3
if(a instanceof Person){
alert('yes');
}

64、模块化怎么做

立即执行函数,不暴露私有成员

1
2
3
4
5
6
7
8
9
10
11
12
13
var module1 = (function(){
var _count = 0;
var m1 = function(){
//...
};
var m2 = function(){
//...
};
return {
m1 : m1,
m2 : m2
};
})();

65、告诉我答案是多少?

(function(x){
delete x;
alert(x);
})(1+5);

函数参数无法 delete 删除,delete 只能删除通过 for in 访问的属性。当然,删除失败也不会报错,所以代码运行会弹出 1。

66、Jquery 与 jQuery UI 有啥区别?

jQuery是一个js库,主要提供的功能是选择器,属性修改和事件绑定等等。
jQuery UI则是在jQuery的基础上,利用jQuery的扩展性,设计的插件。

提供了一些常用的界面元素,诸如对话框、拖动行为、改变大小行为等等

67、jquery 中如何将数组转化为json字符串,然后再转化回来

jQuery中没有提供这个功能,所以你需要先编写两个jQuery的扩展:

1
2
3
4
5
6
7
8
$.fn.stringifyArray = function(array) {
return JSON.stringify(array);
}
$.fn.parseArray = function(array) {
return JSON.parse(array);
}
// 然后调用:
$("").stringifyArray(array);

68、http状态码有那些?分别代表是什么意思?

100-199 用于指定客户端应相应的某些动作。
200-299 用于表示请求成功。
300-399 用于已经移动的文件并且常被包含在定位头信息中指定新的地址信息。
400-499 用于指出客户端的错误。
400 语义有误,当前请求无法被服务器理解。
401 当前请求需要用户验证
403 服务器已经理解请求,但是拒绝执行它。
500-599 用于支持服务器错误。
503 – 服务不可用

感谢您的支持!