一道经典面试题

123 阅读1分钟
function Foo() {
    showAlert = function() { alert(1) }
    return this
}
Foo.showAlert = function() { alert(2) }
Foo.prototype.showAlert = function() { alert(3) }
var showAlert = function() { alert(4) }
function showAlert() { alert(5) }

// run
Foo.showAlert()
showAlert()
Foo().showAlert()
showAlert()
new Foo.showAlert()
new Foo().showAlert()
new new Foo().showAlert()

执行

  • var的变量以及function会进行变量提升,此时全局下有函数FooshowAlert => 5
  • Foo添加属性showAlert => 2Fooprototype添加属性showAlert => 3
  • 赋值全局下showAlert => 4,覆盖showAlert => 5

输出

  • Foo.showAlert(): 执行FooshowAlert => 2,输出 2
  • showAlert(): 执行全局下的showAlert(),由于showAlert => 5已经被showAlert => 4覆盖,所以输出 4
  • Foo().showAlert(): 执行Foo函数后调用showAlert(),执行FooshowAlert = function() { alert(1) },由于Foo函数自身没有showAlert,所以找到上级(window),覆盖掉全局的showAlert => 4,变为showAlert => 1Foo()返回的thiswindow,所以调用全局的showAlert,输出 1
  • showAlert(): 再次调用全局下showAlert,此时全局下为showAlert => 1,输出 1
  • new Foo.showAlert()new Foo().showAlert(): 由于成员访问(.)优先级为19new Foo()优先级为19(优先级一样时从左到右),new Foo优先级为18,所以new Foo.showAlert()先执行Foo.showAlert(),得到showAlert => 2,再进行new,输出 2new Foo().showAlert()先执行new Foo(),得到Foo的对象,再通过原型链找到showAlert,最后得到showAlert => 3,输出 3
    查看js运算符优先级
  • new new Foo().showAlert():new一次showAlert => 3,输出 3
  • 最终输出结果为 2 4 1 1 2 3 3
  • 注意: alert(message)message将转换为字符串,所以结果为:'2', '4', '1', '1', '2', '3', '3'