# 代码输出值(this/自调用/闭包)

在群里看到了一个挺有意思的面试题,第一感觉是:又是哪来的SB面试官

结果还是低头面对现实吧,指不定哪天面试遇到了,做不出来就尴尬了

var x = 2;
var y = {
    x: 3,
    z: (function(x){
        this.x *= x;
        x += 2;
        return function(n){
            this.x *= n;
            x += 3;
            console.log(x)
        }
    })(x)
}
var m = y.z
m(4)
y.z(5)
console.log(x, y.x)
// 7
// 10
// 16 15

下面来分析一下过程:

# 分析一

一开始,在定义 对象y 的时候,y对象的属性z的值是一个自执行函数,参数为window.x

  1. 自调用函数的 this 指向 window
  2. 执行第一步,此时全局的 x = 4
  3. 传入的参数+2,参数 x = 4
  4. 最后返回函数,形成了闭包,也就是外部的 x += 2,最终是 x = 4
var x = 2;
(function(x){
    this.x *= x;    // 第一步
    x += 2;         // 第二步
    return function(n){
        this.x *= n;
        x += 3;
        console.log(x)
    }
})(x)

# 分析二

先是把 y.z 赋值给 m,再调用函数 m(4),所以这里的 this 指向 window,this永远指向调用的最后一个对象

  1. 第一步的x为window.x,经由分析一得出 window.x = 4 * 4 = 16
  2. 由分析一得出这里是一个闭包,闭包存在 x = 4,所以这里的 x += 3 等于 x = 4 + 3 = 7
var x = 2;

z: (function(x){
    this.x *= x;
    x += 2;
    return function(n){
        this.x *= n;    // 第一步
        x += 3;         // 第二步
        console.log(x)
    }
})(x)

var m = y.z
m(4)  // 7

# 分析三

很明显,这里的 this 指向就是 y对象 了,所以,这里的 this.x *= n 等于 y.x *= n 等于 y.x = 15

接着第二步还是闭包,由分析二得出的,闭包 x = 7,所以 x= 3+7 = 10

var x = 2;
var y = {
    x: 3,
    z: (function(x){
        this.x *= x;
        x += 2;
        return function(n){
            this.x *= n;    // 第一步
            x += 3;         // 第二步
            console.log(x)
        }
    })(x)
}
y.z(5)                  // 10
console.log(x, y.x)     // 16 15