JavaScript中this指向问题

一、this的默认指向问题

简单的概括:

this指向谁,取决于它的直接调用者,调用者是谁就是谁。

没有调用者,this指向 全局 ,浏览器中是 window

箭头函数的this, 取决于他外面第一个不是箭头函数的this。 this一旦绑定了上下文,不会被改变。

function test() {
  return () => {
    return () => {
      console.log(this)
    }
  }
}

console.log(test()()()) // window

二、this 存在的深层次分析

this指向谁是在运行中决定的,this其实是一个当前函数记录当前所属环境对象的一个指针,可以理解为一个上下文变量,this指向的对象,包含了可以访问的属性和变量,相当于作用域的作用。

三、更改this指向的方法

  1. 方法有

call, apply, bind

  1. call和apply区别

func.apply(<运行中的this>, [argsArray])

function.call(<运行在的this>, arg1, arg2, ...)

call()方法的作用和 apply() 方法类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组。

  1. bind

bind方法和call很相似,第一参数也是this的指向,后面传入的也是一个参数列表(但是这个参数列表可以分多次传入,call则必须一次性传入所有参数),但是它改变this指向后不会立即执行,而是返回一个永久改变this指向的函数。

var arr=[1,10,5,8,12];
var max=Math.max.bind(null,arr[0],arr[1],arr[2],arr[3])
console.log(max(arr[4])); //12,分两次传参

参考:

四、手写模拟 apply/call/bind

模拟call

 Function.prototype.myCall=function(context=window,...args){
            console.log('----mycall this')
            console.log(this) // 会输出为 f
            console.log('---------')

            // this,就是未来的函数f,比如他会调用  f.myCall(window, 其他参数),这里this就是f
            // 相当于换了一个调用对象,帮他调用
            context.f = this;
            const res = context.f(...args);
            delete context.f;
            return res
}


function f(num){
    console.log(this, num)
}
var obj={
    a:1
}
f.call(obj,10);
f.myCall(obj,10);
console.log(obj)

模拟 apply

Function.prototype.myApply=function(context=window,args){
        context.f = this;
        const res = context.f(...args);
        delete context.f;
        return res
    }
function f(num){
    console.log(this,num)
}
let obj={
    a:1
}
f.apply(obj,[10]);
f.myApply(obj,[10]);
console.log(obj)

模拟bind

    Function.prototype.myBind=function(context=window, ...outerArgs){
        const _this = this; // _this就是 f
        console.log('position 1',_this)
        return function(...innerArgs){
            console.log('position 2',this)
            _this.call(context,...outerArgs.concat(innerArgs))
        }
    }
    let obj = {a:1}
    function f(number){
        console.log(this,number)
    }
 
    f1 = f.bind(obj,10);
    f2 = f.myBind(obj,10);
    f1();
    f2();

参考

Mark24

Everything can Mix.