各大互联网公司前端笔试面试题–JavaScript篇(持续更新)

整理分享出来希望更多的前端er共同进步吧,不仅适用于求职者,对于巩固复习js更是大有裨益。
而更多的题目是我一路以来收集的,也有往年的,答案不确保一定正确,如有错误或有更好的解法,还请斧正。
前面几题是会很基础,越下越有深度。

初级Javascript

1.JavaScript是一门什么样的语言,它有哪些特点?

没有标准答案。

2.JavaScript的数据类型都有什么?

基本数据类型:String,boolean,Number,Undefined, Null
引用数据类型:Object(Array,Date,RegExp,Function)
那么问题来了,如何判断某变量是否为数组数据类型?

  • 方法一.判断其是否具有“数组性质”,如slice()方法。可自己给该变量定义slice方法,故有时会失效。

  • 方法二.obj instanceof Array 在某些IE版本中不正确。

  • 方法三.方法一二皆有漏洞,在ECMA Script5中定义了新方法Array.isArray(), 保证其兼容性,最好的方法如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <script type="text/javascript">
    if (typeof Array.isArray == "undefined") {
    Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === "[object Array]";
    };
    }
    var s = new Array();
    if (Array.isArray(s)) {
    console.log("数组");
    } else {
    console.log("非数组");
    }
    </script>

检测Function、Date、RegExp、Error、Object都可以使用以上类似方式实现

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
if(typeof Function.isFunction=="undefined"){
Function.isFunction=function(value){
return Object.prototype.toString.call(value)==="[object Function]";
};
}
if(typeof Date.isDate=="undefined"){
Date.isDate=function(value){
return Object.prototype.toString.call(value)==="[object Date]";
};
}
if(typeof RegExp.isRegExp=="undefined"){
RegExp.isRegExp=function(value){
return Object.prototype.toString.call(value)==="[object RegExp]";
};
}
if(typeof Error.isError=="undefined"){
Error.isError=function(value){
return Object.prototype.toString.call(value)==="[object Error]";
};
}
if(typeof Object.isObject=="undefined"){
Object.isObject=function(value){
return Object.prototype.toString.call(value)==="[object Object]";
};
}
//......

如何判断基础数据类型?

1、检测字符串(string)、数值(number)、布尔值(boolean)、未定义(undefined)、函数(function) 、对象(object)使用typeof(在Safari和Chrome中检测正则也会返回 “function”)
2、检测null 应用“===”,返回”null”
3、检测其它对象:

  • 方法一:利用instanceof/constructor
    (再某些ie版本中存在跨iframe问题,每个iframe下都有自己的一套原型链,跨frame实例化的对象彼此是不共享原型链)

    1
    2
    3
    4
    5
    6
    var isObject=value instanceof Object;
    var isArray=value instanceof Array;//此处要想返回true,首先value必须是一个数组,而且必须与Array构造函数在同个全局作用域中。(Array是window的属性),如果value是在另一个frame中定义的数组,那么以上的代码会返回false.
    var isDate=value instanceof Date;
    var isRegExp=value instanceof RegExp;
    var isError=value instanceof Error;
    var isArray=(value.constructor == Array);
  • 方法二:利用 Object.prototype.toString.call() (解决了方法一跨iframe 失效的问题)

1
2
3
4
5
6
7
8
9
10
11
Object.prototype.toString.call ({}); //"[object Object]"
Object.prototype.toString.call ([1,2,3,4]); //"[object Array]"
Object.prototype.toString.call(new Date()); //"[object Date]"
Object.prototype.toString.call(/^hello/); //"[object RegExp]"
Object.prototype.toString.call(new Error()); //"[object Error]"
Object.prototype.toString.call(new Number()); //"[object Number]"不建议用此方法创建变量
Object.prototype.toString.call(123); //"[object Number]"
Object.prototype.toString.call(new String()); //"[object String]"不建议用此方法创建变量
Object.prototype.toString.call('abc'); //"[object String]"
Object.prototype.toString.call(new Boolean());//"[object Boolean]"不建议用此方法创建变量
Object.prototype.toString.call(true); //"[object Boolean]"

综合typeof和instanceof封装一个获取类型的函数:

1
2
3
4
5
6
7
8
9
10
11
12
function type(ele) {
var r;
if (ele === null) r = 'null';
else if (ele instanceof Array) r = 'array';
else if (ele === window) r = 'window';
else if (ele instanceof Date) r = 'date';
else if (ele instanceof RegExp) r = 'regExp';
else if (ele instanceof Function) r = 'function';
else if (ele instanceof Error) r = 'Error';
else r = typeof ele;
return r;
}

参考jquery解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function type(obj) {
var class2type = {};
var toString = class2type.toString;
var arry = "Boolean Number String Function Array Date RegExp Object Error".split(" ");
arry.forEach(function(item, index) {
class2type["[object " + item + "]"] = item.toLowerCase();
});
if (obj === null) {
return obj + "";
}
return typeof obj === "object" || typeof obj === "function" ?
class2type[toString.call(obj)] || "object" :
typeof obj;
}

或者:

1
2
3
4
function getType(obj) {
var typeName;
return ((typeName = typeof(obj)) == "object" ? obj == null && "null" || Object.prototype.toString.call(obj).slice(8, -1):typeName).toLowerCase();
}

3.已知ID的Input输入框,希望获取这个输入框的输入值,怎么做?(不使用第三方框架)

1
document.getElementById("ID").value

4.希望获取到页面中所有的checkbox怎么做?(不使用第三方框架)

1
2
3
4
5
6
7
8
9
var domList = document.getElementsByTagName('input');
var checkBoxList = [];
var len = domList.length; //缓存到局部变量
while (len--) //使用while的效率比for循环更高
{
if (domList[len].type == 'checkbox') {
checkBoxList.push(domList[len]);
}
}

5.设置一个已知ID的DIV的html内容为xxxx,字体颜色设置为黑色(不使用第三方框架)

1
2
3
var dom = document.getElementById("id");
dom.innerHTML = "Nothing is impossible!";
dom.style.color="red";

6.当一个DOM节点被点击时候,我们希望能够执行一个函数,应该怎么做?

  • 直接在DOM里绑定事件:
  • 在JS里通过onclick绑定:xxx.onclick = test
  • 通过事件添加进行绑定:addEventListener(xxx, ‘click’, test)

那么问题来了,Javascript的事件流模型都有什么?

  • “事件冒泡”:事件开始由最具体的元素接受,然后逐级向上传播
  • “事件捕捉”:事件由最不具体的节点先接收,然后逐级向下,一直到最具体的
  • “DOM事件流”:三个阶段:事件捕捉,目标阶段,事件冒泡

7.什么是Ajax和JSON,它们的优缺点。
Ajax是异步JavaScript和XML,用于在Web页面中实现异步数据交互。
优点:

  • 可以使得页面不重载全部内容的情况下加载局部内容,降低数据传输量
  • 避免用户不断刷新或者跳转页面,提高用户体验
    缺点:
  • 对搜索引擎不友好
  • 要实现ajax下的前后退功能成本较大
  • 可能造成请求数的增加
  • 跨域问题限制

JSON是一种轻量级的数据交换格式,ECMA的一个子集
优点:轻量级、易于人的阅读和编写,便于机器(JavaScript)解析,支持复合数据类型(数组、对象、字符串、数字)

8.看下列代码输出为何?解释原因。

1
2
3
var a ;
alert(typeof a); //undefined;
alert(b);//Uncaught ReferenceError: b is not defined 报错

解释:Undefined是一个只有一个值的数据类型,这个值就是“undefined”,在使用var声明变量但并未对其赋值进行初始化时,这个变量的值就是undefined。而b由于未声明将报错。注意未申明的变量和声明了未赋值的是不一样的。

9.看下列代码,输出什么?解释原因。

1
2
var a = null;
alert(typeof a);

解释:null是一个只有一个值的数据类型,这个值就是null。表示一个空指针对象,所以用typeof检测会返回”object”。

10.看下列代码,输出什么?解释原因。

1
2
3
4
5
6
7
8
9
var undefined;
undefined == null; //true
1 == true; //true
2 == true; //true
0 == false; //true
0 == ''; //true
NaN == NaN; //false
[] == false; //true
[] == ![]; //true
  • undefined与null相等,但不恒等(===)
  • 一个是number一个是string时,会尝试将string转换为number
  • 尝试将boolean转换为number,0或1
  • 尝试将Object转换成number或string,取决于另外一个对比量的类型
  • 所以,对于0、空字符串的判断,建议使用 “===” 。“===”会先判断两边的值类型,类型不匹配时为false。

那么问题来了,看下面的代码,输出什么,foo的类型为什么?

1
2
3
var foo = "11" + 2 - "1";
console.log(foo);
console.log(typeof foo);

执行完后foo的值为111,foo的类型为Number。

1
2
3
var foo = "11" + 2 + "1";
console.log(foo);
console.log(typeof foo);

执行完后foo的值为1121,foo的类型为String。

11.看代码给答案。

1
2
3
4
5
var a = new Object();
a.value = 1;
b = a;
b.value = 2;
alert(a.value);

答案:2(考察引用数据类型细节)

12.已知数组var stringArray = [“This”, “is”, “Baidu”, “Campus”],Alert出”This is Baidu Campus”。

答案:alert(stringArray.join(“”))

1
2
var stringArray = ["This", "is", "Baidu", "Campus"];
alert(stringArray.join(" "));

已知有字符串foo=”get-element-by-id”,写一个function将其转化成驼峰表示法”getElementById”。

1
2
3
4
5
6
7
8
9
10
function combo(msg) {
var arr = msg.split("-");
for(var n=0;n<arr.length;n++)
{
arr[n] = arr[n].charAt(0).toUpperCase() + arr[n].substring(1,arr[n].length);
}
msg = arr.join("");
return msg;
}
alert(combo('get-element-by-id'));

(考察基础API)
13.var numberArray = [3,6,2,4,1,5]; (考察基础API)
1) 实现对该数组的倒排,输出[5,1,4,2,6,3]

1
2
3
var numberArray = [3,6,2,4,1,5];
numberArray.reverse();
alert(numberArray);//5,1,4,2,6,3

2) 实现对该数组的降序排列,输出[6,5,4,3,2,1]

1
2
3
4
5
6
7
var numberArray = [3,6,2,4,1,5];
numberArray.sort(); //默认升序
alert(numberArray);//1,2,3,4,5,6
numberArray.sort(function (a,b) { //降序
return b-a;
})
alert(numberArray);//6,5,4,3,2,1

14.输出今天的日期,以YYYY-MM-DD的方式,比如今天是2016年9月06日,则输出2016-09-06

1
2
3
4
5
6
7
var d = new Date();
var year = d.getFullYear();
var month = d.getMonth()+1;
month = month < 10 ? '0'+month : month;
var day = d.getDate();
day = day < 10 ? '0'+day : day;
alert(year + '-' + month + '-' + day);

15.将字符串”{$id}{$name}”中的{$id}替换成10,{$name}替换成Tony (使用正则表达式)

1
2
3
var htmlText = "<tr><td>{$id}</td><td>{$id}_{$name}</td></tr>";
htmlText = htmlText.replace(/{\$id}/g, '10').replace(/{\$name}/g, 'Tony');
document.writeln(htmlText);

正则表达式
1./pattern/是正则表达式的界定符,里面的内容(pattern)是要匹配的内容,例如上面的/{\$name}/g,其中g是全局匹配。
2.由于$符号与正则表达式已有规则冲突了,所以要用’\’转义。
3.

16.为了保证页面输出安全,我们经常需要对一些特殊的字符进行转义,请写一个函数escapeHtml,将<, >, &, “进行转义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function escapeHtml(str)
{
return str.replace(/[<>"&]/g,function (match) {
switch (match)
{
case "<":
return "&lt;";
case ">":
return "&gt;";
case "&":
return "&amp;";
case "\"":
return "&quot;";
}
});
}

17.foo = foo || bar ,这行代码是什么意思?为什么要这样写?

答案:if(foo) foo = bar; //如果foo存在,值不变,否则把bar的值赋给foo。
短路表达式:作为”&&”和”||”操作符的操作数表达式,这些表达式在进行求值时,只要最终的结果已经可以确定是真或假,求值过程便告终止,这称之为短路求值。

18.看下列代码,将会输出什么?(变量声明提升)

1
2
3
4
5
6
7
8
9
var foo = 1;
function f()
{
console.log(foo);
var foo = 2;
console.log(foo); //访问局部执行环境的成员变量
console.log(window.foo);
//访问全局执行环境的成员变量或者也可以叫作父环境中的标识符
}

答案:输出undefined 和 2。
上面代码相当于:

1
2
3
4
5
6
7
function f()
{
var foo;
console.log(foo); //undefined
foo = 2;
console.log(foo);
}

函数声明与变量声明会被JavaScript引擎隐式地提升到当前作用域的顶部,但是只提升名称不会提升赋值部分。
其实在执行函数对象时候,首先对函数内部成员变量进行初始化,此时函数对象就会产生一个自己的执行环境,每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。
执行环境分为全局执行环境(global)和局部执行环境(local),按照f函数执行流程来看,首先f函数会先初始化执行环境,包括对函数成员初始化,当代码在一个环境执中执行时,会创建变量对象的作用域链。执行到console.log(foo);时,查找foo标识符解析是沿着作用域链一级一级地向上搜索标识符,先在局部执行环境local中查找foo标识符,在这个搜索过程中,如果存在一个foo局部的变量的定义,则搜索会自动停止,不再进入另一个变量对象。换句话说,如果局部环境中存在着同名标识符,就不会使用位于父环境中的标识符,否则搜索过程将一直追溯到全局环境的变量对象。如果找不到标识符,通常会导致错误发生。
建议减少通过作用域链来查找标识符次数,很明显,访问局部变量要比访问全局变量更快,因为不用向上搜索作用域链。JavaScript引擎在优化标识符查询方面做得不错,因此这个差别在将来恐怕就可以忽略不计了。

需要注意的是,JavaScript没有块级作用域经常会导致理解上的困惑。在其他类C的语言中,由花括号封闭的代码块都有自己的作用域(如果用ECMAScript的话来讲,就是它们自己的执行环境),因而支持根据条件来定义变量。例如,下面的代码在JavaScript中并不会得到想象中的结果:

1
2
3
4
if(true){
var color = "blue";
}
alert(color); //"blue";

这里是在一个if语句中定义了变量color。如果是在C、C++或Java中,color会在if语句执行完毕后被销毁。但在JavaScript中,if语句中的变量声明会将变量添加到当前的执行环境(在这里是全局环境)中。在使用for语句时尤其要牢记这一差异,例如:

1
2
3
4
5
for(var i = 0;i < 10;i++)
{
doSomething(i);
}
alert(i) //10

对于有块级作用域的语言来说,for语句初始化变量的表达式所定义的变量,只会存在于循环的环境之中。而对于JavaScript来说,由for语句创建的变量i即使在for循环执行结束后,也依旧会存在于循环外部的执行环境中。

19.用js实现随机选取10–100之间的10个数字,存入一个数组,并排序。

1
2
3
4
5
6
7
8
9
10
var iArray = [];
function getRandom(istart,iend) {
var iChoice = iend - istart + 1;
return Math.floor(Math.random()*iChoice+istart);
}
for(var i=0;i<10;i++)
{
iArray.push(getRandom(10,100));
}
document.writeln(iArray.sort());

20.把两个数组合并,并删除第二个元素。

1
2
3
4
5
var array = ['a','b','c'];
var brray = ['d','e','f'];
var crray = array.concat(brray);
crray.splice(1,1);
document.writeln(crray);

21.怎样添加、移除、移动、复制、创建和查找节点(原生JS,实在基础,没细写每一步)

  • (1)创建新节点

createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点

  • (2)添加、移除、替换、插入

appendChild() //添加
removeChild() //移除
replaceChild() //替换
insertBefore() //插入

  • (3)查找

getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的Name属性的值
getElementById() //通过元素Id,唯一性

文章目录
  1. 1. 初级Javascript
    1. 1.1. 1.JavaScript是一门什么样的语言,它有哪些特点?
    2. 1.2. 2.JavaScript的数据类型都有什么?
    3. 1.3. 如何判断基础数据类型?
    4. 1.4. 3.已知ID的Input输入框,希望获取这个输入框的输入值,怎么做?(不使用第三方框架)
    5. 1.5. 4.希望获取到页面中所有的checkbox怎么做?(不使用第三方框架)
    6. 1.6. 5.设置一个已知ID的DIV的html内容为xxxx,字体颜色设置为黑色(不使用第三方框架)
    7. 1.7. 6.当一个DOM节点被点击时候,我们希望能够执行一个函数,应该怎么做?
    8. 1.8. 8.看下列代码输出为何?解释原因。
    9. 1.9. 9.看下列代码,输出什么?解释原因。
    10. 1.10. 10.看下列代码,输出什么?解释原因。
    11. 1.11. 11.看代码给答案。
    12. 1.12. 12.已知数组var stringArray = [“This”, “is”, “Baidu”, “Campus”],Alert出”This is Baidu Campus”。
    13. 1.13. 已知有字符串foo=”get-element-by-id”,写一个function将其转化成驼峰表示法”getElementById”。
    14. 1.14. 14.输出今天的日期,以YYYY-MM-DD的方式,比如今天是2016年9月06日,则输出2016-09-06
    15. 1.15. 15.将字符串”{$id}{$name}”中的{$id}替换成10,{$name}替换成Tony (使用正则表达式)
    16. 1.16. 16.为了保证页面输出安全,我们经常需要对一些特殊的字符进行转义,请写一个函数escapeHtml,将<, >, &, “进行转义
    17. 1.17. 17.foo = foo || bar ,这行代码是什么意思?为什么要这样写?
    18. 1.18. 18.看下列代码,将会输出什么?(变量声明提升)
    19. 1.19. 19.用js实现随机选取10–100之间的10个数字,存入一个数组,并排序。
    20. 1.20. 20.把两个数组合并,并删除第二个元素。
    21. 1.21. 21.怎样添加、移除、移动、复制、创建和查找节点(原生JS,实在基础,没细写每一步)