每日 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】