网络日志

前端面试题每日3题——2022-08-31

每日 3 题

1 以下代码执行后,控制台中的输出内容为?

var foo = function bar() {
  return 123;
};

console.log(typeof foo);
console.log(typeof foo());
console.log(typeof bar());

2 以下代码执行后,控制台中的输出内容为?

var obj = {
  a: 1,
  foo: function () {
    return this.a;
  },
};
var fun = obj.foo;
console.log(obj.foo());
console.log(fun());

3 以下代码执行后,控制台中的输出内容为?

function A(x) {
  this.x = x;
}

function B(x) {
  this.x = x;
}

A.prototype.x = 1;
B.prototype = new A();
var a = new A(2);
var b = new B(3);
delete b.x;

console.log(a.x);
console.log(b.x);

解析

1、答案:function number 报错

解析:

  1. 这是一个命名函数表达式,被函数表达式赋值的变量类型为function,故typeof foo 为 function
  2. foo 调用后返回 123,故类型为 number
  3. 有关命名函数表达式,MDN 文档中是这么描述的:
命名函数表达式(Named function expression)如果你想在函数体内部引用当前函数,则需要创建一个命名函数表达式。然后函数名称将会(且只会)作为函数体(作用域内)的本地变量

命名函数表达式的函数名只在其函数体内有效

所以在外部调用 bar() 会报错

2、答案:1 undefined

  1. 直接调用 obj.foo() 时,它的前面加上了对 obj 的引用。当函数引用有上下文对象是,隐式绑定规则会把函数调用中的 this 绑定到这个上下文对象。因为调用 obj.foo() 时 this 被绑定到 obj,因此 this.a 和 obj.a 是一样的,所以结果为 1
  2. 虽然 fun 是 obj.foo 的一个引用,但是它引用的是 foot 函数本身,因此 fun() 实际上是一个不带任何修饰的函数调用,此时应用默认绑定规则,即 this 指向全局对象。而全局对象不存在属性 a,故输出 undefined

3、答案:2 undefined

考察原型链

  1. JS 中每个函数都有一个 prototype 属性,指向一个对象(称为原型对象)
  2. 每个对象都有一个__proto__属性,指向该对象的构造函数的原型对象
  3. 原型对象也有__proto__属性,于是一个对象可以沿着__proto__层层向上,直到一个对象的原型对象为 null,null 没有原型,即为原型链的终点
  4. 访问对象的属性时,如果对象不存在该属性,则会沿着原型链向上寻找该属性,直到到达原型链的终点

回到题目:

  1. a.x,对象 a 上存在属性 x 为2,所以输出 2
  2. b.x,对象 b 上的属性 x 被 delete,所以向上寻找,首先查看 b.__proto__,即 B.prototype,为 new A(),因为没传入 x,所以 x 为 undefined,找到属性 x,最终返回 undefined

    公众号【今天也要写bug】