美文网首页
最基本的JavaScript面试题(16个)

最基本的JavaScript面试题(16个)

作者: 南慕瑶 | 来源:发表于2018-02-27 11:41 被阅读0次

1.使用 typeof bar === "object" 来确定 bar 是否是对象的潜在陷阱是什么?如何避免这个陷阱?

陷阱:

typeof null === "object" //true

避免:

console.log((bar !== null) && (typeof bar === "object"));  // false

2.下面的代码将输出什么到控制台,为什么?

(function(){

var a=b=3;

})();

console.log("a defined? "+(typeof a!=='undefined'));

console.log("b defined? "+(typeof b!=='undefined'));

输出:

a defined?false

b defined?true

原因:

var a = b = 3; 实际是以下声明的简写:

b=3;

var a=b;

在闭包外访问内部变量,正常应该输出undefined。b不是undefined,是因为没有var声明,则b=3,默认定义的是全局变量。

3.封装JavaScript源文件的全部内容到一个函数块有什么意义及理由?

创建一个私有的命名空间,避免不同JavaScript模块和库之间潜在的名称冲突。

4.在JavaScript源文件的开头包含 use strict 有什么意义和好处?

意义:

有利于那些被忽略或默默失败了的代码错误,产生或抛出异常。

严格模式的主要优点:

(1)使调试更加容易。

(2)防止意外的全局变量。

(3)消除 this 强制。如果没有严格模式,引用null或未定义的值到 this 值会自动强制到全局变量。在严格模式下,引用 null或未定义的 this 值会抛出错误。

(4)不允许重复的属性名称或参数值。有利于bug的定位。

(5)使eval() 更安全。

(6)在 delete使用无效时抛出错误。

5.考虑以下两个函数。它们会返回相同的东西吗? 为什么相同或为什么不相同?

function foo1(){  

    return {     

            bar: "hello"  

    };

}

 function foo2(){ 

     return  

    {      

        bar: "hello" 

     };

}

返回不同的东西。

foo1(); //Object{bar:"hello"}

foo2(); //undefined 

原因:

foo2的return语句后面空白,默认会被添加一个分号。导致运行后返回undefined。

6.NaN 是什么?它的类型是什么?你如何可靠地测试一个值是否等于 NaN ?

NaN:not a number

类型:number。typeof NaN,返回number

可靠地测试:

由于NaN !== NaN,可使用value !== value测试。

内置函数(全局函数)isNaN(),或ES6新增的Number.isNaN() 函数。注:后者更可靠。

7.讨论写函数 isInteger(x) 的可能方法,用于确定x是否是整数。

es6提供Number.isInteger() 函数。

es5时代,自行实现:

function isInteger(x) {

    return (x^0) === x; //或 return Math.round(x) === x;

}

function isInteger(x) {

    return (typeof x === 'number') && (x % 1 === 0);

}

8.写一个简单的函数(少于80个字符),要求返回一个布尔值指明字符串是否为回文结构。

function isPalindrome(str) {    

    str = str.replace(/W/g, '').toLowerCase();   

    return (str == str.split('').reverse().join(''));

}

9.请看下面的代码片段:

for (var i = 0; i < 5; i++) {  

    var btn = document.createElement('button');  

    btn.appendChild(document.createTextNode('Button ' + i));      

    btn.addEventListener('click', function(){ console.log(i); });  

    document.body.appendChild(btn);

}

(a)当用户点击“Button 4”的时候会输出什么到控制台,为什么?

(b)提供一个或多个备用的可按预期工作的实现方案。

答案:

(a)输出:5。原因:当 onclick 方法被调用(对于任何按钮)的时候, for 循环已经结束,变量 i 已经获得了5的值。变量i是全局变量,在click事件被触发的时候,执行响应函数function,打印i,则都会打印出5。

(b)

for (var i = 0; i < 5; i++) {  

    var btn = document.createElement('button');  

    btn.appendChild(document.createTextNode('Button ' + i));  

    btn.addEventListener('click', (function(i) {   

         return function() { console.log(i); }; 

     })(i)); 

     document.body.appendChild(btn);

}

for (var i = 0; i < 5; i++) {  

    var btn = document.createElement('button');  

    btn.appendChild(document.createTextNode('Button' + i)); 

     (function (i) {    

        btn.addEventListener('click', function() { console.log(i); });  

    })(i); 

     document.body.appendChild(btn);

}

10.下面的代码将输出什么到控制台,为什么?

var arr1 = "john".split('');

var arr2 = arr1.reverse();

var arr3 = "jones".split('');

arr2.push(arr3);

console.log("array 1: length=" + arr1.length + " last=" + arr1.slice(-1));

console.log("array 2: length=" + arr2.length + " last=" + arr2.slice(-1));

输出:

"array 1: length=5 last=j,o,n,e,s"

"array 2: length=5 last=j,o,n,e,s"

原因:

reverse()操作会改变原数组,并返回改变后的数组。即:var a = [1,2,3]; a.reverse(); console.log(a);//[3,2,1]

同时,数组是引用类型,arr2指向arr1的地址,二者的值完全相同

11.下面的代码将输出什么到控制台,为什么?

console.log(1 +  "2" + "2"); //"122"

console.log(1 +  +"2" + "2"); //"32"

console.log(1 + -"1" + "2"); //"02"

console.log(+"1" +  "1" + "2"); //"112"

console.log( "A" - "B" + "2"); //"NaN2"

console.log( "A" - "B" + 2); //NaN

12.下面的递归代码在数组列表偏大的情况下会导致堆栈溢出。在保留递归模式的基础上,你怎么解决这个问题?

var list = readHugeList(); 

var nextListItem = function() {   

     var item = list.pop();    

     if (item) {        

    // process the list item...       

     nextListItem();   

     }

};

解决:

var list = readHugeList();

    var nextListItem = function() {    

    var item = list.pop();    

    if (item) {       

         // process the list item...        

        setTimeout( nextListItem, 0);    

    }

};

堆栈溢出之所以会被消除,是因为事件循环操纵了递归,而不是调用堆栈。当 nextListItem 运行时,如果 item不为空,timeout函数(nextListItem)就会被推到事件队列,该函数退出,因此就清空调用堆栈。当事件队列运行其timeout事件,且进行到下一个 item 时,定时器被设置为再次调用 nextListItem。因此,该方法从头到尾都没有直接的递归调用,所以无论迭代次数的多少,调用堆栈保持清空的状态。

13.JavaScript中的“闭包”是什么?请举一个例子。

闭包是一个可以访问外部(封闭)函数作用域链中的变量的内部函数。

闭包可以访问三种范围中的变量:

这三个范围具体为:(1)自己范围内的变量,(2)封闭函数范围内的变量(3)全局变量。

例子:

var globalVar = "xyz"; 

(function outerFunc(outerArg) {  

    var outerVar = 'a';   

    (function innerFunc(innerArg) {    

        var innerVar = 'b';    

        console.log(      

            "outerArg = " + outerArg + "n" +     

             "innerArg = " + innerArg + "n" +     

             "outerVar = " + outerVar + "n" +      

            "innerVar = " + innerVar + "n" +     

            "globalVar = " + globalVar);   

    })(456);

})(123);

输出:

outerArg = 123

innerArg = 456

outerVar = a

innerVar = b

globalVar = xyz

14.以下代码行将输出什么到控制台?

console.log("0 || 1 = "+(0 || 1));

console.log("1 || 2 = "+(1 || 2));

console.log("0 && 1 = "+(0 && 1));

console.log("1 && 2 = "+(1 && 2));

输出:

0 || 1 = 1

1 || 2 = 1

0 && 1 = 0

1 && 2 = 2

15.以下代码将输出什么?并解释你的答案。

var a={},   

b={key:'b'},   

c={key:'c'}; 

a[b]=123;

a[c]=456; 

console.log(a[b]);

输出:456

原因:

当设置对象属性时,JavaScript会暗中字符串化参数值。在这种情况下,由于 b 和 c都是对象,因此它们都将被转换为"[object Object]"。结果就是, a[b]和a[c]均相当于a["[object Object]"] ,并可以互换使用。因此,设置或引用 a[c]和设置或引用 a[b]完全相同。

16.创建一个函数,给定页面上的一个DOM元素,就会去访问元素本身及其所有子元素(不只是它的直接子元素)。对于每个被访问的元素,函数应该传递元素到提供的回调函数。

此函数的参数为:

DOM元素

回调函数(将DOM元素作为其参数)

访问树(DOM)的所有元素是经典的深度优先搜索算法应用。下面是一个示范的解决方案:

function Traverse(p_element,p_callback) {   

    p_callback(p_element);  

    var list = p_element.children;  

    for (var i = 0; i < list.length; i++) {       

        Traverse(list[i],p_callback);  // recursive call  

     }

}

相关文章

网友评论

      本文标题:最基本的JavaScript面试题(16个)

      本文链接:https://www.haomeiwen.com/subject/cllnwxtx.html