今天刚作完网易校招的前端笔试题,整体难度不算很难,有送分题也有拉分题,不过大公司的笔试算法题占比最大,整套笔试题的题型与分值分布分别是:单选题40分共20题、编程题60分共3题、问答题20分共2题,是牛客网的笔试。前端
遇到一道比较坑的单选题,在此记录一下。算法
如下代码执行时console.log的结果是:编程
1 var obj = { 2 x: 1, 3 xyz: function () { 4 with(this) { 5 function con () { 6 console.log(x); 7 console.log(this.x); 8 } 9 var x = 2; 10 (function() { 11 con() 12 })() 13 con.call(this) 14 } 15 } 16 } 17 18 obj.xyz()
执行结果:app
要理解这道题就必须搞懂每个this指向的是什么,因此咱们能够把对应的各个this打印出来分析一波函数
1 var obj = { 2 x: 1, 3 xyz: function () { 4 console.log('1', this) 5 with(this) { 6 function con () { 7 console.log('2', this) 8 console.log(x); 9 console.log(this.x); 10 } 11 var x = 2; 12 console.log('3', this); 13 (function() { 14 con() 15 })() 16 con.call(this) 17 } 18 } 19 } 20 21 obj.xyz()
执行结果以下:this
从执行顺序分析,1号this打印出来的是obj对象,也就是说with传进去的是obj对象,在with代码块里,首先声明了con函数,而后再执行了var x=2;这一段代码,而with修改了词法做用域,把with代码块里的上下文改成obj对象,那么这段代码等同于obj.x = 2,即把obj对象里的x属性修改成2,接着打印了3号this,值为obj对象,验证了with代码块的上下文是obj对象。接着执行了一个当即执行函数,函数里调用了con函数。在《你不知道的JavaScript上卷》第2章里有提到函数里this的绑定取决于函数的调用方式,而于函数声明的位置无关,this的绑定规则有四个:默认绑定(独立函数调用)、隐式绑定(obj.foo())、显示绑定(call()和apply())和new绑定。显然,当即执行函数里直接调用con函数,属于默认绑定,默认绑定this会指向全局对象(window或global),因此第9行console.log(this.x)打印的是window.x,而全局对象window中并无定义x,所以打印出undefined,而第8行console.log(x)打印的是当前词法做用域里的x,即为obj.x,打印出2。接着分析第16行代码con.call(this)至关于con.call(obj),显然,使用call()方法调用con函数,显示绑定this指向obj,因此第9行console.log(this.x)打印的是obj.x,即为2,而后第8行同理打印的是当前词法做用域里的x。如此分析一波,这道题的答案就很清晰明了了。spa