this指向的问题
this是js中的一个关键字,它是在函数运行时,自动生成的一个内部对象,根据不同的函数使用场合或者说是在不同的函数代码块中,它的值是不同的
一、普通函数:
1、this在全局环境中,无论是否是严格模式,this就代表全局对象window。
'use strict'
console.log(this === window); // true
2、在非箭头函数下, this 指向调用其所在函数的对象,由谁调用指向谁
作为普通函数调用,这时函数属于全局性调用,因此this就代表全局对象window。
作为对象方法的调用,这时this就指这个当前对象。
test();
function test() {
console.log(this); // window
console.log(this === window); // true
}
注:如果函数作用域中使用严格模式,this不会指向window
test();
function test() {
'use strict'
console.log(this); //undefined
console.log(this === window); // false
}
3、在构造函数中,this指向新的实例对象
4、自执行函数、定时器中,this默认指向window
var obj = {
say: function () {
setTimeout(function () {
console.log(this); //window
});
}
}
obj.say();
二、箭头函数
箭头函数的this是继承而来; 默认指向在定义时所处的对象。在定义的时候就决定了指向。
(PS:函数内层的this就是外层代码块的this)
// 箭头函数中的this指向上一层的代码块的this
function foo() {
setTimeout(() => {
console.log('id:', this.id);
}, 100);
}
var obj = {
id:1,
foo:foo
}
var id = 21;
foo(); //由window调用, 21
obj.foo(); //由obj调用 1
在箭头函数中,this的指向是固定的。
下面这个这个例子来自阮一峰的《ECMAScript6入门》:
function Timer() {
this.s1 = 0;
this.s2 = 0;
// 箭头函数
setInterval(() => this.s1++, 1000);
// 普通函数
setInterval(function () {
this.s2++;
}, 1000);
}
var timer = new Timer();
setTimeout(() => console.log('s1: ', timer.s1), 3100);
setTimeout(() => console.log('s2: ', timer.s2), 3100);
// s1: 3
// s2: 0
time函数内部设置了两个定时器,分别使用了箭头函数和普通函数。前者的this绑定定义时所在的作用域(即Timer函数),后者的this指向运行时所在的作用域(即全局对象)。所以,3100 毫秒之后,timer.s1被更新了 3 次,而timer.s2一次都没更新。
有个比较容易误解的地方,如下:
var obj = {
a:1,
m:{
b:2,
fn:function(){
console.log(this);
},
fn1:()=>{
console.log(this);
},
fn2:function(){
var a = ()=>{
console.log(this);
}
a();
}
}
}
obj.m.fn(); //obj
obj.m.fn1(); //window
obj.m.fn2(); //obj
obj.m.fn1()对应输出是window的,我的理解是作用域分为全局和函数作用域,fn1不在函数作用域中,是在全局中(PS:如果这么理解不准确,或者有更好的解释麻烦我说下哦^_^)。
apply 、 call 、bind函数
apply 、call 、bind 三者都是用来改变函数的this对象的指向的;
第一个参数都是this要指向的新的对象,也就是想指定的上下文;
第二个参数开始,就是函数的本身的参数;
区别:bind 是返回对应函数,返回新函数,便于稍后调用,不会马上调用;
apply 、call 则是立即调用 。