this的指向有以下几条规律
- 在函数体中,非或隐式地简单调用函数时,在严格模式下,函数内的this会被绑定到undefined上,在非严格模式下则会被绑定到全局对象window/global上。
- 一般使用new方法调用构造函数时,构造函数内的this会被绑定到新创建的对象上。
- 一般通过call/apply/bink方法显式调用函数时,函数体内的this会被绑定到指定参数的对象上。
- 一般通过上下文对象调用函数时,函数体内的this会被绑定到该对象上。
- 在箭头函数中,this的指向是由外层(函数或全局)作用域来决定的。
一、全局环境中的this
function f1(){
console.log(this);
}
function f2(){
'use strict'
console.log(this);
}
f1() //window
f2() //undefined
上面的比较基础,函数在全局环境中被简单调用,在非严格模式下this指向window,在通过 use strict 指明严格模式的情况下指向undefined。但是要注意它的变种
const foo = {
bar:10,
fn:function(){
console.log(this);
console.log(this.bar);
}
}
var fn3 = foo.fn
fn3() //window,undefined
//还是上面这题:如果将调用改为下面这种形式
foo.fn() //{bar: 10, fn: ƒ} 10
二、上下文对象调用中的this
const student ={
name:'Mike',
fn:function(){
return this
}
}
console.log(student.fn() === student); //true
当存在更复杂的调用关系时,如以下代码中的嵌套关系,this会指向最后调用它的对象,因此输出将会是Mike
const person = {
name:'Lucas',
brother:{
name:'Mike',
fn:function(){
return this.name
}
}
}
console.log(person.brother.fn()); //Mike
上面介绍的都是this的上下文对象调用,下面看一道更高阶的
const o1 = {
text:'o1',
fn:function(){
return this.text
}
}
const o2 = {
text:'o2',
fn:function(){
return o1.fn()
}
}
const o3 ={
text:'o3',
fn:function(){
var fn = o1.fn
return fn()
}
}
console.log(o1.fn()); //o1
console.log(o2.fn()); //o1
console.log(o3.fn()); //undefined
答案是o1、o1、undefined。
- 第一个console最简单,输出o1不难理解,难点在第二个和第三个console上,关键还是看调用this的那个函数。
- 第二个console中的o2.fn()最终调用的还是o1.fn(),因此运行结果仍然是o1。
- 最后一个console中的o3.fn()通过var fn = o1.fn的赋值进行了‘裸奔’调用,因此这里的this指向window。运行结果就是undefined。
如果再深入一些,想让console.log(o2.fn())语句输出o2。该怎么办? 有两个思路:1. 用call/apply/bind来改变this指向。2. 把o2.fn = o1.fn
console.log(o1.fn.call(o2));
console.log(o1.fn.apply(o2));
console.log(o1.fn.bind(o2)());
如果不使用call/apply/bind应该怎么做? ****** this指向最后调用它的对象 *******
const o1 = {
text:'o1',
fn:function(){
return this.text
}
}
const o2 = {
text:'o2',
fn:o1.fn
}
console.log(o2.fn());
构造函数和this
function Foo(){
this.user = 'Lucas'
const o = {}
return o
}
const foo = new Foo()
console.log(foo.user); //undefined
function Bar(){
this.user = 'Lucas'
const o = {}
return 1
}
const bar = new Bar()
console.log(bar.user); //Lucas
这是因为如果构造函数返回一个值,且返回的是一个对象(复杂对象),那么this就指向这个对象。如果返回的不是一个对象(基本类型),那么this仍然指向实例。
箭头函数中的this
var a = 123;
// const a = 123;
const foo = ()=> a=>{
console.log(this.a);
}
const obj1 = {
a:2
}
const obj2 = {
a:3
}
const bar = foo.call(obj1) //123 const a = 123,则这里打印undefined,原因是const声明的变量不会挂载到window对象上。因此this指向window时,自然就找不到a变量了。
console.log(bar.call(obj2)); //undefined
const a = 123,则这里打印undefined,原因是const声明的变量不会挂载到window对象上。因此this指向window时,自然就找不到a变量了。