1.实现一个函数clone,可以对JavaScript中的5种主要的数据类型(包括Number、String、Object、Array、Boolean)进行值复制
考察点1:对于基本数据类型和引用数据类型在内存中存放的是值还是指针这一区别是否清楚
考察点2:是否知道如何判断一个变量是什么类型的
考察点3:递归算法的设计
//方法一:
Object.prototype.clone=function(){
varo=this.constructor===Array?[]:{};
for(vareinthis){
o[e]=typeofthis[e]===object?this[e].clone():this[e];
}
returno;
}
//方法二:
/**
*克隆一个对象
*
paramObj*
returns*/
functionclone(Obj){
varbuf;
if(ObjinstanceofArray){
buf=[];//创建一个空的数组
vari=Obj.length;
while(i--){
buf[i]=clone(Obj[i]);
}
returnbuf;
}elseif(ObjinstanceofObject){
buf={};//创建一个空对象
for(varkinObj){//为这个对象添加新的属性
buf[k]=clone(Obj[k]);
}
returnbuf;
}else{//普通变量直接赋值
returnObj;
}
}
2.如何消除一个数组里面重复的元素?
vararr=[1,2,3,3,4,4,5,5,6,1,9,3,25,4];
functiondeRepeat(){
varnewArr=[];
varobj={};
varindex=0;
varl=arr.length;
for(vari=0;il;i++){
if(obj[arr[i]]==undefined)
{
obj[arr[i]]=1;
newArr[index++]=arr[i];
}
elseif(obj[arr[i]]==1)
continue;
}
returnnewArr;
}
varnewArr2=deRepeat(arr);
alert(newArr2);//输出1,2,3,4,5,6,9,25
3.小贤是一条可爱的小狗(Dog),它的叫声很好听(wow),每次看到主人的时候就会乖乖叫一声(yelp)。从这段描述可以得到以下对象:
functionDog(){
this.wow=function(){
alert(’Wow’);
}
this.yelp=function(){
this.wow();
}
}
小芒和小贤一样,原来也是一条可爱的小狗,可是突然有一天疯了(MadDog),一看到人就会每隔半秒叫一声(wow)地不停叫唤(yelp)。请根据描述,按示例的形式用代码来实。(继承,原型,setInterval)
答案:
functionMadDog(){
this.yelp=function(){
varself=this;
setInterval(function(){
self.wow();
},);
}
}
MadDog.prototype=newDog();
//fortest
vardog=newDog();
dog.yelp();
varmadDog=newMadDog();
madDog.yelp();
4.下面这个ul,如何点击每一列的时候alert其index?(闭包)
ulid=”test”
li这是第一条/li
li这是第二条/li
li这是第三条/li
/ul
答案:
//方法一:
varlis=document.getElementById().getElementsByTagName(li);
for(vari=0;i3;i++)
{
lis[i].index=i;
lis[i].onclick=function(){
alert(this.index);
};
}
//方法二:
varlis=document.getElementById().getElementsByTagName(li);
for(vari=0;i3;i++)
{
lis[i].index=i;
lis[i].onclick=(function(a){
returnfunction(){
alert(a);
}
})(i);
}
5.编写一个JavaScript函数,输入指定类型的选择器(仅需支持id,class,tagName三种简单CSS选择器,无需兼容组合选择器)可以返回匹配的DOM节点,需考虑浏览器兼容性和性能。
/***
paramselector{String}传入的CSS选择器。*return{Array}*/答案:
varquery=function(selector){
varreg=/^(#)?(\.)?(\w+)$/img;
varregResult=reg.exec(selector);
varresult=[];
//如果是id选择器
if(regResult[1]){
if(regResult[3]){
if(typeofdocument.querySelector===function){
result.push(document.querySelector(regResult[3]));
}
else{
result.push(document.getElementById(regResult[3]));
}
}
}
//如果是class选择器
elseif(regResult[2]){
if(regResult[3]){
if(typeofdocument.getElementsByClassName===function){
vardoms=document.getElementsByClassName(regResult[3]);
if(doms){
result=converToArray(doms);
}
}
//如果不支持getElementsByClassName函数
else{
varallDoms=document.getElementsByTagName(*);
for(vari=0,len=allDoms.length;ilen;i++){
if(allDoms[i].className.search(newRegExp(regResult[2]))-1){
result.push(allDoms[i]);
}
}
}
}
}
//如果是标签选择器
elseif(regResult[3]){
vardoms=document.getElementsByTagName(regResult[3].toLowerCase());
if(doms){
result=converToArray(doms);
}
}
returnresult;
}
functionconverToArray(nodes){
vararray=null;
try{
array=Array.prototype.slice.call(nodes,0);//针对非IE浏览器
}catch(ex){
array=newArray();
for(vari=0,len=nodes.length;ilen;i++){
array.push(nodes[i])
}
}
returnarray;
}
6.请评价以下代码并给出改进意见。
if(window.addEventListener){
varaddListener=function(el,type,listener,useCapture){
el.addEventListener(type,listener,useCapture);
};
}
elseif(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指向问题,所以调用它时需要处理一下
改进如下:
functionaddEvent(elem,type,handler){
if(elem.addEventListener){
elem.addEventListener(type,handler,false);
}elseif(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;
}
}
7.给String对象添加一个方法,传入一个string类型的参数,然后将string的每个字符间价格空格返回,例如:
addSpace(“helloworld”)//-‘helloworld’
String.prototype.spacify=function(){
returnthis.split().join();
};
接着上述问题答案提问,1)直接在对象的原型上添加方法是否安全?尤其是在Object对象上。(这个我没能答出?希望知道的说一下。)2)函数声明与函数表达式的区别?
答案:在js中,解析器在向执行环境中加载数据时,对函数声明和函数表达式并非是一视同仁的,解析器会率先读取函数声明,并使其在执行任何代码之前可用(可以访问),至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解析执行。
8.定义一个log方法,让它可以代理console.log的方法。
可行的方法一:
functionlog(msg){
console.log(msg);
}
log(helloworld!)//helloworld!
如果要传入多个参数呢?显然上面的方法不能满足要求,所以更好的方法是:
functionlog(){
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])。
9.在JavaScript中什么是伪数组?如何将伪数组转化为标准数组?
答案:
伪数组(类数组):无法直接调用数组方法或期望length属性有什么特殊的行为,但仍可以对真正数组遍历方法来遍历它们。典型的是函数的argument参数,还有像调用getElementsByTagName,document.childNodes之类的,它们都返回NodeList对象都属于伪数组。可以使用Array.prototype.slice.call(fakeArray)将数组转化为真正的Array对象。
假设接第八题题干,我们要给每个log方法添加一个”(app)”前缀,比如’helloworld!’-’(app)helloworld!’。方法如下:
functionlog(){
varargs=Array.prototype.slice.call(arguments);//为了使用unshift数组方法,将argument转化为真正的数组
args.unshift((app));
console.log.apply(console,args);
};
10.对作用域上下文和this的理解,看下列代码:
varUser={
count:1,
getCount:function(){
returnthis.count;
}
};
console.log(User.getCount());//what?
varfunc=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){
varself=this;
returnfunction(){
returnself.apply(context,arguments);
};
}
varfunc=User.getCount.bind(User);
console.log(func());
11.原生JS的window.onload与Jquery的$(document).ready(function(){})有什么不同?如何用原生JS实现Jq的ready方法?
window.onload()方法是必须等到页面内包括图片的所有元素加载完毕后才能执行。
$(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕。
/*
*传递函数给whenReady()
*当文档解析完毕且为操作准备就绪时,函数作为document的方法调用
*/
varwhenReady=(function(){//这个函数返回whenReady()函数
varfuncs=[];//当获得事件时,要运行的函数
varready=false;//当触发事件处理程序时,切换为true
//当文档就绪时,调用事件处理程序
functionhandler(e){
if(ready)return;//确保事件处理程序只完整运行一次
//如果发生onreadystatechange事件,但其状态不是北京看的好白癜风的医院白癜疯