一些经典的前端面试JavaScript代码分析题(附答案)--第一回合

415 阅读4分钟
  1. 下面代码输出什么?
const firstPromise = new Promise((res, rej) => {
    setTimeout(res, 500, 'one');
});
const secondPromist = new Promise((res, rej) => {
    setTimeout(res, 100, 'two');
});

Promise.race([firstPromise, secondPromise]).then(res => console.log(res));

答案:'two'。
解析:

如果setTimeout(cb, time, param)中有三个参数,那么第三个参数param将被作为cb的实参传递进去。Promise.race只要其中有一个实例率先改变状态,Promise.race的状态就跟着改变。那个率先改变的Promise实例的返回值,就传递给Promise.race的回调函数。


  1. 下面代码输出什么?
let person = { name: 'Jack' };
const members = [person];
person = null;

console.log(members);

答案:[{name:"Lydia"}]
解析:

在JavaScript中对象是引用类型,放在堆内存中。执行完const members = [person]之后members[0]person均指向了同一块堆内存空间。执行person = null只是将person指向堆内存空间的那个链路断开,并不影响members[0]


  1. 下面代码输出什么?
const person = {
    name: 'Jack',
    age: 28
}

for(const item in person) {
    console.log(item);
}

答案:"name","age"
解析:

for...in循环只遍历可枚举属性。像 Array和 Object使用内置构造函数所创建的对象都会继承自Object.prototypeString.prototype的不可枚举属性,例如 StringindexOf()方法或 ObjecttoString()方法是不能够被遍历到的。循环将遍历对象本身的所有可枚举属性,以及对象从其构造函数原型中继承的属性(更接近原型链中对象的属性覆盖原型属性)。该循环不建议用到数组的遍历,因为顺序不能保证且可能访问到数组继承的属性。


  1. 下面代码输出什么?
console.log(3 + 4 + '5');

答案:75
解析:

当所有运算符的 优先级 相同时,计算表达式需要确定运算符的结合顺序,即从右到左还是从左往右。在这个例子中,我们只有一类运算符 +,对于加法来说,结合顺序就是从左到右。
3+4首先计算,得到数字 7。 由于类型的强制转换, 7+'5'的结果是 "75"。JavaScript将 7转换成了字符串。我们可以用+号把两个字符串连接起来。"7"+"5" 就得到了 "75"。


  1. num的值是什么?
const num = parseInt('7*6', 10);

答案:7
解析:

parseInt()会检查字符串中的字符是否合法。一旦遇到一个在指定进制中不合法的字符后,立即停止解析并且忽略后面所有的字符。*就是不合法的数字字符。所以只解析到 "7",并将其解析为十进制的 7。num的值即为7。


  1. 下面代码输出什么?
[1, 2, 3].map(num => {
    if(typeof num === 'number') {
        return;
        return num*2;
    }
})

答案:[undefined, undefined, undefined]
解析:

当函数没有返回值时,则默认返回undefined


  1. 下面代码输出什么?
function setInfo(person, year) {
    person.name = 'Jack';
    year = '1998';
}

const p = { name: 'Tom' };
const birthYear = '1997';

setInfo(p, birthYear);
console.log(p, birthYear);

答案:{ name: 'Jack' }, '1997'
解析:

按值传递,不明白的需要好好读学习学习一下JavaScript基础


  1. 下面代码输出什么?
function greeting() {
    throw 'Hello world'
}

function sayHi() {
    try {
        const data = greeting();
        console.log('It worked!', data);
    } catch(e) {
        console.log('get a error!', e);
    }
}

答案:'get a error! Hello world'
解析:

throw可以抛出自定义异常。异常可以是一个字符串,一个数字,一个布尔类型 或者是一个对象。在本例中,我们的异常是字符串 'Hello world'。


9-1. 下面代码输出什么?

function Car() {
    this.type = 'benchi';
    return {type: 'aodi'}
}
const myCar = new Car()
console.log(myCar.type);

答案:'aodi'

9-2. 下面代码输出什么?

function Car() {
    this.type = 'benchi';
    return 10
}
const myCar = new Car()
console.log(myCar.type);

答案:'benchi'
解析:

JavaScript中函数和new关键词一起使用时一般情况下是作为构造函数。如果作为构造函数时里面有return且返回的是一个对象(非基础类型),那么新的对象实例就等于该返回的对象。其他情况均按照构造函数中的属性给新的对象实例赋值。


  1. 下面代码输出什么?
(() => {
    let x = (y = 10)
})()

console.log(x);
console.log(y);

答案:undefined, 10
解析:

在块级作用域(y = 10)相当于window.y = 10。如果没有括号也是一样的,原理同题4,赋值操作从右边开始。


  1. 下面代码输出什么?
class Dog() {
    constructor(name) {
        this.name = name;
    }
}
Dog.prototype.sayHello = function() {
    console.log(`Hello, I am ${this.name}`);
}

const pet = new Dog('Tom');
pet.sayHello();
delete Dog.prototype.sayHello;
pet.sayHello();

答案:'Hello, I am Tom', TypeError
解析:

可以用 delete关键字删除对象的属性,对原型也是适用


  1. 下面代码输出什么?
const set = new Set([1,1,2,3,4]);
console.log(set);

答案:{1, 2, 3, 4}
解析:

set是一个集合,而不是数组