您的位置:首页 > 职场人生

经典的js题库(常见的js面试题以及答案分析)

2019-03-26 10:51 357 查看

1.

function Foo() { getName = function () { alert (1); }; return this; } Foo.getName = function () { alert (2);}; Foo.prototype.getName = function () { alert (3);}; var getName = function () { alert (4);}; function getName() { alert (5);} //请写出以下输出结果: Foo.getName(); getName(); Foo().getName(); getName(); new Foo.getName(); new Foo().getName(); new new Foo().getName(); //答案: Foo.getName();//2 getName();//4 Foo().getName();//1 getName();//1 new Foo.getName();//2 new Foo().getName();//3 new new Foo().getName();//3

// 没有5的原因:

function Foo() { getName = function () { alert (1); }; return this; } var getName;//只提升变量声明 function getName() { alert (5);}//提升函数声明,覆盖var的声明 Foo.getName = function () { alert (2);}; Foo.prototype.getName = function () { alert (3);}; getName = function () { alert (4);};//最终的赋值再次覆盖function getName声明 getName();//最终输出4

//为什么第2个和第4个getName()输出的不一样

Foo函数的第一句  getName = function () { alert (1); };  是一句函数赋值语句,注意它没有var声明,所以先向当前Foo函数作用域内寻找getName变量,没有。再向当前函数作用域上层,即外层作用域内寻找是否含有getName变量,找到了,也就是第二问中的alert(4)函数,将此变量的值赋值为 function(){alert(1)}。

// 优先级 

(.)的优先级高于new操作,

于是 new (Foo.getName)();遂弹出2。

于是(new Foo()).getName();(new Foo())在FoO上没有在原型上找到getName(),遂弹出3

于是new (((new Foo()).getName)());遂弹出3

2.

var arr = [],

arr2 = {};

 

console.log(typeof(arr) === typeof(arr2)); // true

  上方利用typeof比较数组和对象,因为typeof获取NULL、数组、对象的类型都为object,所以console为true。

 

var arr = [],

arr2 = [];

 

console.log(arr === arr2); // false

上方两个相同的数组比较,因为两个单独的数组永不相等,所以console为false。

 

var arr = [];

 

console.log(arr instanceof Object); // true

console.log(arr instanceof Array); // true

上方利用instanceof判断一个变量是否属于某个对象的实例,因为在JavaScript中数组也是对象的一种,所以两个console都为true。

3

var elem = document.getElementsByTagName('div'); // 如果页面上有5个div

 

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

elem[i].onclick = function () {

alert(i); // 总是5

};

}

上方是一个很常见闭包问题,点击任何div弹出的值总是5,因为当你触发点击事件的时候i的值早已是5,可以用下面方式解决:

 

var elem = document.getElementsByTagName('div'); // 如果页面上有5个div

 

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

(function (w) {

elem[w].onclick = function () {

alert(w); // 依次为0,1,2,3,4

};

})(i);

}

在绑定点击事件外部封装一个立即执行函数,并将i传入该函数即可。

4.

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

setTimeout(funcation(){

console.log(i)

},1000)

}

//=> 3次3

原因:定时器是一次执行函数,当执行for循环时候,并没有执行定时器中的闭包函数,当1s之后,触发闭包函数,但是for循环已经执行完毕,i等于3了

for(let i=0;i<3;i++){

setTimeout(funcation(){

console.log(i)

},1000)

}

//=> 0,1,2

原因:for循环使用let定义变量,let是块变量,定时器中的闭包函数通过var是无法传到函数内部的,但是通过let声明的块声明变量,变量的作用域就是这个快

5.

async function async1(){

console.log('async1 start');

await async2();

console.log('async1 end')

}

async function async2(){

console.log('async2')

}

console.log('script start');

setTimeout(function(){

console.log('setTimeout')

},0);

async1();

new Promise(function(resolve){

console.log('promise1');

resolve();

}).then(function(){

console.log('promise2')

});

console.log('script end')

答案:

script start

async1 start

async2

promise1

script end

promise2

async1 end

setTimeout

// async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。 可以理解为,是让出了线程,跳出了async 函数体

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: