this首先我们分析一下下面代码的执行结果function foo(num) { console.log( “foo: " + num ); this.count++; //记录函数执行次数}foo.count = 0;function test(){ for(let i = 0 ; i < 4; i++){ foo(i) } console.log(‘foo执行次数:’+foo.count)}test()执行结果如下:foo: 0foo: 1foo: 2foo: 3foo执行次数:0由此可见this指向的并不是函数自身。this 是在运行时进行绑定的,它的指向取决于它的调用位置。我们可以通过分析调用栈来找到函数的调用位置。(调用位置为当前正在执行的函数的前一个调用中)。当我们在第一个例子中增加debugger,在浏览器工具中可以清晰的看到函数的调用栈:foo函数的调用位置在test函数中,此时this的指向默认绑定为window,而不是foo对象。我们可以可以通过修改this.count为foo.count来达到目的。绑定this的绑定规则有:默认绑定、隐式绑定、显式绑定、new绑定,上面函数调用中this就是默认绑定。new绑定function foo(a) { this.a = a;} var bar = new foo(2);console.log(bar.a); //2var bar2 = new foo(3);console.log(bar2.a) //3当使用new调用foo函数时,会构造一个新对象并把它绑定到 foo显式绑定我们可以通过call、bind、apply来改变this的指向。call、apply本质上没有区别,都是立即执行,只是第二个参数的传值方式不一样。bind返回要执行的函数,需要的时候再执行。(bind后的函数当使用new执行时,绑定无效)function foo() { console.log(this.a);}var obj = { a:2};var fn = foo.bind( obj );fn() //2new fn() //undefined隐式绑定当函数存在上下文对象时会影响调用位置function foo() { console.log( this.a );}var obj2 = { a: 42, foo: foo };var obj1 = { a: 2, obj2: obj2 };obj1.obj2.foo(); //42箭头函数箭头函数会继承外层函数调用的 this 绑定