JavaScript中的this

210 阅读2分钟

在绝大多数情况下,函数的调用方式决定了this的值。this不能在执行期间被赋值,并且在每次函数被调用时this的值也可能会不同。ES5引入了bind方法来设置函数的this值,而不用考虑函数如何被调用的,ES2015 引入了支持this词法解析的箭头函数(它在闭合的执行环境内设置this的值)。

分析每种函数调用方式的this指向

  1. 很显然当函数在全局环境中定义时,this将指向window对象, 在严格模式下将返回 undefined
function GetName(){ 
    return this
}
console.log(GetName())
  1. 当函数作为对象方法调用时,函数的执行环境为该对象。对象o会作为隐式的this参数传入函数
function GetName(){ 
    return this.name
}
let o = {
    name:"jack"
}
o.getname = GetName
  1. 当函数作为构造函数调用时,通过new关键字新建空对象,并作为上下文传入构造函数中,this将指该新建对象。
function GetName(name) {
  this.name = name;
  this.getname = function() {
    console.log(this);
  };
}
let man = new GetName("jack");
button.onclick = man.getname;
  1. 有些时候的this指向将由函数所在环境决定,如将对象的方法绑定到button的onclick事件,此时浏览器将this指向了button。
function GetName(name) {
  this.name = name;
  this.getname = function() {
    console.log(this);
  };
}
let man = new GetName("jack");
button.onclick = man.getname;

很显然这不是我们想要的,所以我们需要修正this指向,使用什么方式呢?


下面有请apply、call、bind登场!

apply、call是所有函数都拥有的方法,apply将接收我们想指向的this(也就是上面的man对象)以及参数数组(我们没有所以为null)并执行该函数,与apply不同call的参数由参数列表传入。

let man = new GetName("jack");
button.onclick = function{
    man.getname.apply(man,null);
}

有时候我们仅仅想为某函数绑定this,不立即执行,可以使用bind绑定。


使用箭头函数绕过函数上下文

调用箭头函数时,不会隐式传入this 参数,而是从定义时的函数继承上下文!

function Button(){
    this.clicked = false;
    this.click = () => {
        this.clicked = true;
    };
}
var button = new Button();
var elem = document.getElementById("test");
elem.addEventListener("click", button.click);

所以在创建实例时,箭头函数被创建,其中的this 指向了新创建的对象(button)。

如果使用字面量定义呢?

var button = {
    clicked: false,
    click: () => {
    this.clicked = true;
    }
}

由于click 箭头函数是作为对象字面量的属性定义的,对象字面量在全局代码中定义,因此,箭头函数内部this值与全局代码的this 值相同(指向window对象)。