【基础强化】从例子中深入理解this

164 阅读2分钟

1,首先理解严格和非严格模式下的全局this

function f1() { console.log(this)}
function f2() { 'use strict' console.log(this)}
f1()  // window
f2()  // undefined
/** 
* 这里因为将foo.fn赋值给f3之后,f3是在全局环境中执行
*/
const foo = {
    bar: '10',
    fn: function() {
        console.log(this)
        console.log(this.bar)
    }
}
var f3 = foo.fn
f3()  // window  undefined
/*,
* 如果直接调用的话,此时 this指向最后调用它的对象foo
*/
foo.fn()  // { bar: 10, fn: f}  10

2 this 的上下文调用

const o1 = {
    text: 'o1',
    fn: function() {
        return this.text
    }
}
const o2 = {
    text: 'o2',
    fn: function() {
        var fn = o1.fn
        return fn()
    }
}
console.log(o2.fn())  // undefined
/*
*  o1.fn进行赋值之后调用,此时 this指向window
*/

3, 构造函数 和this

function foo() {
    this.user = 'mike';
    const o = {}
    return o
}
const ins = new foo();
console.log(ins.user) // undefined
function foo1() {
    this.user = 'mike';
    return 1;
}
const ins1 = new foo1();
console.log(ins1.user)  // mike
/* 如果构造函数中显示的返回一个值,且返回的是一个对象(复杂类型),this指向这个返回的对象;
如果返回的不是对象(基本类型),this指向实例
*/

4,箭头函数,this指向由外层作用域决定

// 如果将箭头函数换成一个匿名函数,this在匿名函数中,指向window
const foo = {
    fn: function() {
        setTimeout(() => {
            console.log(this)
        })
    }
}
console.log(foo.fn())   // {fn:f}


var a = 123
const foo = () => a => console.log(this)
const obj1 = { a: 2}
const obj2 = { a: 3}
var bar = foo.call(obj1)
console.log(bar.call(obj2))  // 123
/* 由于箭头函数的this绑定无法修改,所以call无法修改,绑定在window下
这里如果把 var变量声明换成const ,将会输出 undefined;因为const声明的变量不会挂载在window上
*/

5,优先级

new 绑定 > 显示bind绑定(call, apply)> 根据调用关系的隐式绑定

6, 总结规律

  • 在函数体中,非显式或隐式地简单调用函数时,严格模式下,函数内的this会绑定到undefined上,非严格模式下会被绑定到全局对象window / global上;
  • 一般用new方法构造函数时,构造函数内的this会被绑定到新创建的对象上;
  • 一般通过call/ apply / bind方法显式调用函数时,函数体内的this会被绑定到指定参数的对象上;
  • 一般通过上下文对象调用函数时,函数体内的this会被绑定到该对象上
  • 箭头函数中,this的指向由外层(函数/全局)作用域来决定