Javascript基础-理解this

85 阅读2分钟

this关键字是 JavaScript 中最复杂的机制之一,被自动定义在所有函数的作用域中。this是javascript中最难理解的一个知识点,甚至对一部分开发人员来说this完全就是一种魔法。

一、为什么需要this

可以在不同的上下文对象中重复使用函数,而不用针对每个对象编写不同的函数。

function identify() { 
    return this.name.toUpperCase(); 
} 
function speak() { 
    var greeting = "Hello, I'm " + identify.call( this ); 
    console.log( greeting ); 
} 
var me = { name: "Kyle" }; 
var you = { name: "Reader" }; 
identify.call( me ); // KYLE 
identify.call( you ); // READER 
speak.call( me ); // Hello, 我是 KYLE 
speak.call( you ); // Hello, 我是 READER
二、this的误解:
  • 指向自身,人们很容易把 this 理解成指向函数自身;
  • 指向函数作用域
三、this绑定时机

this 是在运行时进行绑定的,并不是在编写时绑定,this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。

在理解 this 的绑定过程之前,首先要理解调用位置,你必须找到调用位置,然后判断需要应用下面四条规则中的哪一条。

四、绑定规则:
  • 默认绑定,函数调用类型:独立函数调用。默认绑定到全局对象,如果使用严格模式(strict mode),那么全局对象将无法使用默认绑定,因此 this 会绑定 到 undefined:

  • 隐式绑定:调用位置是否有上下文对象,或者说是否被某个对象拥有或者包 含

  • 显式绑定:call(...),apply(...)

  • new绑定:var a = new String('hello')

五、判断this顺序:
  • 函数是否在 new 中调用(new 绑定)?如果是的话 this 绑定的是新创建的对象。
  • 函数是否通过 call、apply(显式绑定)或者硬绑定调用?如果是的话,this 绑定的是 指定的对象。
  • 函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this 绑定的是那个上 下文对象。
  • 如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到 undefined,否则绑定到 全局对象。
六、总结

把 null 或者 undefined 作为 this 的绑定对象传入 call、apply 或者 bind,这些值 在调用时会被忽略,实际应用的是默认绑定规则:

ES6 中的箭头函数并不会使用四条标准的绑定规则,而是根据当前的词法作用域来决定 this,具体来说,箭头函数会继承外层函数调用的 this 绑定

如果函数并不关心 this 的话,你 仍然需要传入一个占位值,这时 null 可能是一个不错的选择,然而,总是使用 null 来忽略 this 绑定可能产生一些副作用。一种“更安全”的做法是传入一个特殊的对象,我们可以创建一个“DMZ”,JavaScript 中创建一个空对象最简单的方法都是 Object.create(null)