关于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">
//
function show(){
console.log("这是一个函数");
} //
(function(){
console.log("这是一个函数表达式");
})(); //
var obj1={
show:function(){
console.log("这是一个方法");
}
}; //
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'));