this 的指向
不管是什么场合,this
都有一个共同点:它总是返回一个对象。javascript 的 this 不是在函数定义的时候确定的,而是在调用的时候确定的,指向调用者。
const A = {
name: '张三',
describe: function () {
return '姓名:'+ this.name;
}
};
const name = '李四';
const f = A.describe;
f() // "姓名:李四" - 相当于 window 调用了

1. 方法调用
通过对象来调用其方法函数 对象.方法函数(...)
,函数中的 this
指向调用该方法的对象。
const obj = {
// 第一种方式,定义对象的时候定义其方法
test() {
console.log(this === obj);
}
};
// 第二种方式,对象定义好之后为其附加一个方法(函数表达式)
obj.test2 = function() {
console.log(this === obj);
};
// 第三种方式和第二种方式原理相同,是对象定义好之后为其附加一个方法(函数定义)
function t() {
console.log(this === obj);
}
obj.test3 = t;
// 这也是为对象附加一个方法函数,但是这个函数绑定了一个不是 obj 的其它对象
obj.test4 = (function() {
console.log(this === obj);
}).bind({});
obj.test(); // true
obj.test2(); // true
obj.test3(); // true
obj.test4(); // false -受 bind() 影响,test4 中的 this 指向不是 obj
2. new 实例调用
在 es5 中,用 new
调用一个构造函数会创建一个新对象,而其中的 this
就指向这个新对象。
var data = "Hi"; // 全局变量
function AClass(data) {
this.data = data;
}
var a = new AClass("Hello World");
console.log(a.data); // Hello World
console.log(data); // Hi
var b = new AClass("Hello World");
console.log(a === b); // false
但是构造函数如果有 return 语句,且 return 语句是个对象,则 new 出来的新对象是指 return 的这个对象,如果 return 的是非对象数据类型,则 this 依旧指向 new 的新对象。
// 1
function fn(){
this.user = '追梦子';
return {};
}
var a = new fn;
console.log(a.user); //undefined
// 2
function fn(){
this.user = '追梦子';
return function(){};
}
var a = new fn;
console.log(a.user); //undefined
// 3
function fn(){
this.user = '追梦子';
return 1;
}
var a = new fn;
console.log(a.user); //追梦子
3. call/bind/apply 绑定
3.1 call()
函数实例的 call
方法,可以指定函数内部 this
的指向(即函数执行时所在的作用域),然后在所指定的作用域中,调用该函数。call
方法的参数,应该是一个对象。如果参数为空、null
和 undefined
,则默认传入全局对象。
// func.call(thisValue, arg1, arg2, ...)
// 第一个参数就是this所要指向的那个对象
var n = 123;
var obj = { n: 456 };
function a() {
console.log(this.n);
}
a.call() // 123
a.call(null) // 123
a.call(undefined) // 123
a.call(window) // 123
a.call(obj) // 456
3.2 apply()
apply
方法的作用与 call
方法类似,也是改变 this
指向,然后再调用该函数。唯一的区别就是,它接收一个数组作为函数执行时的参数。
// 1、找出数组最大元素
var a = [10, 2, 4, 15, 9];
Math.max.apply(null,a) // 15
// 2、将数组的空元素变为undefined,空与undefined的区别在于遍历时空会被跳过
Array.apply(null, ['a', ,'b']) // [ 'a', undefined, 'b' ]
// 3、转换类似数组的对象,比如arguments对象
Array.prototype.slice.apply({0: 1, length: 1}) // [1]
Array.prototype.slice.apply({0: 1}) // []
Array.prototype.slice.apply({0: 1, length: 2}) // [1, undefined]
Array.prototype.slice.apply({length: 1}) // [undefined]
// 4、绑定回调函数的对象
var o = new Object();
o.f = function () {
console.log(this === o);
}
var f = function (){
o.f.apply(o); // 或者 o.f.call(o);
};
$('#button').on('click', f);
3.3 bind()
bind
方法用于将函数体内的 this
绑定到某个对象,然后返回一个新函数。
var counter = {
count: 0,
inc: function () {
this.count++;
}
};
var func = counter.inc.bind(counter);
func();
counter.count // 1
3.4 总结
bind
返回一个函数
this指向改变后的对象
直接传递
apply
函数直接调用
this指向改变后的对象
用数组包裹参数
call
函数直接调用
this指向改变后的对象
直接传递
如果第一个参数为null或undefined,this 的指向就是全局变量,在浏览器里就是window对象。
不管我们给函数 bind 几次,fn 中的 this 永远由第一次 bind 决定。
4. 箭头函数中的 this
箭头函数中使用的 this
,其实是直接包含它的那个函数或函数表达式中的 this
。函数体内的this
对象,是定义时所在的对象,而不是使用时所在的对象。或者可以说 箭头函数没有 this。
const obj = {
test() {
const arrow = () => {
// 这里的 this 是 test() 中的 this,
// 由 test() 的调用方式决定
console.log(this === obj);
};
arrow();
},
getArrow() {
return () => {
// 这里的 this 是 getArrow() 中的 this,
// 由 getArrow() 的调用方式决定
console.log(this === obj);
};
}
};
obj.test(); // true
const arrow = obj.getArrow();
arrow(); // true
5. 总结
this 代表函数调用相关联的对象,通常页称之为执行上下文。
作为函数直接调用,非严格模式下,this指向window,严格模式下,this指向undefined
作为某对象的方法调用,this通常指向调用的对象
使用apply、call、bind 可以绑定this的指向
在构造函数中,new 调用时指的是被构造的对象
箭头函数没有单独的this值,this在箭头函数创建时确定,它与声明所在的上下文相同
简单来说就是:
普通函数的this ==> 谁调用就是谁(经常变:谁调用是谁)
箭头函数的this ==> 在谁的环境下
this
就是谁(不变:当前作用域),例如常见document/window等
最后更新于
这有帮助吗?