一、常规函数中this
this是使用常规方法调用函数时(call)传递的第一个参数,它可以在函数调用时修改,在函数没有调用的时候,this的值是无法确定的。
1. 纯粹的函数调用
常见写法(简写):
function test(name) {
console.log(name)
console.log(this)
}
test('Jerry') //调用函数
完整写法:
function test(name) {
console.log(name)
console.log(this)
}
test.call(undefined, 'Tom')
如果你传的context 是 null 或者 undefined,那么 window 对象就是默认的 context(严格模式下默认 context 是 undefined)
2. 对象中函数的调用
默认this
const obj = {
name: 'Jerry',
greet: function() {
console.log(this.name)
}
}
obj.greet() //第一种调用方法(语法糖)
obj.greet.call(obj) //第二种调用方法
手动指定this
const obj = {
name: 'Jerry',
greet: function() {
console.log(this.name)
}
}
obj.greet.call({name: 'Spike'}) // Spike
3. 构造函数中this
构造函数里的this稍微有点特殊,每个构造函数在new之后都会返回一个对象,这个对象就是this,也就是context上下文。
function Test() {
this.name = 'Tom'
}
let p = new Test()
console.log(typeof p) // object
console.log(p.name) // Tom
new关键字会创建一个空的对象,将this指向这个空对象,这样的话函数内部的this就会被这个空的对象替代。
当this碰到return时
function fn()
{
this.user = 'Jerry';
return {}; // undefined
return function(){}; // undefined
return 1; // Jerry
return undefined; // Jerry
}
var a = new fn;
console.log(a.user);
如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。
function fn()
{
this.user = 'Jerry';
return null;
}
var a = new fn;
console.log(a); // fn {user: "Jerry"}
虽然null也是对象,但是在这里this还是指向那个函数的实例,因为null比较特殊。
4. window.setTimeout()和window.setInterval()中函数的调用
window.setTimeout()和window.setInterval()的函数中的this有些特殊,里面的this默认是window对象。
二、箭头函数中的this
MDN官方文档:箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this。
1. 箭头函数的特性一:继承上层this
不使用箭头函数
const obj = {
a: function() { console.log(this) }
}
obj.a() // {a: ƒ} obj对象
使用箭头函数
const obj = {
a: () => {
console.log(this)
}
}
obj.a() // window
2. 箭头函数的特性二:不能用call方法修改里面的this
例子
const obj = {
a: () => {
console.log(this)
}
}
obj.a.call('123') // window
结合window.setTimeout()
const obj = {
a: function() {
console.log(this)
window.setTimeout(() => {
console.log(this)
}, 1000)
}
}
obj.a.call(obj) //第一个this是obj对象,第二个this还是obj对象
三、多层对象嵌套里函数的this
例子1
const obj = {
a: function() { console.log(this) },
b: {
c: function() {console.log(this)}
}
}
obj.a() // obj对象, 相当于obj.a.call(obj)
obj.b.c() // obj.b对象, 相当于obj.b.c.call(obj.b)
例子2
const obj = {
a: function() { console.log(this) },
b: {
c: () => {console.log(this)}
}
}
obj.a() // obj对象
obj.b.c() // window!!
window对象就是它的上一层this,此例中的多层嵌套只是对象嵌套,这时候没有作用域链的嵌套,实际上对箭头函数来说,还是只有自己一级的作用域,和上一层的window作用域
例子3
function fn0() {
return {
fn1: function () {
var obj = {
a: function() { console.log(this) },
b: {
c: () => console.log(this)
}
}
return obj;
}
}
}
fn0().fn1().b.c() // 得到{fn1: f} fn1对象
在ES5中,只有全局作用域和函数作用域,并没有块级作用域,所以这里箭头函数仍然绑定外层this值,而非根作用域