关于JavaScript常见的面试题总结
一、JavaScript基本数据类型
- null:空、无。表示不存在,当为对象的属性赋值为null,表示删除该属性
- undefined:未定义。当声明变量却没有赋值时会显示该值。可以为变量赋值为undefined
- number:数值。最原始的数据类型
- string:字符串。最抽象的数据类型
- boolean:布尔值。最机械的数据类型
- object:对象。面向对象的基础
怎么判断是否是某数据类型??
typeof:
alert(typeof 1); // 返回字符串"number" alert(typeof "1"); // 返回字符串"string" alert(typeof true); // 返回字符串"boolean" alert(typeof {}); // 返回字符串"object" alert(typeof []); // 返回字符串"object " alert(typeof function(){}); // 返回字符串"function" alert(typeof null); // 返回字符串"object" alert(typeof undefined); // 返回字符串"undefined"
示例代码:
<script type="text/javascript"> var app={}; alert(typeof app); </script>
运行效果:
二、闭包的相关问题
问题:点击每个li输出里面的内容
示例代码:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>闭包</title> </head> <body> <ul id="parent"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> </ul> <script> var ul = document.getElementById('parent'); var li = ul.getElementsByTagName('li'); for(var i=0;i<li.length;i++){ li[i].onclick=function(){ alert(i); } } </script> </body> </html>
运行效果:
我点击的是3 而弹出i的是却是7
原因就在于 点击事件的函数内部使用外部的变量i一直在变化,当我们指定click事件时并没有保存i的副本,这样做也是为了提高性能,但达不到我们的目的,我们要让他执行的上下文保存i的副本,这种机制就是闭包。
因此,小编总结了三种比较常见的办法 让点击每个li输出里面的内容
No1:
运行效果:
达到了我们想要的效果
理解:当一个内部函数被调用,就会形成闭包,闭包就是能够读取其他函数内部变量的函数,定义在一个函数内部的函,创建一个闭包环境,让返回的这个子程序抓住i,以便在后续执行时可以保持对这个i的引用。内部函数比外部函数有更长的生命周期;函数可以访问它被创建时所处的上下文环境。
No2:
运行效果:
达到了我们想要的效果
理解:使用this的原理,因为对于this的隐式绑定来说,this指向的是调用位置上的包含对象,也就是你点击的那个li[i]
。this 谁调用它他就指向谁 通过this的指向就可以得到我们想要的结果
No3:
运行效果:
理解:使用的是事件代理以及event事件的内置属性来达到效果。
二、JavaScript面向对象
对象就是“键/值”对的集合并拥有一个连接到原型(prototype)对隐藏连接。
2.1、对象常量(字面量)
一个对象字面量就是包含在一对花括号中的零个或多个“键/值”对。对象字面量可以出现在任何允许表达式出现的地方。
对象的定义:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>面向对象</title> <script> //空对象对象 var obj={}; //对象的属性 var obj1 = {name:"foo",age:"19"}; var obj2 = {"nick name":"dog"}; //对象中的方法 var obj4 = { price:99, inc:function(){ //obj4这个对象调用this this指向obj4 obj4.price+=1 =100; alert(this.price+=1); } } obj4.inc(); </script> </head> <body> </body> </html>
对象中可包含的内容:
对象常量可以出现在任何允许表达式出现的地方,对象、数组、函数可以相互间嵌套,形式可以多种多样。对象的值可以是:数组,函数,对象,基本数据类型等。
//对象中可包含的内容 var obj5 = [{ name: "jack" }, { name: "lucy", //常量 hobby:["读书","上网","代码"], //数组 friend:{name:"mark",height:198,friend:{}}, //对象 show:function(){ //函数 console.log("大家好,我是"+this.name); } }]; //对象中的this是动态的,指向的是:调用者 obj5[1].show();
输出:大家好,我是lucy
2.2、取值
方法一:直接使用点号运算
//3取值 var obj6={"nick name":"pig",realname:"Rose"}; console.log(obj6.realname); //console.log(obj6.nick name); 错误
2.3、枚举(遍历)
var obj7={weight:"55Kg","nick name":"pig",realname:"Rose"}; for (var key in obj7) { console.log(key+":"+obj7[key]); }
运行结果:
weight:55Kg
nick name:pig
realname:Rose
输出的顺序是不一定的
2.4、更新与添加
如果对象中存在属性就修改对应值,如果不存在就添加。对象通过引用传递,它们永远不会被复制
var obj8={realname:"King"}; obj8.realname="Queen"; //修改 obj8.weight=1000; //添加属性 obj8.show=function() //添加方法 { console.log(this.realname+","+this.weight); } obj8.show();
输出:
Queen,1000
var obj8={realname:"King"}; obj8.realname="Queen"; //修改 obj8.weight=1000; //添加属性 obj8.show=function() //添加方法 { console.log(this.realname+","+this.weight); } obj8.show(); //引用 var obj9=obj8; //obj9指向obj8的引用 obj9.realname="Jack"; obj8.show();
二、JavaScript当中的this
在JavaScript中this表示:谁调用它,this就是谁。
JavaScript是由对象组成的,一切皆为对象,万物皆为对象。this是一个动态的对象,根据调用的对象不同而发生变化,当然也可以使用call、apply修改this指向的对象。它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用
2.1、JavaScript中函数与方法的区分
在面向过程的语言中我们习惯把完成某个特定功能的代码块称为“函数”或“过程”,当然过程一般没有返回值。在面向对象语言中我们把对象的功能称为“方法”。但JavaScript是种介于面向对象与面向过程中间的语言,同样的方法有时是函数,有时是方法,如下所示:
<script type="text/javascript"> //1 function show(){ console.log("这是一个函数"); } //2 (function(){ console.log("这是一个函数表达式"); })(); //3 var obj1={ show:function(){ console.log("这是一个方法"); } }; //4 function obj2(){ //obj2是函数,构造函数 this.show=function(){ console.log("这是一个方法,是一个表达式"); } } var obj3=new obj2(); </script>
2.2、指向全局对象
当在全部范围内使用 this,它将会指向全局对象。一般是window对象,但全局对象不一定只有window,特别是在node.js环境中。作为函数调用时一般指向全局对象。
<script type="text/javascript"> var name="tom"; console.log(this.name); //顶层对象,一般为window function show() { console.log(this.name); //顶层对象,一般为window return function(){ console.log(this.name); //顶层对象,一般为window,因为返回的是函数 } } var f1=show(); f1(); </script>
2.3、作为事件时的this
示例代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>this</title> </head> <body> <input type="button" value="btnA" class="btn"/> <input type="button" value="btnB" class="btn"/> <input type="button" value="btnC" class="btn"/> <input type="button" value="btnD" onclick="handler()"/> <input type="button" value="btnE" id="btnE"/> <script> var btns= document.getElementsByClassName("btn"); for (var i=0;i<btns.length;i++) { btns[i].onclick=handler; } function handler(){ alert(this.value); } //handler中的this指向btnE document.getElementById("btnE").addEventListener("click",handler,false); </script> </body> </html>
运行结果:
点击按钮A
点击按钮D
没有取到this的值 此时的this指向了window对象
示例代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>this</title> </head> <body> <input type="button" value="按钮F的值" id="btnF" /> <input type="button" value="按钮G的值" id="btnG" onclick="app.show()"/> <script type="text/javascript"> value="window的值" var app = { value: "app的值", show: function() { alert(this.value); //如果show为事件,则this指向触发事件的对象 }, init: function() { //handler中的this指向btnE document.getElementById("btnF").addEventListener("click", this.show, false); } }; app.show(); //"app的值",show方法中的this指向app这个对象 app.init(); //init中的this指向谁app对象 </script> </body> </html>
运行加载时的结果:
点击按钮F时
点击按钮G时:
在HTML元素上直接指定事件严格来说都不能说是事件绑定,只能描述是当按钮点击完成后执行的函数。如果想将执行时的对象带回,可以增加参数this。
三、JavaScript数组
3.1数组的定义
var array01 = new Array(); //空数组 //alert(typeof array01); object var array02 = new Array(5); alert(array02.length); 5 var array03 = new Array("a","b" ,1,2,3,true,false); var array04 = [] //空数组 var array05 = [2,3,4,"x","y"];
运行效果:弹出array02的长度
3.2访问数组:
//访问数组 No1 console.log(array03[6]);
运行效果:
//访问数组 No2 for (var i = 0; i<array05.length;i++) { console.log("第"+(i+1)+"个值: "+array05[i]); }
运行效果:
//访问数组 No3 枚举 for(var i in array03){ console.log("下标为"+i+"的值为: "+array03[i]);//此处是i的下标 }
运行效果:
3.3、添加元素
将一个或多个新元素添加到数组未尾,并返回数组新长度
arrayObj. push([item1 [item2 [. . . [itemN ]]]]);
将一个或多个新元素添加到数组开始,数组中的元素自动后移,返回数组新长度
arrayObj.unshift([item1 [item2 [. . . [itemN ]]]]);
将一个或多个新元素插入到数组的指定位置,插入位置的元素自动后移,返回被删除元素数组,deleteCount要删除的元素个数
arrayObj.splice(insertPos,deleteCount,[item1[, item2[, . . . [,itemN]]]])
示例代码:
//添加元素 array03.push(5,8); //添加到末尾 array03.unshift("we"); //添加到末尾 for(var i in array03){ console.log("下标为"+i+"的值为: "+array03[i]);//此处是i的下标 }
运行效果:
//添加到中间 array05.splice(3,0,"w","e"); //从第三位开始插入 删除第三位后面 0 个元素 默认会删除3后面一个元素的 for (var i=0;i<array03.length;i++) { console.log(array05[i]); }
运行结果:
3.4、删除
移除最后一个元素并返回该元素值
arrayObj.pop();
移除最前一个元素并返回该元素值,数组中元素自动前移
arrayObj.shift();
删除从指定位置deletePos开始的指定数量deleteCount的元素,数组形式返回所移除的元素
arrayObj.splice(deletePos,deleteCount);
示例:
//删除最后一个元素 array03.pop(); for (var i in array03) { console.log(array03[i]); }
运行效果:
//删除首个一个元素 array03.shift(); for (var i in array03) { console.log(array03[i]); }
运行效果:
//删除指定位置与个数 array05.splice(1,2);//从下标第二的开始删 删2个 for (var i=0 ;i<array05.length; i++) { console.log(array05[i]); }
运行效果:
3.5、截取和合并
以数组的形式返回数组的一部分,注意不包括 end 对应的元素,如果省略 end 将复制 start 之后的所有元素
arrayObj.slice(start, [end]);
将多个数组(也可以是字符串,或者是数组和字符串的混合)连接为一个数组,返回连接好的新的数组
arrayObj.concat([item1[, item2[, . . . [,itemN]]]]);
示例:
//4.5、截取和合并 var array51=[1,2,3,4,5,6]; var array52=[7,8,9,0,"a","b","c"]; //截取,切片 var array53=array51.slice(2); //从第3个元素开始截取到最后 console.log("被截取:"+array53+"——"+array51); var array54=array51.slice(1,4); //从第3个元素开始截取到索引号为3的元素 console.log("被截取:"+array54+"——"+array51); //合并 var array55=array51.concat(array52,["d","e"],"f","g"); console.log("合并后:"+array55);
运行效果:
3.6、拷贝
返回数组的拷贝数组,注意是一个新的数组,不是指向
arrayObj.slice(0);
返回数组的拷贝数组,注意是一个新的数组,不是指向
arrayObj.concat();
因为数组是引用数据类型,直接赋值并没有达到真正实现拷贝,地址引用,我们需要的是深拷贝。
3.7、排序
反转元素(最前的排到最后、最后的排到最前),返回数组地址
arrayObj.reverse();
对数组元素排序,返回数组地址
arrayObj.sort();
arrayObj.sort(function(obj1,obj2){});
示例:
var array71=[4,5,6,1,2,3]; array71.sort(); console.log("排序后:"+array71); var array72=[{name:"tom",age:19},{name:"jack",age:20},{name:"lucy",age:18}]; array72.sort(function(user1,user2){ return user1.age<user2.age; }); console.log("排序后:"); for(var i in array72) console.log(array72[i].name+","+array72[i].age);
运行效果:
3.8、合并成字符
返回字符串,这个字符串将数组的每一个元素值连接在一起,中间用 separator 隔开。
arrayObj.join(separator);
//4.8、合并成字符与将字符拆分成数组 var array81=[1,3,5,7,9]; var ids=array81.join(","); console.log(ids); //拆分成数组 var text="hello nodejs and angular"; var array82=text.split(" "); console.log(array82);
运行效果:
3.9数组的排序
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <script type="text/javascript"> /* *(1)在数据集之中,选择一个元素作为"基准"(pivot)。 *(2)所有小于"基准"的元素,都放置于"基准"的"小值区域"(左边);所有大于"基准"的元素,都被置于"基准"的"大值区域"(右边)。 *(3)对以"基准"为分割线的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。 */ //定义一个数组 var arr = [85, 24, 63, 45, 17, 31, 96, 50]; //定义一个存放结果的result var result = ""; var quickSort = function(arr) { if(arr.length <= 1) { return arr; } //选取被排序数组中的任一元素作为"基准"(这里我们就选取数组中间的元素) var pivotIndex = Math.floor(arr.length / 2); var pivot = arr.splice(pivotIndex, 1); //声明两个数组分别用来放置"小值"和"大值" var left = []; var right = []; //然后,开始遍历数组,小于"基准"的元素放入左边的子集,大于基准的元素放入右边的子集。 for(var i = 0; i < arr.length; i++) { if(arr[i] < pivot) { left.push(arr[i]); } else { right.push(arr[i]); } } return result = quickSort(left).concat(pivot, quickSort(right)); }; //执行方法 quickSort(arr); //输出结果 console.log(result.join(" < ")); </script> </head> <body> </body> </html>
运行效果:
3.10数组的去重:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>数组去重</title> <script type="text/javascript"> var array11 = [2, 3, 4, 2, 3]; var newArr = []; //新建一个数组 function unique1(arr) { for(var i = 0, len = arr.length; i < len; i++) { if(newArr.indexOf(arr[i]) == -1) { //若新数组中未包含该项则将其存入新数组 newArr.push(arr[i]); } } return newArr; } unique1(array11); alert(newArr.length)//3 for(var i in newArr){ console.log(newArr[i]); } </script> </head> <body> </body> </html>
运行效果:
4.在未知多少个数字输入框的情况下,计算这些输入框中数字的总和:
代码:
$('input').keyup(function() { console.log($(this).val()); var num = 0; $('input').each(function(index, item){ num += Number($(item).val()); }); $("#business").text(num); });
效果:
附:
判断输入的是否是数字:
$.isNumber($(this).val());
判断输入的是否是大于0的数字:
$(this).val()<0;
4.1在一个table中,有未知多少个tr,我要选择最后三个用jQurey怎样实现:
代码:
$('tr td').slice(-3).css("color", "red");
效果:
5.1两个小案例
<ul class="ul"> <li ><a href="#">第一条</a></li> <li ><a href="#">第二条</a></li> <li ><a href="#">第三条</a></li> <li ><a href="#">第四条</a></li> <li ><a href="#">第五条</a></li> <li ><a href="#">第六条</a></li> <li ><a href="#">第七条</a></li> </ul> <span class="span">12.234567</span> <span class="span">43.7675</span> <span class="span">54.456765</span> <span class="span">23.76543</span> <span class="span">232.765</span> <span class="span">9876.4542345</span> <script type="text/javascript"> var arr = [1,5,3,6]; for(var i=0;i<arr.length;i++){ $(".ul li a:eq('"+arr[i]+"')").css("color","red"); console.log(arr[i]); } var span=0; for(var i=0;i<$(".span").length;i++){ span = Number($(".span:eq('"+i+"')").text()); span = parseFloat(span.toFixed(2)); $(".span:eq('"+i+"')").html(span); } </script>
运行效果:
6、jQuery 验证from表单提交文件类型
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>无标题文档</title> <script src="http://libs.baidu.com/jquery/2.1.1/jquery.min.js"></script> </head> <body> <form action="002.html" method="post"> <input type="file" name="myFile" id="myFile"/> <br /> <input type="file" name="myImg" id="myImg" /> <br /> <input type="submit" id="sub" value="提交"/><br /> </form> <script type="text/javascript"> $(document).ready(function () { $("#sub").on('click',function(){ function check(){ var filepathExl = $("input[name='myFile']").val(); var extStartExl = filepathExl.lastIndexOf("."); var ext1 = filepathExl.substring(extStartExl, filepathExl.length).toUpperCase(); var filepathImg = $("input[name='myImg']").val(); var extStart = filepathImg.lastIndexOf("."); var ext = filepathImg.substring(extStart, filepathImg.length).toUpperCase(); if (ext1 != ".XLS" && ext1 != ".XLSX") { alert("文件限于Excel格式"); return false; } if (ext != ".BMP" && ext != ".PNG" && ext != ".GIF" && ext != ".JPG" && ext != ".JPEG") { alert("图片限于bmp,png,gif,jpeg,jpg格式"); return false; } } return check(); }); }); </script> </body> </html>
7、图片显示并修改
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <script src="http://libs.baidu.com/jquery/2.1.1/jquery.min.js"></script> <style> .topleftbox { width: 200px; height: 130px; border: 1px solid #262626; padding: 3px; border-radius:4px; margin-left: 10px; margin-top: 10px; float: left; } .topleftbox #addimga { display: block; width: 100%; height: 100%; background-size:100% 100%; background-position: center center; background-repeat: no-repeat; } .topleftbox #addimga input { width: 100%; height: 100%; opacity: 0; } #sub{margin: 120px 10px;} </style> </head> <body> <form method="get" action="001.html" enctype="multipart/form-data"> <div class="topleftbox"> <a class="addimga" id="addimga" href="javascript:;"> <input type="file" name="file" onchange="showImg(this)"/> </a> </div> <input type="submit" name="" id="sub" value="提交" /> </form> <script> //常常显示的是一张原图 $("#addimga").css("background-image","url(img/10.jpg)"); //显示上传的图片 function showImg(obj) { var srcs = window.URL.createObjectURL(obj.files[0]); var addimga = document.getElementById("addimga"); if(srcs){ //把上传后的图片路径给a链接背景图片的路径 addimga.style.background = "url(" + srcs + ") center no-repeat"; $("#addimga").css("background-size", "100% 100%"); } } </script> </body> </html>
运行效果:
选择一张图片后
点击提交之后,图片信息已经发送过去
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <script src="http://libs.baidu.com/jquery/2.1.1/jquery.min.js"></script> <style> .topleftbox { width: 200px; height: 130px; border: 1px solid #262626; padding: 3px; border-radius:4px; margin-left: 10px; margin-top: 10px; float: left; } .topleftbox #addimga { display: block; width: 100%; height: 100%; background-size:100% 100%; background-position: center center; background-repeat: no-repeat; } .topleftbox #addimga input { width: 100%; height: 100%; opacity: 0; } #sub{margin: 120px 10px;} </style> </head> <body> <div class="topleftbox"> <a class="addimga" id="addimga" href="javascript:;"> <input type="file" name="file" id="file" onchange="showImg(this)"/> </a> </div> <input type="submit" name="" id="sub" value="提交" /> <script> //常常显示的是一张原本的图 $("#addimga").css("background-image","url(img/10.jpg)"); //显示上传的图片 function showImg(obj) { var srcs = window.URL.createObjectURL(obj.files[0]); var addimga = document.getElementById("addimga"); if(srcs){ //把上传后的图片路径给a链接背景图片的路径 addimga.style.background = "url(" + srcs + ") center no-repeat"; $("#addimga").css("background-size", "100% 100%"); } } $("#sub").on('click',function(){ var imgFile = $("#file").val(); $.ajax({ url:'001.html', data:imgFile, type:'get', dataType:'JSON', success:function(res){ console.log(res); }, error:function(re){ console.log("er") } }) }) </script> </body> </html>
如何让银行卡卡号每四位出现空格隔开
return val.replace(/s/g,'').replace(/(d{4})(?=d)/g,"$1 ");
JS 计算时间差
function getTimeSpace(startTime,endTime){ console.log(startTime,endTime) var spaceTine = new Date(endTime).getTime()-new Date(startTime).getTime(); //时间差的毫秒数 if (spaceTine<0) { alert('结束时间必须大于开始时间'); return ; } //计算出相差天数 var days=Math.floor(spaceTine/(24*3600*1000)) //计算出小时数 var leave1=spaceTine%(24*3600*1000) //计算天数后剩余的毫秒数 var hours=Math.floor(leave1/(3600*1000)) //计算相差分钟数 var leave2=leave1%(3600*1000) //计算小时数后剩余的毫秒数 var minutes=Math.floor(leave2/(60*1000)) //计算相差秒数 var leave3=leave2%(60*1000) //计算分钟数后剩余的毫秒数 var seconds=Math.round(leave3/1000) if (days>0) { if (hours==0) { return " 相差 "+days+"天 "+minutes+"分钟 "; }else{ return " 相差 "+days+"天 "+hours+"小时 "; } }else if(hours>0){ if (minutes==0) { return hours+"小时 "+seconds+" 秒"; }else{ return hours+"小时 "+minutes+" 分钟"; } }else if(minutes>0){ return minutes+" 分钟"+seconds+" 秒"; }else{ return seconds+" 秒"; } } console.log(getTimeSpace(new Date().getTime(),'2019-06-29 23:00:00'));