Js问题--高级

1、JQuery 一个对象可以同时绑定多个事件,这是如何实现的?
jQuery 可以给一个对象同时绑定多个事件,低层实现方式是使用 addEventListner或
attachEvent兼容不同的浏览器实现事件的绑定,这样可以给同一个对象注册多个事件。
2、知道什么是 webkit 么? 知道怎么用浏览器的各种工具来调试和 debug代码么?
Webkit 是浏览器引擎,包括html渲染和js 解析功能,手机浏览器的主流内核,与之相对应
的引擎有Gecko(Mozilla Firefox 等使用)和Trident(也称MSHTML,IE 使用)。 141
对于浏览器的调试工具要熟练使用,主要是页面结构分析,后台请求信息查看,js 调
试工具使用,熟练使用这些工具可以快速提高解决问题的效率
3、如何测试前端代码? 知道 BDD, TDD, Unit Test 么? 知道怎么测试你的前端工程
么(mocha, sinon, jasmin, qUnit..)?
了解 BDD 行为驱动开发与 TDD 测试驱动开发已经单元测试相关概念,
4 、前端 templating(Mustache, underscore, handlebars) 是干嘛的 , 怎么用 ?
Web 模板引擎是为了使用户界面与业务数据(内容)分离而产生的,
Mustache 是一个 logic-less (轻逻辑)模板解析引擎,它的优势在于可以应用在
Javascript、PHP、Python、Perl 等多种编程语言中。
Underscore 封装了常用的JavaScript 对象操作方法,用于提高开发效率。Handlebars 是
JavaScript 一个语义模板库,通过对 view和data 的分离来快速构建Web模板。
5 、简述一下 Handlebars 的基本用法?
没有用过的话说出它是干什么的即可
官网: http://handlebarsjs.com/
参考:J:\代码,PPT,笔记,电子书\面试题\handlebarDemo
6 、简述一下 Handlerbars 的对模板的基本处理流程, 如何编译的?如何缓存
的?
学习技术不仅要会用,还有熟悉它的实现机制,这样在开发中遇到问题时才能更好的解决
7 、用 js 实现千位分隔符 ?
原生 js 的熟练度,实践经验,实现思路
8 、检测浏览器版本版本有哪些方式?
IE与标准浏览器判断,IE不同版本的判断,userAgent
var ie = /*@cc_on !@*/false; 142
9 、我们给一个 dom 同时绑定两个点击事件,一个用捕获,一个用冒泡,你来说
下会执行几次事件,然后会先执行冒泡还是捕获
对两种事件模型的理解
10 、实现一个函数 clone ,可以对 JavaScript 中的 5 种主要的数据类型(包括
Number String Object Array Boolean )进行值复制
考察点1:对于基本数据类型和引用数据类型在内存中存放的是值还是指针这一区
别是否清楚
考察点2:是否知道如何判断一个变量是什么类型的
考察点3:递归算法的设计
// 方法一:
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]);
} 143
return buf;
}else{
//普通变量直接赋值
return Obj;
}
}
11 、如何消除一个数组里面重复的元素?
var arr=[1,2,3,3,4,4,5,5,6,1,9,3,25,4];
function deRepeat(){
var newArr=[];
var obj={}; var
index=0;
var l=arr.length; for(var
i=0;i<l;i++){
if(obj[arr[i]]==undefined)
{
obj[arr[i]]=1;
newArr[index++]=arr[i];
}
else if(obj[arr[i]]==1)
continue;
}
return newArr;
}
var newArr2=deRepeat(arr); alert(newArr2); //输
出 1,2,3,4,5,6,9,25
12 、小贤是一条可爱的小狗 (Dog) ,它的叫声很好听 (wow) ,每次看到主人的时
候就会乖乖叫一声 (yelp) 。从这段描述可以得到以下对象:
function Dog() {
this.wow = function() {
alert(’Wow’);
}
this.yelp = function() {
this.wow();
}
} 小芒和小贤一样,原来也是一条可爱的小狗,可是突然有一天疯了(MadDog),一看到人就会
隔半秒叫一声(wow)地不停叫唤(yelp)。请根据描述,按示例的形式用代码来实。(继承, 原型,
setInterval)
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();
13 、下面这个 ul ,如何点击每一列的时候 alert index? (闭包)
<ul id=”test”>
<li>这是第一条</li>
<li>这是第二条</li>
<li>这是第三条</li>
</ul>
// 方法一:
var lis=document.getElementById('2223').getElementsByTagName('li'); for(var
i=0;i<3;i++)
{
lis[i].index=i;
lis[i].οnclick=function(){
alert(this.index);
};
}
//方法二:
var lis=document.getElementById('2223').getElementsByTagName('li'); for(var
i=0;i<3;i++){
144 145
lis[i].index=i;
lis[i].οnclick=(function(a){
return function() {
alert(a);
}
})(i);
}
14 、编写一个 JavaScript 函数,输入指定类型的选择器 ( 仅需支持 id class
tagName 三种简单 CSS 选择器,无需兼容组合选择器 ) 可以返回匹配的 DOM
点,需考虑浏览器兼容性和性能。
/***
@param selector
{String}
传入的CSS选择器。*
@return
{Array}*/
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]));
}
}
}
//如果是class 选择器else
if(regResult[2]){
if(regResult[3]) {
if(typeof document.getElementsByClassName === 'function') { var doms =
document.getElementsByClassName(regResult[3]); if(doms) {
result = converToArray(doms);
}
} //如果不支持getElementsByClassName函数else {
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;
}
15 、请评价以下代码并给出改进意见。
if(window.addEventListener){
var addListener =
function(el,type,listener,useCapture){ el.addEventListener(ty
pe,listener,useCapture);
146 147
};
}
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 指向问题,所以调用它时需要处理一下改进如
下:
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;
}
}
16 、给 String 对象添加一个方法,传入一个 string 类型的参数,然后将 string
每个字符间价格空格返回,例如:
addSpace(“hello world”) // -> ‘h e l l o
w o r l d’
String.prototype.spacify = function(){
return this.split('').join(' ');
}; 148
接着上述问题答案提问,1)直接在对象的原型上添加方法是否安全?尤其是在 Object 对象
上。(这个我没能答出?希望知道的说一下。)2)函数声明与函数表达式的区别?
答案:在js 中,解析器在向执行环境中加载数据时,对函数声明和函数表达式并非是一视 同仁
的,解析器会率先读取函数声明,并使其在执行任何代码之前可用(可以访问),至于 函数表达
式,则必须等到解析器执行到它所在的代码行,才会真正被解析执行。
17 、定义一个 log 方法,让它可以代理 console.log 的方法。
可 行 的 方 法 一 :
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]) 。
18 、在 Javascript 中什么是伪数组?如何将伪数组转化为标准数组?
伪数组(类数组):无法直接调用数组方法或期望 length 属性有什么特殊的行为,但仍可以对
真正数组遍历方法来遍历它们。典型的是函数的argument 参数,还有像调用
getElementsByTagName,document.childNodes之类的,它们都返回NodeList 对象都属于伪数组。可以使
用Array.prototype.slice.call(fakeArray)将数组转化为真正的Array对象。
假设接第八题题干,我们要给每个 log 方法添加一个”(app)”前缀,比如’helloworld!’
->’(app)hello world!’。方法如下: 149
function log(){
var args = Array.prototype.slice.call(arguments);
//为了使用unshift 数
组方法,将 argument 转化为真正的数组
args.unshift('(app)');
console.log.apply(console, args);
};
19 、对作用域上下文和 this 的理解,看下列代码:
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。兼容各个浏览器完整代码如下:
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());
20 、原生 JS window.onload Jquery $(document).ready(function(){}) 有什
么不同?如何用原生 JS 实现 Jq ready 方法?
window.onload()方法是必须等到页面内包括图片的所有元素加载完毕后才能执行。 150
$(document).ready()是 DOM 结构绘制完毕后就执行,不必等到加载完毕。
/*
* 传递函数给whenReady()
* 当文档解析完毕且为操作准备就绪时,函数作为 document 的方法调用
*/
varwhenReady=(function(){
//这个函数返回 whenReady()
函数
var funcs = [];
//当获得事件时,要运行的函数var
ready = false;
//当触发事件处理程序时,切换为true
//当文档就绪时,调用事件处理程序
function handler(e) {
if(ready) return;
//确保事件处理程序只完整运行一次
//如果发生 onreadystatechange 事件,但其状态不是 complete 的话,那么文
档尚未准备好
'complete') {
if(e.type === 'onreadystatechange' && document.readyState !== 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); 151
}
//返回 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.c
allee, false);
fn();//执行函数
}, false);
}else if(document.attachEvent) {//IE document.attachEvent('onreadystatechange',
function() {
if(document.readyState == 'complete')
{ document.detachEvent('onreadystatechange',
arguments.callee);
}
});
}
};
fn();//函数执行
21 、(设计题)想实现一个对页面某个节点的拖曳?如何做?(使用原生 JS
回答出概念即可,下面是几个要点
1. 给需要拖拽的节点绑定mousedown,
mousemove,
mouseup事件
2. mousedown 事件触发后,开始拖拽
3. mousemove 时,需要通过event.clientX和clientY 获取拖拽位置,并实时更新位置
4. mouseup 时,拖拽结束
5. 需要注意浏览器边界的情况 152
22 、请实现如下功能
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")returnfalse;
},
hideTip: function(bNever){
if(bNever) setcookie('tips', 'never_show_again', 365);
oTips.style.display = "none";//隐藏 153
},
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();
})();
23 、说出以下函数的作用是?空白区域应该填写什么?
//define
(function(window){
function fn(str){
this.str=str;
}
fn.prototype.format = function(){ var arg =
;
return
this.str.replace(
,function(a,b){ retur
n 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
24、 Javascript 作用域链?
理解变量和函数的访问范围和生命周期,全局作用域与局部作用域的区别,JavaScript 中没
有块作用域,函数的嵌套形成不同层次的作用域,嵌套的层次形成链式形式,通过作用 域链查找
属性的规则需要深入理解。
25、 谈谈 this 对象的理解。
理解不同形式的函数调用方式下的 this指向,理解事件函数、定时函数中的this 指向,函数
的调用形式决定了this 的指向。
26、 eval 是做什么的?
它的功能是把对应的字符串解析成 JS 代码并运行;应该避免使用eval,不安全,非常耗
性能(2个步骤,一次解析成js 语句,一次执行)
27、 关于事件,IE 与火狐的事件机制有什么区别? 如何阻止冒泡?
[1].在IE 中,事件对象是作为一个全局变量来保存和维护的.所有的浏览器事件,不管是用户触发
的, 还是其他事件, 都会更新 window.event 对象. 所以在代码中, 只要调用window.event 就
可以获取事件对象,再 event.srcElement 就可以取得触发事件的元素进行进一步处理.
[2].在FireFox中,事件对象却不是全局对象,一般情况下,是现场发生,现场使用,FireFox 把事件
对象自动传给事件处理程序.
关于事件的兼容性处理要熟练掌握,事件对象具体哪些属性存在兼容性问题,IE 与标准事
件模型事件冒泡与事件捕获的支持要理解
28、 什么是闭包(closure),为什么要用它?
简单的理解是函数的嵌套形成闭包,闭包包括函数本身已经它的外部作用域 使
用闭包可以形成独立的空间,延长变量的生命周期,报存中间状态值
154 155
正常模式下,如果对象有多个重名属性,最后赋值的那个属性会覆盖前面的值。严格模式下
正常模式下,对一个对象的只读属性进行赋值,不会报错,只会默默地失败。严格模式下,
这属于语法错误。
语法错误。
29、javascript 代码中的"use strict";是什么意思 ? 使用它区别是什么?
意思是使用严格模式,使用严格模式,一些不规范的语法将不再支持
09-10 87
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值