下列题目调用后会输出什么?

第一题:

var name = 'window'
var person1 = {
    name: 'person1',
    foo1: function () { //形成作用域
        console.log(this.name)
    },
    foo2: () => console.log(this.name), //外层作用域是window,对象不属于作用域
    foo3: function () {
        return function () { //所调用的是哪个函数,call所指向的this对象会有所不同的答案
            console.log(this.name)
        }
    },
    foo4: function () {
        return () => {
            console.log(this.name) //被函数包裹着形成作用域,要是foo4函数里面没有相关name值,就继续向上一级作用域继续找nane变量,所以是找到person1.name 为止
        }
    }
}
var person2 = { name: 'person2' }

person1.foo1() //person1
person1.foo1.call(person2) //person2

person1.foo2() //window
person1.foo2.call(person2) //window

person1.foo3()() //window
person1.foo3.call(person2)() //window  
person1.foo3().call(person2) //person2 

person1.foo4()()  //person1 
person1.foo4.call(person2)() //person2  指向person2对象 其里面有name变量
person1.foo4().call(person2) //person1  与调用函数位置没有关系,与函数所在位置执行上下文有关系
  1. 普通函数this指向调用当前函数的对象,箭头函数是所在上级普通函数(若父级不是普通函数,一直往上找,到window为止)的调用者。
  2. 箭头函数.call()不会改变this的指向,但是也能成功调用箭头函数

第二题:

var name = 'window'
function Person(name) {
    this.name = name
    this.foo1 = function () {
        console.log(this.name)
    },
        this.foo2 = () => console.log(this.name),
        this.foo3 = function () {
            return function () {
                console.log(this.name)
            }
        },
        this.foo4 = function () {
            return () => {
                console.log(this.name)
            }
        }
}

var person1 = new Person('person1')
var person2 = new Person('person2')

person1.foo1()//person1  .foo1的前面是person1,所以this指向person1对象
person1.foo1.call(person2)//person2  通过call改变this指向成为person2对象

person1.foo2()//person1 箭头函数的this执行上下文
person1.foo2.call(person2)//person1 箭头函数的this不可以直接通过call、bind、apply直接进行修改

person1.foo3()()//window
person1.foo3.call(person2)()//window  person1.foo3.call(person2)虽然执行person2的函数,但是返回的仍是function(){console.log(this.name)} this指向的是window作用域
person1.foo3().call(person2)//person2  最后的函数进行调用的时候通过call改变this指向成为person2对象

person1.foo4()()//person1  箭头函数,执行上下文,向上级作用域查找变量
person1.foo4.call(person2)()//person2  第一个()是函数(非箭头函数)时通过call改变this指向成为person2对象,其有name变量
person1.foo4().call(person2)//person1  箭头函数不能直接通过call改变this指向

第三题:

var name = 'window'
function Person(name) {
    this.name = name
    this.obj = {
        name: 'obj',
        foo1: function () {
            return function () {
                console.log(this.name)
            }
        },
        foo2: function () {
            return () => {
                console.log(this.name)
            }
        }
    }
}
var person1 = new Person('person1')
var person2 = new Person('person2')

person1.obj.foo1()()// window  
person1.obj.foo1.call(person2)() //window 第一个()函数调用通过call改变this指向成为person2对象,但返回 function(){console.log(this.name)} 其this指向还是window
person1.obj.foo1().call(person2) //person2  第二个()函数(非箭头函数)的this通过call改变成为person2对象

person1.obj.foo2()()//obj 箭头函数,执行上下文,向上级作用域进行查找
person1.obj.foo2.call(person2)()// person2  第一个()函数(非箭头函数)通过call改变this指向成为person2对象,其里面箭头函数的上级作用域就是person2
person1.obj.foo2().call(person2)//obj 第二个()箭头函数执行,不能直接通过call来改变this指向,其箭头函数执行上下文向上级作用域进行查找

第四题:

function foo() {
  console.log(this.a)
}
var a = 2;
(function() {
  'use strict';
  foo();
})()

/* 
运行结果:输出 2
备注:var a = 2 改为 let a = 2,输出为 undefined
*/

第五题: