记录一个面试题目
程序员文章站
2023-08-17 23:01:59
判断以下代码的执行结果(涉及变量提升,函数声明,原型链,this指向,作用域等知识点) "掘金" 上看到的一个笔试题目,记录并分析总结以下考察点。 第一个 不用说什么,直接调用Foo构造函数的getName属性,输出2。 第二个 调用当前作用域下的getName函数,要注意 函数表达式 和 函数声明 ......
判断以下代码的执行结果(涉及变量提升,函数声明,原型链,this指向,作用域等知识点)
上看到的一个笔试题目,记录并分析总结以下考察点。
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(); // 2 getname(); // 4 foo().getname(); // 1 getname(); // 1 new foo.getname(); // 2 new foo().getname(); // 3 new new foo().getname(); //3
第一个 不用说什么,直接调用foo构造函数的getname属性,输出2。
第二个 调用当前作用域下的getname函数,要注意函数表达式和函数声明的不同:
- 函数声明会‘被提前’到外部脚本或者外部函数的顶部,所以这种方式声明的函数,可以在它被定义之前的代码中所调用。
- 函数表达式,就和声明变量一样了,变量声明会提前到顶部,但是赋值会在执行到原位置的时候才进行。
4会变量提升,但是并没有赋值,然后5函数提升(在4赋值之前调用下getname(),输出的是5),而代码执行4的位置时,会赋值就覆盖了5。所以第二个会输出4。
第三个 foo()执行时,foo函数体内并没有getname变量,所以就去上一层window下找,重新赋值了window下的getname为输出1(如果没有找到,会在window下创建一个getname),然后返回了this,这里的this指向的是window,再调用window的getname属性,即为重新赋值后的输出1。
第四个 执行当前作用域下的getname,注意此时getname已经重新赋值,所以输出1
第五个 这里需要特别注意表达式的执行顺序,详见 mdn
.
比无参数列表new
执行的优先级高,所以是 new (foo.getname)()
输出2
第六个 同样是执行顺序()
比.
的执行优先级高,所以是 (new foo()).getname()
,foo作为构造函数,指定了返回this,而在构造函数中,this指向的是生成的实例,而foo中没有对实例添加getname属性,所以在调用实例的getname时,会去foo.prototype中找,所以输出3
第七个 同样是执行顺序new ((new foo()).getname)()
是以原型链上的getname为构造函数来执行,输出3